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
52static 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
71static unsigned char m_irq_mask = 0xfb;
72static unsigned char s_irq_mask = 0xff;
73
74static 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
86static 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
97static 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
116static 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
147static void end_mpc1211_irq(unsigned int irq)
148{
149	enable_mpc1211_irq(irq);
150}
151
152static unsigned int startup_mpc1211_irq(unsigned int irq)
153{
154	enable_mpc1211_irq(irq);
155	return 0;
156}
157
158static void shutdown_mpc1211_irq(unsigned int irq)
159{
160	disable_mpc1211_irq(irq);
161}
162
163static 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
173static 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
182int 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
201static 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
237static void delay1000(void)
238{
239	int i;
240
241	for (i=0; i<1000; i++)
242		ctrl_delay();
243}
244
245static 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
285static struct resource heartbeat_resources[] = {
286	[0] = {
287		.start	= 0xa2000000,
288		.end	= 0xa2000000 + 8 - 1,
289		.flags	= IORESOURCE_MEM,
290	},
291};
292
293static struct platform_device heartbeat_device = {
294	.name		= "heartbeat",
295	.id		= -1,
296	.num_resources	= ARRAY_SIZE(heartbeat_resources),
297	.resource	= heartbeat_resources,
298};
299
300static struct platform_device *mpc1211_devices[] __initdata = {
301	&heartbeat_device,
302};
303
304static 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 */
312void mpc1211_time_init(void);
313
314static 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 */
341struct 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};
348ALIAS_MV(mpc1211)
349