blob: e9c8ff221dda35c213973757c823c30d49e4f174 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/sh/board/mpc1211/setup.c
3 *
4 * Copyright (C) 2002 Saito.K & Jeanne, Fujii.Y
5 *
6 */
7
Linus Torvalds1da177e2005-04-16 15:20:36 -07008#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
53const char *get_system_type(void)
54{
55 return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
56}
57
58static 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
77static unsigned char m_irq_mask = 0xfb;
78static unsigned char s_irq_mask = 0xff;
79volatile unsigned long irq_err_count;
80
81static void disable_mpc1211_irq(unsigned int irq)
82{
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 if( irq < 8) {
84 m_irq_mask |= (1 << irq);
85 outb(m_irq_mask,I8259_M_MR);
86 } else {
87 s_irq_mask |= (1 << (irq - 8));
88 outb(s_irq_mask,I8259_S_MR);
89 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91}
92
93static void enable_mpc1211_irq(unsigned int irq)
94{
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 if( irq < 8) {
96 m_irq_mask &= ~(1 << irq);
97 outb(m_irq_mask,I8259_M_MR);
98 } else {
99 s_irq_mask &= ~(1 << (irq - 8));
100 outb(s_irq_mask,I8259_S_MR);
101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102}
103
104static inline int mpc1211_irq_real(unsigned int irq)
105{
106 int value;
107 int irqmask;
108
109 if ( irq < 8) {
110 irqmask = 1<<irq;
111 outb(0x0b,I8259_M_CR); /* ISR register */
112 value = inb(I8259_M_CR) & irqmask;
113 outb(0x0a,I8259_M_CR); /* back ro the IPR reg */
114 return value;
115 }
116 irqmask = 1<<(irq - 8);
117 outb(0x0b,I8259_S_CR); /* ISR register */
118 value = inb(I8259_S_CR) & irqmask;
119 outb(0x0a,I8259_S_CR); /* back ro the IPR reg */
120 return value;
121}
122
123static void mask_and_ack_mpc1211(unsigned int irq)
124{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 if(irq < 8) {
126 if(m_irq_mask & (1<<irq)){
127 if(!mpc1211_irq_real(irq)){
128 irq_err_count++;
129 printk("spurious 8259A interrupt: IRQ %x\n",irq);
130 }
131 } else {
132 m_irq_mask |= (1<<irq);
133 }
134 inb(I8259_M_MR); /* DUMMY */
135 outb(m_irq_mask,I8259_M_MR); /* disable */
136 outb(0x60+irq,I8259_M_CR); /* EOI */
137
138 } else {
139 if(s_irq_mask & (1<<(irq - 8))){
140 if(!mpc1211_irq_real(irq)){
141 irq_err_count++;
142 printk("spurious 8259A interrupt: IRQ %x\n",irq);
143 }
144 } else {
145 s_irq_mask |= (1<<(irq - 8));
146 }
147 inb(I8259_S_MR); /* DUMMY */
148 outb(s_irq_mask,I8259_S_MR); /* disable */
149 outb(0x60+(irq-8),I8259_S_CR); /* EOI */
150 outb(0x60+2,I8259_M_CR);
151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152}
153
154static void end_mpc1211_irq(unsigned int irq)
155{
156 enable_mpc1211_irq(irq);
157}
158
159static unsigned int startup_mpc1211_irq(unsigned int irq)
160{
161 enable_mpc1211_irq(irq);
162 return 0;
163}
164
165static void shutdown_mpc1211_irq(unsigned int irq)
166{
167 disable_mpc1211_irq(irq);
168}
169
170static struct hw_interrupt_type mpc1211_irq_type = {
171 .typename = "MPC1211-IRQ",
172 .startup = startup_mpc1211_irq,
173 .shutdown = shutdown_mpc1211_irq,
174 .enable = enable_mpc1211_irq,
175 .disable = disable_mpc1211_irq,
176 .ack = mask_and_ack_mpc1211,
177 .end = end_mpc1211_irq
178};
179
180static void make_mpc1211_irq(unsigned int irq)
181{
Ingo Molnard1bef4e2006-06-29 02:24:36 -0700182 irq_desc[irq].chip = &mpc1211_irq_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 irq_desc[irq].status = IRQ_DISABLED;
184 irq_desc[irq].action = 0;
185 irq_desc[irq].depth = 1;
186 disable_mpc1211_irq(irq);
187}
188
189int mpc1211_irq_demux(int irq)
190{
191 unsigned int poll;
192
193 if( irq == 2 ) {
194 outb(0x0c,I8259_M_CR);
195 poll = inb(I8259_M_CR);
196 if(poll & 0x80) {
197 irq = (poll & 0x07);
198 }
199 if( irq == 2) {
200 outb(0x0c,I8259_S_CR);
201 poll = inb(I8259_S_CR);
202 irq = (poll & 0x07) + 8;
203 }
204 }
205 return irq;
206}
207
208void __init init_mpc1211_IRQ(void)
209{
210 int i;
211 /*
212 * Super I/O (Just mimic PC):
213 * 1: keyboard
214 * 3: serial 1
215 * 4: serial 0
216 * 5: printer
217 * 6: floppy
218 * 8: rtc
219 * 10: lan
220 * 12: mouse
221 * 14: ide0
222 * 15: ide1
223 */
224
225 pci_write_config(0,0,0,0x54, 0xb0b0002d);
226 outb(0x11, I8259_M_CR); /* mater icw1 edge trigger */
227 outb(0x11, I8259_S_CR); /* slave icw1 edge trigger */
228 outb(0x20, I8259_M_MR); /* m icw2 base vec 0x08 */
229 outb(0x28, I8259_S_MR); /* s icw2 base vec 0x70 */
230 outb(0x04, I8259_M_MR); /* m icw3 slave irq2 */
231 outb(0x02, I8259_S_MR); /* s icw3 slave id */
232 outb(0x01, I8259_M_MR); /* m icw4 non buf normal eoi*/
233 outb(0x01, I8259_S_MR); /* s icw4 non buf normal eo1*/
234 outb(0xfb, I8259_M_MR); /* disable irq0--irq7 */
235 outb(0xff, I8259_S_MR); /* disable irq8--irq15 */
236
237 for ( i=0; i < 16; i++) {
238 if(i != 2) {
239 make_mpc1211_irq(i);
240 }
241 }
242}
243
Paul Mundt959f85f2006-09-27 16:43:28 +0900244static void delay1000(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245{
246 int i;
247
248 for (i=0; i<1000; i++)
Paul Mundt959f85f2006-09-27 16:43:28 +0900249 ctrl_delay();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250}
251
252static int put_smb_blk(unsigned char *p, int address, int command, int no)
253{
254 int temp;
255 int timeout;
256 int i;
257
258 outb(0xff, SMBHSTSTS);
259 temp = inb(SMBHSTSTS);
260 for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) {
261 delay1000();
262 temp = inb(SMBHSTSTS);
263 }
264 if (timeout >= MAX_TIMEOUT){
265 return -1;
266 }
267
268 outb(((address & 0x7f) << 1), SMBHSTADD);
269 outb(0xc0, SMBHSTCNT);
270 outb(command & 0xff, SMBHSTCMD);
271 outb(no & 0x1f, SMBHSTDAT0);
272
273 for(i = 1; i <= no; i++) {
274 outb(*p++, SMBBLKDAT);
275 }
276 outb(0xff, SMBHSTSTART);
277
278 temp = inb(SMBHSTSTS);
279 for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) {
280 delay1000();
281 temp = inb(SMBHSTSTS);
282 }
283 if (timeout >= MAX_TIMEOUT) {
284 return -2;
285 }
286 if ( temp & ALI15X3_STS_ERR ){
287 return -3;
288 }
289 return 0;
290}
291
292/*
293 * The Machine Vector
294 */
295
296struct sh_machine_vector mv_mpc1211 __initmv = {
297 .mv_nr_irqs = 48,
298 .mv_irq_demux = mpc1211_irq_demux,
299 .mv_init_irq = init_mpc1211_IRQ,
300
301#ifdef CONFIG_HEARTBEAT
302 .mv_heartbeat = heartbeat_mpc1211,
303#endif
304};
305
306ALIAS_MV(mpc1211)
307
308/* arch/sh/boards/mpc1211/rtc.c */
309void mpc1211_time_init(void);
310
311int __init platform_setup(void)
312{
313 unsigned char spd_buf[128];
314
315 __set_io_port_base(PA_PCI_IO);
316
317 pci_write_config(0,0,0,0x54, 0xb0b00000);
318
319 do {
320 outb(ALI15X3_ABORT, SMBHSTCNT);
321 spd_buf[0] = 0x0c;
322 spd_buf[1] = 0x43;
323 spd_buf[2] = 0x7f;
324 spd_buf[3] = 0x03;
325 spd_buf[4] = 0x00;
326 spd_buf[5] = 0x03;
327 spd_buf[6] = 0x00;
328 } while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0);
329
330 board_time_init = mpc1211_time_init;
331
332 return 0;
333}
334