aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/boards/mach-cayman
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2008-07-29 08:01:19 -0400
committerPaul Mundt <lethal@linux-sh.org>2008-07-29 08:01:19 -0400
commitda2014a2b080e7f3024a4eb6917d47069ad9620b (patch)
treecfde12c6d4b5baa222966b14a676f107992cf786 /arch/sh/boards/mach-cayman
parent71b8064e7df5698520d73b4c1566a3dbc98eb9ef (diff)
sh: Shuffle the board directories in to mach groups.
This flattens out the board directories in to individual mach groups, we will use this for getting rid of unneeded directories, simplifying the build system, and becoming more coherent with the refactored arch/sh/include topology. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/boards/mach-cayman')
-rw-r--r--arch/sh/boards/mach-cayman/Makefile5
-rw-r--r--arch/sh/boards/mach-cayman/irq.c197
-rw-r--r--arch/sh/boards/mach-cayman/led.c51
-rw-r--r--arch/sh/boards/mach-cayman/setup.c187
4 files changed, 440 insertions, 0 deletions
diff --git a/arch/sh/boards/mach-cayman/Makefile b/arch/sh/boards/mach-cayman/Makefile
new file mode 100644
index 000000000000..489a8f867368
--- /dev/null
+++ b/arch/sh/boards/mach-cayman/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the Hitachi Cayman specific parts of the kernel
3#
4obj-y := setup.o irq.o
5obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/mach-cayman/irq.c b/arch/sh/boards/mach-cayman/irq.c
new file mode 100644
index 000000000000..ceb37ae92c70
--- /dev/null
+++ b/arch/sh/boards/mach-cayman/irq.c
@@ -0,0 +1,197 @@
1/*
2 * arch/sh/mach-cayman/irq.c - SH-5 Cayman Interrupt Support
3 *
4 * This file handles the board specific parts of the Cayman interrupt system
5 *
6 * Copyright (C) 2002 Stuart Menefy
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/io.h>
13#include <linux/irq.h>
14#include <linux/interrupt.h>
15#include <linux/signal.h>
16#include <cpu/irq.h>
17#include <asm/page.h>
18
19/* Setup for the SMSC FDC37C935 / LAN91C100FD */
20#define SMSC_IRQ IRQ_IRL1
21
22/* Setup for PCI Bus 2, which transmits interrupts via the EPLD */
23#define PCI2_IRQ IRQ_IRL3
24
25unsigned long epld_virt;
26
27#define EPLD_BASE 0x04002000
28#define EPLD_STATUS_BASE (epld_virt + 0x10)
29#define EPLD_MASK_BASE (epld_virt + 0x20)
30
31/* Note the SMSC SuperIO chip and SMSC LAN chip interrupts are all muxed onto
32 the same SH-5 interrupt */
33
34static irqreturn_t cayman_interrupt_smsc(int irq, void *dev_id)
35{
36 printk(KERN_INFO "CAYMAN: spurious SMSC interrupt\n");
37 return IRQ_NONE;
38}
39
40static irqreturn_t cayman_interrupt_pci2(int irq, void *dev_id)
41{
42 printk(KERN_INFO "CAYMAN: spurious PCI interrupt, IRQ %d\n", irq);
43 return IRQ_NONE;
44}
45
46static struct irqaction cayman_action_smsc = {
47 .name = "Cayman SMSC Mux",
48 .handler = cayman_interrupt_smsc,
49 .flags = IRQF_DISABLED,
50};
51
52static struct irqaction cayman_action_pci2 = {
53 .name = "Cayman PCI2 Mux",
54 .handler = cayman_interrupt_pci2,
55 .flags = IRQF_DISABLED,
56};
57
58static void enable_cayman_irq(unsigned int irq)
59{
60 unsigned long flags;
61 unsigned long mask;
62 unsigned int reg;
63 unsigned char bit;
64
65 irq -= START_EXT_IRQS;
66 reg = EPLD_MASK_BASE + ((irq / 8) << 2);
67 bit = 1<<(irq % 8);
68 local_irq_save(flags);
69 mask = ctrl_inl(reg);
70 mask |= bit;
71 ctrl_outl(mask, reg);
72 local_irq_restore(flags);
73}
74
75void disable_cayman_irq(unsigned int irq)
76{
77 unsigned long flags;
78 unsigned long mask;
79 unsigned int reg;
80 unsigned char bit;
81
82 irq -= START_EXT_IRQS;
83 reg = EPLD_MASK_BASE + ((irq / 8) << 2);
84 bit = 1<<(irq % 8);
85 local_irq_save(flags);
86 mask = ctrl_inl(reg);
87 mask &= ~bit;
88 ctrl_outl(mask, reg);
89 local_irq_restore(flags);
90}
91
92static void ack_cayman_irq(unsigned int irq)
93{
94 disable_cayman_irq(irq);
95}
96
97static void end_cayman_irq(unsigned int irq)
98{
99 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
100 enable_cayman_irq(irq);
101}
102
103static unsigned int startup_cayman_irq(unsigned int irq)
104{
105 enable_cayman_irq(irq);
106 return 0; /* never anything pending */
107}
108
109static void shutdown_cayman_irq(unsigned int irq)
110{
111 disable_cayman_irq(irq);
112}
113
114struct hw_interrupt_type cayman_irq_type = {
115 .typename = "Cayman-IRQ",
116 .startup = startup_cayman_irq,
117 .shutdown = shutdown_cayman_irq,
118 .enable = enable_cayman_irq,
119 .disable = disable_cayman_irq,
120 .ack = ack_cayman_irq,
121 .end = end_cayman_irq,
122};
123
124int cayman_irq_demux(int evt)
125{
126 int irq = intc_evt_to_irq[evt];
127
128 if (irq == SMSC_IRQ) {
129 unsigned long status;
130 int i;
131
132 status = ctrl_inl(EPLD_STATUS_BASE) &
133 ctrl_inl(EPLD_MASK_BASE) & 0xff;
134 if (status == 0) {
135 irq = -1;
136 } else {
137 for (i=0; i<8; i++) {
138 if (status & (1<<i))
139 break;
140 }
141 irq = START_EXT_IRQS + i;
142 }
143 }
144
145 if (irq == PCI2_IRQ) {
146 unsigned long status;
147 int i;
148
149 status = ctrl_inl(EPLD_STATUS_BASE + 3 * sizeof(u32)) &
150 ctrl_inl(EPLD_MASK_BASE + 3 * sizeof(u32)) & 0xff;
151 if (status == 0) {
152 irq = -1;
153 } else {
154 for (i=0; i<8; i++) {
155 if (status & (1<<i))
156 break;
157 }
158 irq = START_EXT_IRQS + (3 * 8) + i;
159 }
160 }
161
162 return irq;
163}
164
165#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
166int cayman_irq_describe(char* p, int irq)
167{
168 if (irq < NR_INTC_IRQS) {
169 return intc_irq_describe(p, irq);
170 } else if (irq < NR_INTC_IRQS + 8) {
171 return sprintf(p, "(SMSC %d)", irq - NR_INTC_IRQS);
172 } else if ((irq >= NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32)) {
173 return sprintf(p, "(PCI2 %d)", irq - (NR_INTC_IRQS + 24));
174 }
175
176 return 0;
177}
178#endif
179
180void init_cayman_irq(void)
181{
182 int i;
183
184 epld_virt = onchip_remap(EPLD_BASE, 1024, "EPLD");
185 if (!epld_virt) {
186 printk(KERN_ERR "Cayman IRQ: Unable to remap EPLD\n");
187 return;
188 }
189
190 for (i=0; i<NR_EXT_IRQS; i++) {
191 irq_desc[START_EXT_IRQS + i].chip = &cayman_irq_type;
192 }
193
194 /* Setup the SMSC interrupt */
195 setup_irq(SMSC_IRQ, &cayman_action_smsc);
196 setup_irq(PCI2_IRQ, &cayman_action_pci2);
197}
diff --git a/arch/sh/boards/mach-cayman/led.c b/arch/sh/boards/mach-cayman/led.c
new file mode 100644
index 000000000000..a808eac4ecd6
--- /dev/null
+++ b/arch/sh/boards/mach-cayman/led.c
@@ -0,0 +1,51 @@
1/*
2 * arch/sh/boards/cayman/led.c
3 *
4 * Copyright (C) 2002 Stuart Menefy <stuart.menefy@st.com>
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Flash the LEDs
10 */
11#include <asm/io.h>
12
13/*
14** It is supposed these functions to be used for a low level
15** debugging (via Cayman LEDs), hence to be available as soon
16** as possible.
17** Unfortunately Cayman LEDs relies on Cayman EPLD to be mapped
18** (this happen when IRQ are initialized... quite late).
19** These triky dependencies should be removed. Temporary, it
20** may be enough to NOP until EPLD is mapped.
21*/
22
23extern unsigned long epld_virt;
24
25#define LED_ADDR (epld_virt + 0x008)
26#define HDSP2534_ADDR (epld_virt + 0x100)
27
28void mach_led(int position, int value)
29{
30 if (!epld_virt)
31 return;
32
33 if (value)
34 ctrl_outl(0, LED_ADDR);
35 else
36 ctrl_outl(1, LED_ADDR);
37
38}
39
40void mach_alphanum(int position, unsigned char value)
41{
42 if (!epld_virt)
43 return;
44
45 ctrl_outb(value, HDSP2534_ADDR + 0xe0 + (position << 2));
46}
47
48void mach_alphanum_brightness(int setting)
49{
50 ctrl_outb(setting & 7, HDSP2534_ADDR + 0xc0);
51}
diff --git a/arch/sh/boards/mach-cayman/setup.c b/arch/sh/boards/mach-cayman/setup.c
new file mode 100644
index 000000000000..e7f9cc5f2ff1
--- /dev/null
+++ b/arch/sh/boards/mach-cayman/setup.c
@@ -0,0 +1,187 @@
1/*
2 * arch/sh/mach-cayman/setup.c
3 *
4 * SH5 Cayman support
5 *
6 * Copyright (C) 2002 David J. Mckay & Benedict Gaster
7 * Copyright (C) 2003 - 2007 Paul Mundt
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/kernel.h>
16#include <cpu/irq.h>
17
18/*
19 * Platform Dependent Interrupt Priorities.
20 */
21
22/* Using defaults defined in irq.h */
23#define RES NO_PRIORITY /* Disabled */
24#define IR0 IRL0_PRIORITY /* IRLs */
25#define IR1 IRL1_PRIORITY
26#define IR2 IRL2_PRIORITY
27#define IR3 IRL3_PRIORITY
28#define PCA INTA_PRIORITY /* PCI Ints */
29#define PCB INTB_PRIORITY
30#define PCC INTC_PRIORITY
31#define PCD INTD_PRIORITY
32#define SER TOP_PRIORITY
33#define ERR TOP_PRIORITY
34#define PW0 TOP_PRIORITY
35#define PW1 TOP_PRIORITY
36#define PW2 TOP_PRIORITY
37#define PW3 TOP_PRIORITY
38#define DM0 NO_PRIORITY /* DMA Ints */
39#define DM1 NO_PRIORITY
40#define DM2 NO_PRIORITY
41#define DM3 NO_PRIORITY
42#define DAE NO_PRIORITY
43#define TU0 TIMER_PRIORITY /* TMU Ints */
44#define TU1 NO_PRIORITY
45#define TU2 NO_PRIORITY
46#define TI2 NO_PRIORITY
47#define ATI NO_PRIORITY /* RTC Ints */
48#define PRI NO_PRIORITY
49#define CUI RTC_PRIORITY
50#define ERI SCIF_PRIORITY /* SCIF Ints */
51#define RXI SCIF_PRIORITY
52#define BRI SCIF_PRIORITY
53#define TXI SCIF_PRIORITY
54#define ITI TOP_PRIORITY /* WDT Ints */
55
56/* Setup for the SMSC FDC37C935 */
57#define SMSC_SUPERIO_BASE 0x04000000
58#define SMSC_CONFIG_PORT_ADDR 0x3f0
59#define SMSC_INDEX_PORT_ADDR SMSC_CONFIG_PORT_ADDR
60#define SMSC_DATA_PORT_ADDR 0x3f1
61
62#define SMSC_ENTER_CONFIG_KEY 0x55
63#define SMSC_EXIT_CONFIG_KEY 0xaa
64
65#define SMCS_LOGICAL_DEV_INDEX 0x07
66#define SMSC_DEVICE_ID_INDEX 0x20
67#define SMSC_DEVICE_REV_INDEX 0x21
68#define SMSC_ACTIVATE_INDEX 0x30
69#define SMSC_PRIMARY_BASE_INDEX 0x60
70#define SMSC_SECONDARY_BASE_INDEX 0x62
71#define SMSC_PRIMARY_INT_INDEX 0x70
72#define SMSC_SECONDARY_INT_INDEX 0x72
73
74#define SMSC_IDE1_DEVICE 1
75#define SMSC_KEYBOARD_DEVICE 7
76#define SMSC_CONFIG_REGISTERS 8
77
78#define SMSC_SUPERIO_READ_INDEXED(index) ({ \
79 outb((index), SMSC_INDEX_PORT_ADDR); \
80 inb(SMSC_DATA_PORT_ADDR); })
81#define SMSC_SUPERIO_WRITE_INDEXED(val, index) ({ \
82 outb((index), SMSC_INDEX_PORT_ADDR); \
83 outb((val), SMSC_DATA_PORT_ADDR); })
84
85#define IDE1_PRIMARY_BASE 0x01f0
86#define IDE1_SECONDARY_BASE 0x03f6
87
88unsigned long smsc_superio_virt;
89
90int platform_int_priority[NR_INTC_IRQS] = {
91 IR0, IR1, IR2, IR3, PCA, PCB, PCC, PCD, /* IRQ 0- 7 */
92 RES, RES, RES, RES, SER, ERR, PW3, PW2, /* IRQ 8-15 */
93 PW1, PW0, DM0, DM1, DM2, DM3, DAE, RES, /* IRQ 16-23 */
94 RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 24-31 */
95 TU0, TU1, TU2, TI2, ATI, PRI, CUI, ERI, /* IRQ 32-39 */
96 RXI, BRI, TXI, RES, RES, RES, RES, RES, /* IRQ 40-47 */
97 RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 48-55 */
98 RES, RES, RES, RES, RES, RES, RES, ITI, /* IRQ 56-63 */
99};
100
101static int __init smsc_superio_setup(void)
102{
103 unsigned char devid, devrev;
104
105 smsc_superio_virt = onchip_remap(SMSC_SUPERIO_BASE, 1024, "SMSC SuperIO");
106 if (!smsc_superio_virt) {
107 panic("Unable to remap SMSC SuperIO\n");
108 }
109
110 /* Initially the chip is in run state */
111 /* Put it into configuration state */
112 outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
113 outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
114
115 /* Read device ID info */
116 devid = SMSC_SUPERIO_READ_INDEXED(SMSC_DEVICE_ID_INDEX);
117 devrev = SMSC_SUPERIO_READ_INDEXED(SMSC_DEVICE_REV_INDEX);
118 printk("SMSC SuperIO devid %02x rev %02x\n", devid, devrev);
119
120 /* Select the keyboard device */
121 SMSC_SUPERIO_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX);
122
123 /* enable it */
124 SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
125
126 /* Select the interrupts */
127 /* On a PC keyboard is IRQ1, mouse is IRQ12 */
128 SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_PRIMARY_INT_INDEX);
129 SMSC_SUPERIO_WRITE_INDEXED(12, SMSC_SECONDARY_INT_INDEX);
130
131#ifdef CONFIG_IDE
132 /*
133 * Only IDE1 exists on the Cayman
134 */
135
136 /* Power it on */
137 SMSC_SUPERIO_WRITE_INDEXED(1 << SMSC_IDE1_DEVICE, 0x22);
138
139 SMSC_SUPERIO_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
140 SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
141
142 SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE >> 8,
143 SMSC_PRIMARY_BASE_INDEX + 0);
144 SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE & 0xff,
145 SMSC_PRIMARY_BASE_INDEX + 1);
146
147 SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE >> 8,
148 SMSC_SECONDARY_BASE_INDEX + 0);
149 SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE & 0xff,
150 SMSC_SECONDARY_BASE_INDEX + 1);
151
152 SMSC_SUPERIO_WRITE_INDEXED(14, SMSC_PRIMARY_INT_INDEX);
153
154 SMSC_SUPERIO_WRITE_INDEXED(SMSC_CONFIG_REGISTERS,
155 SMCS_LOGICAL_DEV_INDEX);
156
157 SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc2); /* GP42 = nIDE1_OE */
158 SMSC_SUPERIO_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */
159 SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */
160 SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */
161#endif
162
163 /* Exit the configuration state */
164 outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
165
166 return 0;
167}
168__initcall(smsc_superio_setup);
169
170static void __iomem *cayman_ioport_map(unsigned long port, unsigned int len)
171{
172 if (port < 0x400) {
173 extern unsigned long smsc_superio_virt;
174 return (void __iomem *)((port << 2) | smsc_superio_virt);
175 }
176
177 return (void __iomem *)port;
178}
179
180extern void init_cayman_irq(void);
181
182static struct sh_machine_vector mv_cayman __initmv = {
183 .mv_name = "Hitachi Cayman",
184 .mv_nr_irqs = 64,
185 .mv_ioport_map = cayman_ioport_map,
186 .mv_init_irq = init_cayman_irq,
187};