aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/boards/mpc1211/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/boards/mpc1211/setup.c')
-rw-r--r--arch/sh/boards/mpc1211/setup.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
new file mode 100644
index 000000000000..2bb581b91683
--- /dev/null
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -0,0 +1,360 @@
1/*
2 * linux/arch/sh/board/mpc1211/setup.c
3 *
4 * Copyright (C) 2002 Saito.K & Jeanne, Fujii.Y
5 *
6 */
7
8#include <linux/config.h>
9#include <linux/init.h>
10#include <linux/irq.h>
11#include <linux/hdreg.h>
12#include <linux/ide.h>
13#include <linux/interrupt.h>
14
15#include <asm/io.h>
16#include <asm/machvec.h>
17#include <asm/mpc1211/mpc1211.h>
18#include <asm/mpc1211/pci.h>
19#include <asm/mpc1211/m1543c.h>
20
21
22/* ALI15X3 SMBus address offsets */
23#define SMBHSTSTS (0 + 0x3100)
24#define SMBHSTCNT (1 + 0x3100)
25#define SMBHSTSTART (2 + 0x3100)
26#define SMBHSTCMD (7 + 0x3100)
27#define SMBHSTADD (3 + 0x3100)
28#define SMBHSTDAT0 (4 + 0x3100)
29#define SMBHSTDAT1 (5 + 0x3100)
30#define SMBBLKDAT (6 + 0x3100)
31
32/* Other settings */
33#define MAX_TIMEOUT 500 /* times 1/100 sec */
34
35/* ALI15X3 command constants */
36#define ALI15X3_ABORT 0x04
37#define ALI15X3_T_OUT 0x08
38#define ALI15X3_QUICK 0x00
39#define ALI15X3_BYTE 0x10
40#define ALI15X3_BYTE_DATA 0x20
41#define ALI15X3_WORD_DATA 0x30
42#define ALI15X3_BLOCK_DATA 0x40
43#define ALI15X3_BLOCK_CLR 0x80
44
45/* ALI15X3 status register bits */
46#define ALI15X3_STS_IDLE 0x04
47#define ALI15X3_STS_BUSY 0x08
48#define ALI15X3_STS_DONE 0x10
49#define ALI15X3_STS_DEV 0x20 /* device error */
50#define ALI15X3_STS_COLL 0x40 /* collision or no response */
51#define ALI15X3_STS_TERM 0x80 /* terminated by abort */
52#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */
53
54const char *get_system_type(void)
55{
56 return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
57}
58
59static void __init pci_write_config(unsigned long busNo,
60 unsigned long devNo,
61 unsigned long fncNo,
62 unsigned long cnfAdd,
63 unsigned long cnfData)
64{
65 ctrl_outl((0x80000000
66 + ((busNo & 0xff) << 16)
67 + ((devNo & 0x1f) << 11)
68 + ((fncNo & 0x07) << 8)
69 + (cnfAdd & 0xfc)), PCIPAR);
70
71 ctrl_outl(cnfData, PCIPDR);
72}
73
74/*
75 Initialize IRQ setting
76*/
77
78static unsigned char m_irq_mask = 0xfb;
79static unsigned char s_irq_mask = 0xff;
80volatile unsigned long irq_err_count;
81
82static void disable_mpc1211_irq(unsigned int irq)
83{
84 unsigned long flags;
85
86 save_and_cli(flags);
87 if( irq < 8) {
88 m_irq_mask |= (1 << irq);
89 outb(m_irq_mask,I8259_M_MR);
90 } else {
91 s_irq_mask |= (1 << (irq - 8));
92 outb(s_irq_mask,I8259_S_MR);
93 }
94 restore_flags(flags);
95
96}
97
98static void enable_mpc1211_irq(unsigned int irq)
99{
100 unsigned long flags;
101
102 save_and_cli(flags);
103
104 if( irq < 8) {
105 m_irq_mask &= ~(1 << irq);
106 outb(m_irq_mask,I8259_M_MR);
107 } else {
108 s_irq_mask &= ~(1 << (irq - 8));
109 outb(s_irq_mask,I8259_S_MR);
110 }
111 restore_flags(flags);
112}
113
114static inline int mpc1211_irq_real(unsigned int irq)
115{
116 int value;
117 int irqmask;
118
119 if ( irq < 8) {
120 irqmask = 1<<irq;
121 outb(0x0b,I8259_M_CR); /* ISR register */
122 value = inb(I8259_M_CR) & irqmask;
123 outb(0x0a,I8259_M_CR); /* back ro the IPR reg */
124 return value;
125 }
126 irqmask = 1<<(irq - 8);
127 outb(0x0b,I8259_S_CR); /* ISR register */
128 value = inb(I8259_S_CR) & irqmask;
129 outb(0x0a,I8259_S_CR); /* back ro the IPR reg */
130 return value;
131}
132
133static void mask_and_ack_mpc1211(unsigned int irq)
134{
135 unsigned long flags;
136
137 save_and_cli(flags);
138
139 if(irq < 8) {
140 if(m_irq_mask & (1<<irq)){
141 if(!mpc1211_irq_real(irq)){
142 irq_err_count++;
143 printk("spurious 8259A interrupt: IRQ %x\n",irq);
144 }
145 } else {
146 m_irq_mask |= (1<<irq);
147 }
148 inb(I8259_M_MR); /* DUMMY */
149 outb(m_irq_mask,I8259_M_MR); /* disable */
150 outb(0x60+irq,I8259_M_CR); /* EOI */
151
152 } else {
153 if(s_irq_mask & (1<<(irq - 8))){
154 if(!mpc1211_irq_real(irq)){
155 irq_err_count++;
156 printk("spurious 8259A interrupt: IRQ %x\n",irq);
157 }
158 } else {
159 s_irq_mask |= (1<<(irq - 8));
160 }
161 inb(I8259_S_MR); /* DUMMY */
162 outb(s_irq_mask,I8259_S_MR); /* disable */
163 outb(0x60+(irq-8),I8259_S_CR); /* EOI */
164 outb(0x60+2,I8259_M_CR);
165 }
166 restore_flags(flags);
167}
168
169static void end_mpc1211_irq(unsigned int irq)
170{
171 enable_mpc1211_irq(irq);
172}
173
174static unsigned int startup_mpc1211_irq(unsigned int irq)
175{
176 enable_mpc1211_irq(irq);
177 return 0;
178}
179
180static void shutdown_mpc1211_irq(unsigned int irq)
181{
182 disable_mpc1211_irq(irq);
183}
184
185static struct hw_interrupt_type mpc1211_irq_type = {
186 .typename = "MPC1211-IRQ",
187 .startup = startup_mpc1211_irq,
188 .shutdown = shutdown_mpc1211_irq,
189 .enable = enable_mpc1211_irq,
190 .disable = disable_mpc1211_irq,
191 .ack = mask_and_ack_mpc1211,
192 .end = end_mpc1211_irq
193};
194
195static void make_mpc1211_irq(unsigned int irq)
196{
197 irq_desc[irq].handler = &mpc1211_irq_type;
198 irq_desc[irq].status = IRQ_DISABLED;
199 irq_desc[irq].action = 0;
200 irq_desc[irq].depth = 1;
201 disable_mpc1211_irq(irq);
202}
203
204int mpc1211_irq_demux(int irq)
205{
206 unsigned int poll;
207
208 if( irq == 2 ) {
209 outb(0x0c,I8259_M_CR);
210 poll = inb(I8259_M_CR);
211 if(poll & 0x80) {
212 irq = (poll & 0x07);
213 }
214 if( irq == 2) {
215 outb(0x0c,I8259_S_CR);
216 poll = inb(I8259_S_CR);
217 irq = (poll & 0x07) + 8;
218 }
219 }
220 return irq;
221}
222
223void __init init_mpc1211_IRQ(void)
224{
225 int i;
226 /*
227 * Super I/O (Just mimic PC):
228 * 1: keyboard
229 * 3: serial 1
230 * 4: serial 0
231 * 5: printer
232 * 6: floppy
233 * 8: rtc
234 * 10: lan
235 * 12: mouse
236 * 14: ide0
237 * 15: ide1
238 */
239
240 pci_write_config(0,0,0,0x54, 0xb0b0002d);
241 outb(0x11, I8259_M_CR); /* mater icw1 edge trigger */
242 outb(0x11, I8259_S_CR); /* slave icw1 edge trigger */
243 outb(0x20, I8259_M_MR); /* m icw2 base vec 0x08 */
244 outb(0x28, I8259_S_MR); /* s icw2 base vec 0x70 */
245 outb(0x04, I8259_M_MR); /* m icw3 slave irq2 */
246 outb(0x02, I8259_S_MR); /* s icw3 slave id */
247 outb(0x01, I8259_M_MR); /* m icw4 non buf normal eoi*/
248 outb(0x01, I8259_S_MR); /* s icw4 non buf normal eo1*/
249 outb(0xfb, I8259_M_MR); /* disable irq0--irq7 */
250 outb(0xff, I8259_S_MR); /* disable irq8--irq15 */
251
252 for ( i=0; i < 16; i++) {
253 if(i != 2) {
254 make_mpc1211_irq(i);
255 }
256 }
257}
258
259/*
260 Initialize the board
261*/
262
263
264static void delay (void)
265{
266 volatile unsigned short tmp;
267 tmp = *(volatile unsigned short *) 0xa0000000;
268}
269
270static void delay1000 (void)
271{
272 int i;
273
274 for (i=0; i<1000; i++)
275 delay ();
276}
277
278static int put_smb_blk(unsigned char *p, int address, int command, int no)
279{
280 int temp;
281 int timeout;
282 int i;
283
284 outb(0xff, SMBHSTSTS);
285 temp = inb(SMBHSTSTS);
286 for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) {
287 delay1000();
288 temp = inb(SMBHSTSTS);
289 }
290 if (timeout >= MAX_TIMEOUT){
291 return -1;
292 }
293
294 outb(((address & 0x7f) << 1), SMBHSTADD);
295 outb(0xc0, SMBHSTCNT);
296 outb(command & 0xff, SMBHSTCMD);
297 outb(no & 0x1f, SMBHSTDAT0);
298
299 for(i = 1; i <= no; i++) {
300 outb(*p++, SMBBLKDAT);
301 }
302 outb(0xff, SMBHSTSTART);
303
304 temp = inb(SMBHSTSTS);
305 for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) {
306 delay1000();
307 temp = inb(SMBHSTSTS);
308 }
309 if (timeout >= MAX_TIMEOUT) {
310 return -2;
311 }
312 if ( temp & ALI15X3_STS_ERR ){
313 return -3;
314 }
315 return 0;
316}
317
318/*
319 * The Machine Vector
320 */
321
322struct sh_machine_vector mv_mpc1211 __initmv = {
323 .mv_nr_irqs = 48,
324 .mv_irq_demux = mpc1211_irq_demux,
325 .mv_init_irq = init_mpc1211_IRQ,
326
327#ifdef CONFIG_HEARTBEAT
328 .mv_heartbeat = heartbeat_mpc1211,
329#endif
330};
331
332ALIAS_MV(mpc1211)
333
334/* arch/sh/boards/mpc1211/rtc.c */
335void mpc1211_time_init(void);
336
337int __init platform_setup(void)
338{
339 unsigned char spd_buf[128];
340
341 __set_io_port_base(PA_PCI_IO);
342
343 pci_write_config(0,0,0,0x54, 0xb0b00000);
344
345 do {
346 outb(ALI15X3_ABORT, SMBHSTCNT);
347 spd_buf[0] = 0x0c;
348 spd_buf[1] = 0x43;
349 spd_buf[2] = 0x7f;
350 spd_buf[3] = 0x03;
351 spd_buf[4] = 0x00;
352 spd_buf[5] = 0x03;
353 spd_buf[6] = 0x00;
354 } while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0);
355
356 board_time_init = mpc1211_time_init;
357
358 return 0;
359}
360