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