diff options
author | Adrian Bunk <bunk@kernel.org> | 2008-03-30 18:40:17 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-05-08 06:51:39 -0400 |
commit | f5f826c685464301e4316a9321eb95801c653158 (patch) | |
tree | 44ca0475e4894edde26f5e16de0e311a9ef3c927 /arch/sh/boards | |
parent | 2a6b8148c050941dd61779cb0b49c5c3ea854ebf (diff) |
sh: remove the broken SH_MPC1211 support
SH_MPC1211 has been marked as BROKEN for some time.
Unless someone is working on reviving it now, I'd therefore suggest this
patch to remove it.
Signed-off-by: Adrian Bunk <bunk@kernel.org>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/boards')
-rw-r--r-- | arch/sh/boards/mpc1211/Makefile | 8 | ||||
-rw-r--r-- | arch/sh/boards/mpc1211/pci.c | 295 | ||||
-rw-r--r-- | arch/sh/boards/mpc1211/rtc.c | 136 | ||||
-rw-r--r-- | arch/sh/boards/mpc1211/setup.c | 347 |
4 files changed, 0 insertions, 786 deletions
diff --git a/arch/sh/boards/mpc1211/Makefile b/arch/sh/boards/mpc1211/Makefile deleted file mode 100644 index 8cd31b5d200b..000000000000 --- a/arch/sh/boards/mpc1211/Makefile +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel | ||
3 | # | ||
4 | |||
5 | obj-y := setup.o rtc.o | ||
6 | |||
7 | obj-$(CONFIG_PCI) += pci.o | ||
8 | |||
diff --git a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c deleted file mode 100644 index 23849f70f133..000000000000 --- a/arch/sh/boards/mpc1211/pci.c +++ /dev/null | |||
@@ -1,295 +0,0 @@ | |||
1 | /* | ||
2 | * Low-Level PCI Support for the MPC-1211(CTP/PCI/MPC-SH02) | ||
3 | * | ||
4 | * (c) 2002-2003 Saito.K & Jeanne | ||
5 | * | ||
6 | * Dustin McIntire (dustin@sensoria.com) | ||
7 | * Derived from arch/i386/kernel/pci-*.c which bore the message: | ||
8 | * (c) 1999--2000 Martin Mares <mj@ucw.cz> | ||
9 | * | ||
10 | * May be copied or modified under the terms of the GNU General Public | ||
11 | * License. See linux/COPYING for more information. | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/ioport.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include <asm/machvec.h> | ||
26 | #include <asm/io.h> | ||
27 | #include <asm/mpc1211/pci.h> | ||
28 | |||
29 | static struct resource mpcpci_io_resource = { | ||
30 | "MPCPCI IO", | ||
31 | 0x00000000, | ||
32 | 0xffffffff, | ||
33 | IORESOURCE_IO | ||
34 | }; | ||
35 | |||
36 | static struct resource mpcpci_mem_resource = { | ||
37 | "MPCPCI mem", | ||
38 | 0x00000000, | ||
39 | 0xffffffff, | ||
40 | IORESOURCE_MEM | ||
41 | }; | ||
42 | |||
43 | static struct pci_ops pci_direct_conf1; | ||
44 | struct pci_channel board_pci_channels[] = { | ||
45 | {&pci_direct_conf1, &mpcpci_io_resource, &mpcpci_mem_resource, 0, 256}, | ||
46 | {NULL, NULL, NULL, 0, 0}, | ||
47 | }; | ||
48 | |||
49 | /* | ||
50 | * Direct access to PCI hardware... | ||
51 | */ | ||
52 | |||
53 | |||
54 | #define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3)) | ||
55 | |||
56 | /* | ||
57 | * Functions for accessing PCI configuration space with type 1 accesses | ||
58 | */ | ||
59 | static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) | ||
60 | { | ||
61 | u32 word; | ||
62 | unsigned long flags; | ||
63 | |||
64 | /* | ||
65 | * PCIPDR may only be accessed as 32 bit words, | ||
66 | * so we must do byte alignment by hand | ||
67 | */ | ||
68 | local_irq_save(flags); | ||
69 | writel(CONFIG_CMD(bus,devfn,where), PCIPAR); | ||
70 | word = readl(PCIPDR); | ||
71 | local_irq_restore(flags); | ||
72 | |||
73 | switch (size) { | ||
74 | case 1: | ||
75 | switch (where & 0x3) { | ||
76 | case 3: | ||
77 | *value = (u8)(word >> 24); | ||
78 | break; | ||
79 | case 2: | ||
80 | *value = (u8)(word >> 16); | ||
81 | break; | ||
82 | case 1: | ||
83 | *value = (u8)(word >> 8); | ||
84 | break; | ||
85 | default: | ||
86 | *value = (u8)word; | ||
87 | break; | ||
88 | } | ||
89 | break; | ||
90 | case 2: | ||
91 | switch (where & 0x3) { | ||
92 | case 3: | ||
93 | *value = (u16)(word >> 24); | ||
94 | local_irq_save(flags); | ||
95 | writel(CONFIG_CMD(bus,devfn,(where+1)), PCIPAR); | ||
96 | word = readl(PCIPDR); | ||
97 | local_irq_restore(flags); | ||
98 | *value |= ((word & 0xff) << 8); | ||
99 | break; | ||
100 | case 2: | ||
101 | *value = (u16)(word >> 16); | ||
102 | break; | ||
103 | case 1: | ||
104 | *value = (u16)(word >> 8); | ||
105 | break; | ||
106 | default: | ||
107 | *value = (u16)word; | ||
108 | break; | ||
109 | } | ||
110 | break; | ||
111 | case 4: | ||
112 | *value = word; | ||
113 | break; | ||
114 | } | ||
115 | PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value); | ||
116 | return PCIBIOS_SUCCESSFUL; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Since MPC-1211 only does 32bit access we'll have to do a read,mask,write operation. | ||
121 | * We'll allow an odd byte offset, though it should be illegal. | ||
122 | */ | ||
123 | static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) | ||
124 | { | ||
125 | u32 word,mask = 0; | ||
126 | unsigned long flags; | ||
127 | u32 shift = (where & 3) * 8; | ||
128 | |||
129 | if(size == 1) { | ||
130 | mask = ((1 << 8) - 1) << shift; // create the byte mask | ||
131 | } else if(size == 2){ | ||
132 | if(shift == 24) | ||
133 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
134 | mask = ((1 << 16) - 1) << shift; // create the word mask | ||
135 | } | ||
136 | local_irq_save(flags); | ||
137 | writel(CONFIG_CMD(bus,devfn,where), PCIPAR); | ||
138 | if(size == 4){ | ||
139 | writel(value, PCIPDR); | ||
140 | local_irq_restore(flags); | ||
141 | PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value); | ||
142 | return PCIBIOS_SUCCESSFUL; | ||
143 | } | ||
144 | word = readl(PCIPDR); | ||
145 | word &= ~mask; | ||
146 | word |= ((value << shift) & mask); | ||
147 | writel(word, PCIPDR); | ||
148 | local_irq_restore(flags); | ||
149 | PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word); | ||
150 | return PCIBIOS_SUCCESSFUL; | ||
151 | } | ||
152 | |||
153 | #undef CONFIG_CMD | ||
154 | |||
155 | static struct pci_ops pci_direct_conf1 = { | ||
156 | .read = pci_conf1_read, | ||
157 | .write = pci_conf1_write, | ||
158 | }; | ||
159 | |||
160 | static void __devinit quirk_ali_ide_ports(struct pci_dev *dev) | ||
161 | { | ||
162 | dev->resource[0].start = 0x1f0; | ||
163 | dev->resource[0].end = 0x1f7; | ||
164 | dev->resource[0].flags = IORESOURCE_IO; | ||
165 | dev->resource[1].start = 0x3f6; | ||
166 | dev->resource[1].end = 0x3f6; | ||
167 | dev->resource[1].flags = IORESOURCE_IO; | ||
168 | dev->resource[2].start = 0x170; | ||
169 | dev->resource[2].end = 0x177; | ||
170 | dev->resource[2].flags = IORESOURCE_IO; | ||
171 | dev->resource[3].start = 0x376; | ||
172 | dev->resource[3].end = 0x376; | ||
173 | dev->resource[3].flags = IORESOURCE_IO; | ||
174 | dev->resource[4].start = 0xf000; | ||
175 | dev->resource[4].end = 0xf00f; | ||
176 | dev->resource[4].flags = IORESOURCE_IO; | ||
177 | } | ||
178 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports); | ||
179 | |||
180 | char * __devinit pcibios_setup(char *str) | ||
181 | { | ||
182 | return str; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Called after each bus is probed, but before its children | ||
187 | * are examined. | ||
188 | */ | ||
189 | |||
190 | void __devinit pcibios_fixup_bus(struct pci_bus *b) | ||
191 | { | ||
192 | pci_read_bridge_bases(b); | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * IRQ functions | ||
197 | */ | ||
198 | static inline u8 bridge_swizzle(u8 pin, u8 slot) | ||
199 | { | ||
200 | return (((pin-1) + slot) % 4) + 1; | ||
201 | } | ||
202 | |||
203 | static inline u8 bridge_swizzle_pci_1(u8 pin, u8 slot) | ||
204 | { | ||
205 | return (((pin-1) - slot) & 3) + 1; | ||
206 | } | ||
207 | |||
208 | static u8 __init mpc1211_swizzle(struct pci_dev *dev, u8 *pinp) | ||
209 | { | ||
210 | unsigned long flags; | ||
211 | u8 pin = *pinp; | ||
212 | u32 word; | ||
213 | |||
214 | for ( ; dev->bus->self; dev = dev->bus->self) { | ||
215 | if (!pin) | ||
216 | continue; | ||
217 | |||
218 | if (dev->bus->number == 1) { | ||
219 | local_irq_save(flags); | ||
220 | writel(0x80000000 | 0x2c, PCIPAR); | ||
221 | word = readl(PCIPDR); | ||
222 | local_irq_restore(flags); | ||
223 | word >>= 16; | ||
224 | |||
225 | if (word == 0x0001) | ||
226 | pin = bridge_swizzle_pci_1(pin, PCI_SLOT(dev->devfn)); | ||
227 | else | ||
228 | pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); | ||
229 | } else | ||
230 | pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); | ||
231 | } | ||
232 | |||
233 | *pinp = pin; | ||
234 | |||
235 | return PCI_SLOT(dev->devfn); | ||
236 | } | ||
237 | |||
238 | static int __init map_mpc1211_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
239 | { | ||
240 | int irq = -1; | ||
241 | |||
242 | /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ | ||
243 | if (dev->bus->number == 0) { | ||
244 | switch (slot) { | ||
245 | case 13: irq = 9; break; /* USB */ | ||
246 | case 22: irq = 10; break; /* LAN */ | ||
247 | default: irq = 0; break; | ||
248 | } | ||
249 | } else { | ||
250 | switch (pin) { | ||
251 | case 0: irq = 0; break; | ||
252 | case 1: irq = 7; break; | ||
253 | case 2: irq = 9; break; | ||
254 | case 3: irq = 10; break; | ||
255 | case 4: irq = 11; break; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | if( irq < 0 ) { | ||
260 | PCIDBG(3, "PCI: Error mapping IRQ on device %s\n", pci_name(dev)); | ||
261 | return irq; | ||
262 | } | ||
263 | |||
264 | PCIDBG(2, "Setting IRQ for slot %s to %d\n", pci_name(dev), irq); | ||
265 | |||
266 | return irq; | ||
267 | } | ||
268 | |||
269 | void __init pcibios_fixup_irqs(void) | ||
270 | { | ||
271 | pci_fixup_irqs(mpc1211_swizzle, map_mpc1211_irq); | ||
272 | } | ||
273 | |||
274 | void pcibios_align_resource(void *data, struct resource *res, | ||
275 | resource_size_t size, resource_size_t align) | ||
276 | { | ||
277 | resource_size_t start = res->start; | ||
278 | |||
279 | if (res->flags & IORESOURCE_IO) { | ||
280 | if (start >= 0x10000UL) { | ||
281 | if ((start & 0xffffUL) < 0x4000UL) { | ||
282 | start = (start & 0xffff0000UL) + 0x4000UL; | ||
283 | } else if ((start & 0xffffUL) >= 0xf000UL) { | ||
284 | start = (start & 0xffff0000UL) + 0x10000UL; | ||
285 | } | ||
286 | res->start = start; | ||
287 | } else { | ||
288 | if (start & 0x300) { | ||
289 | start = (start + 0x3ff) & ~0x3ff; | ||
290 | res->start = start; | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c deleted file mode 100644 index 03b123a4bba4..000000000000 --- a/arch/sh/boards/mpc1211/rtc.c +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/sh/kernel/rtc-mpc1211.c -- MPC-1211 on-chip RTC support | ||
3 | * | ||
4 | * Copyright (C) 2002 Saito.K & Jeanne | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/init.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/time.h> | ||
12 | #include <linux/bcd.h> | ||
13 | #include <linux/mc146818rtc.h> | ||
14 | |||
15 | unsigned long get_cmos_time(void) | ||
16 | { | ||
17 | unsigned int year, mon, day, hour, min, sec; | ||
18 | |||
19 | spin_lock(&rtc_lock); | ||
20 | |||
21 | do { | ||
22 | sec = CMOS_READ(RTC_SECONDS); | ||
23 | min = CMOS_READ(RTC_MINUTES); | ||
24 | hour = CMOS_READ(RTC_HOURS); | ||
25 | day = CMOS_READ(RTC_DAY_OF_MONTH); | ||
26 | mon = CMOS_READ(RTC_MONTH); | ||
27 | year = CMOS_READ(RTC_YEAR); | ||
28 | } while (sec != CMOS_READ(RTC_SECONDS)); | ||
29 | |||
30 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
31 | BCD_TO_BIN(sec); | ||
32 | BCD_TO_BIN(min); | ||
33 | BCD_TO_BIN(hour); | ||
34 | BCD_TO_BIN(day); | ||
35 | BCD_TO_BIN(mon); | ||
36 | BCD_TO_BIN(year); | ||
37 | } | ||
38 | |||
39 | spin_unlock(&rtc_lock); | ||
40 | |||
41 | year += 1900; | ||
42 | if (year < 1970) | ||
43 | year += 100; | ||
44 | |||
45 | return mktime(year, mon, day, hour, min, sec); | ||
46 | } | ||
47 | |||
48 | void mpc1211_rtc_gettimeofday(struct timeval *tv) | ||
49 | { | ||
50 | |||
51 | tv->tv_sec = get_cmos_time(); | ||
52 | tv->tv_usec = 0; | ||
53 | } | ||
54 | |||
55 | /* arc/i386/kernel/time.c */ | ||
56 | /* | ||
57 | * In order to set the CMOS clock precisely, set_rtc_mmss has to be | ||
58 | * called 500 ms after the second nowtime has started, because when | ||
59 | * nowtime is written into the registers of the CMOS clock, it will | ||
60 | * jump to the next second precisely 500 ms later. Check the Motorola | ||
61 | * MC146818A or Dallas DS12887 data sheet for details. | ||
62 | * | ||
63 | * BUG: This routine does not handle hour overflow properly; it just | ||
64 | * sets the minutes. Usually you'll only notice that after reboot! | ||
65 | */ | ||
66 | static int set_rtc_mmss(unsigned long nowtime) | ||
67 | { | ||
68 | int retval = 0; | ||
69 | int real_seconds, real_minutes, cmos_minutes; | ||
70 | unsigned char save_control, save_freq_select; | ||
71 | |||
72 | /* gets recalled with irq locally disabled */ | ||
73 | spin_lock(&rtc_lock); | ||
74 | save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ | ||
75 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | ||
76 | |||
77 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ | ||
78 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
79 | |||
80 | cmos_minutes = CMOS_READ(RTC_MINUTES); | ||
81 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | ||
82 | BCD_TO_BIN(cmos_minutes); | ||
83 | |||
84 | /* | ||
85 | * since we're only adjusting minutes and seconds, | ||
86 | * don't interfere with hour overflow. This avoids | ||
87 | * messing with unknown time zones but requires your | ||
88 | * RTC not to be off by more than 15 minutes | ||
89 | */ | ||
90 | real_seconds = nowtime % 60; | ||
91 | real_minutes = nowtime / 60; | ||
92 | if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) | ||
93 | real_minutes += 30; /* correct for half hour time zone */ | ||
94 | real_minutes %= 60; | ||
95 | |||
96 | if (abs(real_minutes - cmos_minutes) < 30) { | ||
97 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
98 | BIN_TO_BCD(real_seconds); | ||
99 | BIN_TO_BCD(real_minutes); | ||
100 | } | ||
101 | CMOS_WRITE(real_seconds,RTC_SECONDS); | ||
102 | CMOS_WRITE(real_minutes,RTC_MINUTES); | ||
103 | } else { | ||
104 | printk(KERN_WARNING | ||
105 | "set_rtc_mmss: can't update from %d to %d\n", | ||
106 | cmos_minutes, real_minutes); | ||
107 | retval = -1; | ||
108 | } | ||
109 | |||
110 | /* The following flags have to be released exactly in this order, | ||
111 | * otherwise the DS12887 (popular MC146818A clone with integrated | ||
112 | * battery and quartz) will not reset the oscillator and will not | ||
113 | * update precisely 500 ms later. You won't find this mentioned in | ||
114 | * the Dallas Semiconductor data sheets, but who believes data | ||
115 | * sheets anyway ... -- Markus Kuhn | ||
116 | */ | ||
117 | CMOS_WRITE(save_control, RTC_CONTROL); | ||
118 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | ||
119 | spin_unlock(&rtc_lock); | ||
120 | |||
121 | return retval; | ||
122 | } | ||
123 | |||
124 | int mpc1211_rtc_settimeofday(const struct timeval *tv) | ||
125 | { | ||
126 | unsigned long nowtime = tv->tv_sec; | ||
127 | |||
128 | return set_rtc_mmss(nowtime); | ||
129 | } | ||
130 | |||
131 | void mpc1211_time_init(void) | ||
132 | { | ||
133 | rtc_sh_get_time = mpc1211_rtc_gettimeofday; | ||
134 | rtc_sh_set_time = mpc1211_rtc_settimeofday; | ||
135 | } | ||
136 | |||
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c deleted file mode 100644 index fede36361dc7..000000000000 --- a/arch/sh/boards/mpc1211/setup.c +++ /dev/null | |||
@@ -1,347 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/sh/boards/mpc1211/setup.c | ||
3 | * | ||
4 | * Copyright (C) 2002 Saito.K & Jeanne, Fujii.Y | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/init.h> | ||
9 | #include <linux/irq.h> | ||
10 | #include <linux/hdreg.h> | ||
11 | #include <linux/ide.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <asm/io.h> | ||
15 | #include <asm/machvec.h> | ||
16 | #include <asm/mpc1211/mpc1211.h> | ||
17 | #include <asm/mpc1211/pci.h> | ||
18 | #include <asm/mpc1211/m1543c.h> | ||
19 | |||
20 | /* ALI15X3 SMBus address offsets */ | ||
21 | #define SMBHSTSTS (0 + 0x3100) | ||
22 | #define SMBHSTCNT (1 + 0x3100) | ||
23 | #define SMBHSTSTART (2 + 0x3100) | ||
24 | #define SMBHSTCMD (7 + 0x3100) | ||
25 | #define SMBHSTADD (3 + 0x3100) | ||
26 | #define SMBHSTDAT0 (4 + 0x3100) | ||
27 | #define SMBHSTDAT1 (5 + 0x3100) | ||
28 | #define SMBBLKDAT (6 + 0x3100) | ||
29 | |||
30 | /* Other settings */ | ||
31 | #define MAX_TIMEOUT 500 /* times 1/100 sec */ | ||
32 | |||
33 | /* ALI15X3 command constants */ | ||
34 | #define ALI15X3_ABORT 0x04 | ||
35 | #define ALI15X3_T_OUT 0x08 | ||
36 | #define ALI15X3_QUICK 0x00 | ||
37 | #define ALI15X3_BYTE 0x10 | ||
38 | #define ALI15X3_BYTE_DATA 0x20 | ||
39 | #define ALI15X3_WORD_DATA 0x30 | ||
40 | #define ALI15X3_BLOCK_DATA 0x40 | ||
41 | #define ALI15X3_BLOCK_CLR 0x80 | ||
42 | |||
43 | /* ALI15X3 status register bits */ | ||
44 | #define ALI15X3_STS_IDLE 0x04 | ||
45 | #define ALI15X3_STS_BUSY 0x08 | ||
46 | #define ALI15X3_STS_DONE 0x10 | ||
47 | #define ALI15X3_STS_DEV 0x20 /* device error */ | ||
48 | #define ALI15X3_STS_COLL 0x40 /* collision or no response */ | ||
49 | #define ALI15X3_STS_TERM 0x80 /* terminated by abort */ | ||
50 | #define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ | ||
51 | |||
52 | static void __init pci_write_config(unsigned long busNo, | ||
53 | unsigned long devNo, | ||
54 | unsigned long fncNo, | ||
55 | unsigned long cnfAdd, | ||
56 | unsigned long cnfData) | ||
57 | { | ||
58 | ctrl_outl((0x80000000 | ||
59 | + ((busNo & 0xff) << 16) | ||
60 | + ((devNo & 0x1f) << 11) | ||
61 | + ((fncNo & 0x07) << 8) | ||
62 | + (cnfAdd & 0xfc)), PCIPAR); | ||
63 | |||
64 | ctrl_outl(cnfData, PCIPDR); | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | Initialize IRQ setting | ||
69 | */ | ||
70 | |||
71 | static unsigned char m_irq_mask = 0xfb; | ||
72 | static unsigned char s_irq_mask = 0xff; | ||
73 | |||
74 | static void disable_mpc1211_irq(unsigned int irq) | ||
75 | { | ||
76 | if( irq < 8) { | ||
77 | m_irq_mask |= (1 << irq); | ||
78 | outb(m_irq_mask,I8259_M_MR); | ||
79 | } else { | ||
80 | s_irq_mask |= (1 << (irq - 8)); | ||
81 | outb(s_irq_mask,I8259_S_MR); | ||
82 | } | ||
83 | |||
84 | } | ||
85 | |||
86 | static void enable_mpc1211_irq(unsigned int irq) | ||
87 | { | ||
88 | if( irq < 8) { | ||
89 | m_irq_mask &= ~(1 << irq); | ||
90 | outb(m_irq_mask,I8259_M_MR); | ||
91 | } else { | ||
92 | s_irq_mask &= ~(1 << (irq - 8)); | ||
93 | outb(s_irq_mask,I8259_S_MR); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static inline int mpc1211_irq_real(unsigned int irq) | ||
98 | { | ||
99 | int value; | ||
100 | int irqmask; | ||
101 | |||
102 | if ( irq < 8) { | ||
103 | irqmask = 1<<irq; | ||
104 | outb(0x0b,I8259_M_CR); /* ISR register */ | ||
105 | value = inb(I8259_M_CR) & irqmask; | ||
106 | outb(0x0a,I8259_M_CR); /* back ro the IPR reg */ | ||
107 | return value; | ||
108 | } | ||
109 | irqmask = 1<<(irq - 8); | ||
110 | outb(0x0b,I8259_S_CR); /* ISR register */ | ||
111 | value = inb(I8259_S_CR) & irqmask; | ||
112 | outb(0x0a,I8259_S_CR); /* back ro the IPR reg */ | ||
113 | return value; | ||
114 | } | ||
115 | |||
116 | static void mask_and_ack_mpc1211(unsigned int irq) | ||
117 | { | ||
118 | if(irq < 8) { | ||
119 | if(m_irq_mask & (1<<irq)){ | ||
120 | if(!mpc1211_irq_real(irq)){ | ||
121 | atomic_inc(&irq_err_count) | ||
122 | printk("spurious 8259A interrupt: IRQ %x\n",irq); | ||
123 | } | ||
124 | } else { | ||
125 | m_irq_mask |= (1<<irq); | ||
126 | } | ||
127 | inb(I8259_M_MR); /* DUMMY */ | ||
128 | outb(m_irq_mask,I8259_M_MR); /* disable */ | ||
129 | outb(0x60+irq,I8259_M_CR); /* EOI */ | ||
130 | |||
131 | } else { | ||
132 | if(s_irq_mask & (1<<(irq - 8))){ | ||
133 | if(!mpc1211_irq_real(irq)){ | ||
134 | atomic_inc(&irq_err_count); | ||
135 | printk("spurious 8259A interrupt: IRQ %x\n",irq); | ||
136 | } | ||
137 | } else { | ||
138 | s_irq_mask |= (1<<(irq - 8)); | ||
139 | } | ||
140 | inb(I8259_S_MR); /* DUMMY */ | ||
141 | outb(s_irq_mask,I8259_S_MR); /* disable */ | ||
142 | outb(0x60+(irq-8),I8259_S_CR); /* EOI */ | ||
143 | outb(0x60+2,I8259_M_CR); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static void end_mpc1211_irq(unsigned int irq) | ||
148 | { | ||
149 | enable_mpc1211_irq(irq); | ||
150 | } | ||
151 | |||
152 | static unsigned int startup_mpc1211_irq(unsigned int irq) | ||
153 | { | ||
154 | enable_mpc1211_irq(irq); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static void shutdown_mpc1211_irq(unsigned int irq) | ||
159 | { | ||
160 | disable_mpc1211_irq(irq); | ||
161 | } | ||
162 | |||
163 | static struct hw_interrupt_type mpc1211_irq_type = { | ||
164 | .typename = "MPC1211-IRQ", | ||
165 | .startup = startup_mpc1211_irq, | ||
166 | .shutdown = shutdown_mpc1211_irq, | ||
167 | .enable = enable_mpc1211_irq, | ||
168 | .disable = disable_mpc1211_irq, | ||
169 | .ack = mask_and_ack_mpc1211, | ||
170 | .end = end_mpc1211_irq | ||
171 | }; | ||
172 | |||
173 | static void make_mpc1211_irq(unsigned int irq) | ||
174 | { | ||
175 | irq_desc[irq].chip = &mpc1211_irq_type; | ||
176 | irq_desc[irq].status = IRQ_DISABLED; | ||
177 | irq_desc[irq].action = 0; | ||
178 | irq_desc[irq].depth = 1; | ||
179 | disable_mpc1211_irq(irq); | ||
180 | } | ||
181 | |||
182 | int mpc1211_irq_demux(int irq) | ||
183 | { | ||
184 | unsigned int poll; | ||
185 | |||
186 | if( irq == 2 ) { | ||
187 | outb(0x0c,I8259_M_CR); | ||
188 | poll = inb(I8259_M_CR); | ||
189 | if(poll & 0x80) { | ||
190 | irq = (poll & 0x07); | ||
191 | } | ||
192 | if( irq == 2) { | ||
193 | outb(0x0c,I8259_S_CR); | ||
194 | poll = inb(I8259_S_CR); | ||
195 | irq = (poll & 0x07) + 8; | ||
196 | } | ||
197 | } | ||
198 | return irq; | ||
199 | } | ||
200 | |||
201 | static void __init init_mpc1211_IRQ(void) | ||
202 | { | ||
203 | int i; | ||
204 | /* | ||
205 | * Super I/O (Just mimic PC): | ||
206 | * 1: keyboard | ||
207 | * 3: serial 1 | ||
208 | * 4: serial 0 | ||
209 | * 5: printer | ||
210 | * 6: floppy | ||
211 | * 8: rtc | ||
212 | * 10: lan | ||
213 | * 12: mouse | ||
214 | * 14: ide0 | ||
215 | * 15: ide1 | ||
216 | */ | ||
217 | |||
218 | pci_write_config(0,0,0,0x54, 0xb0b0002d); | ||
219 | outb(0x11, I8259_M_CR); /* mater icw1 edge trigger */ | ||
220 | outb(0x11, I8259_S_CR); /* slave icw1 edge trigger */ | ||
221 | outb(0x20, I8259_M_MR); /* m icw2 base vec 0x08 */ | ||
222 | outb(0x28, I8259_S_MR); /* s icw2 base vec 0x70 */ | ||
223 | outb(0x04, I8259_M_MR); /* m icw3 slave irq2 */ | ||
224 | outb(0x02, I8259_S_MR); /* s icw3 slave id */ | ||
225 | outb(0x01, I8259_M_MR); /* m icw4 non buf normal eoi*/ | ||
226 | outb(0x01, I8259_S_MR); /* s icw4 non buf normal eo1*/ | ||
227 | outb(0xfb, I8259_M_MR); /* disable irq0--irq7 */ | ||
228 | outb(0xff, I8259_S_MR); /* disable irq8--irq15 */ | ||
229 | |||
230 | for ( i=0; i < 16; i++) { | ||
231 | if(i != 2) { | ||
232 | make_mpc1211_irq(i); | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
237 | static void delay1000(void) | ||
238 | { | ||
239 | int i; | ||
240 | |||
241 | for (i=0; i<1000; i++) | ||
242 | ctrl_delay(); | ||
243 | } | ||
244 | |||
245 | static int put_smb_blk(unsigned char *p, int address, int command, int no) | ||
246 | { | ||
247 | int temp; | ||
248 | int timeout; | ||
249 | int i; | ||
250 | |||
251 | outb(0xff, SMBHSTSTS); | ||
252 | temp = inb(SMBHSTSTS); | ||
253 | for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) { | ||
254 | delay1000(); | ||
255 | temp = inb(SMBHSTSTS); | ||
256 | } | ||
257 | if (timeout >= MAX_TIMEOUT){ | ||
258 | return -1; | ||
259 | } | ||
260 | |||
261 | outb(((address & 0x7f) << 1), SMBHSTADD); | ||
262 | outb(0xc0, SMBHSTCNT); | ||
263 | outb(command & 0xff, SMBHSTCMD); | ||
264 | outb(no & 0x1f, SMBHSTDAT0); | ||
265 | |||
266 | for(i = 1; i <= no; i++) { | ||
267 | outb(*p++, SMBBLKDAT); | ||
268 | } | ||
269 | outb(0xff, SMBHSTSTART); | ||
270 | |||
271 | temp = inb(SMBHSTSTS); | ||
272 | for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) { | ||
273 | delay1000(); | ||
274 | temp = inb(SMBHSTSTS); | ||
275 | } | ||
276 | if (timeout >= MAX_TIMEOUT) { | ||
277 | return -2; | ||
278 | } | ||
279 | if ( temp & ALI15X3_STS_ERR ){ | ||
280 | return -3; | ||
281 | } | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static struct resource heartbeat_resources[] = { | ||
286 | [0] = { | ||
287 | .start = 0xa2000000, | ||
288 | .end = 0xa2000000, | ||
289 | .flags = IORESOURCE_MEM, | ||
290 | }, | ||
291 | }; | ||
292 | |||
293 | static struct platform_device heartbeat_device = { | ||
294 | .name = "heartbeat", | ||
295 | .id = -1, | ||
296 | .num_resources = ARRAY_SIZE(heartbeat_resources), | ||
297 | .resource = heartbeat_resources, | ||
298 | }; | ||
299 | |||
300 | static struct platform_device *mpc1211_devices[] __initdata = { | ||
301 | &heartbeat_device, | ||
302 | }; | ||
303 | |||
304 | static int __init mpc1211_devices_setup(void) | ||
305 | { | ||
306 | return platform_add_devices(mpc1211_devices, | ||
307 | ARRAY_SIZE(mpc1211_devices)); | ||
308 | } | ||
309 | __initcall(mpc1211_devices_setup); | ||
310 | |||
311 | /* arch/sh/boards/mpc1211/rtc.c */ | ||
312 | void mpc1211_time_init(void); | ||
313 | |||
314 | static void __init mpc1211_setup(char **cmdline_p) | ||
315 | { | ||
316 | unsigned char spd_buf[128]; | ||
317 | |||
318 | __set_io_port_base(PA_PCI_IO); | ||
319 | |||
320 | pci_write_config(0,0,0,0x54, 0xb0b00000); | ||
321 | |||
322 | do { | ||
323 | outb(ALI15X3_ABORT, SMBHSTCNT); | ||
324 | spd_buf[0] = 0x0c; | ||
325 | spd_buf[1] = 0x43; | ||
326 | spd_buf[2] = 0x7f; | ||
327 | spd_buf[3] = 0x03; | ||
328 | spd_buf[4] = 0x00; | ||
329 | spd_buf[5] = 0x03; | ||
330 | spd_buf[6] = 0x00; | ||
331 | } while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0); | ||
332 | |||
333 | board_time_init = mpc1211_time_init; | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | * The Machine Vector | ||
340 | */ | ||
341 | static struct sh_machine_vector mv_mpc1211 __initmv = { | ||
342 | .mv_name = "Interface MPC-1211(CTP/PCI/MPC-SH02)", | ||
343 | .mv_setup = mpc1211_setup, | ||
344 | .mv_nr_irqs = 48, | ||
345 | .mv_irq_demux = mpc1211_irq_demux, | ||
346 | .mv_init_irq = init_mpc1211_IRQ, | ||
347 | }; | ||