1/*
2 * linux/arch/arm/mach-footbridge/netwinder-hw.c
3 *
4 * Netwinder machine fixup
5 *
6 * Copyright (C) 1998, 1999 Russell King, Phil Blundell
7 */
8#include <linux/module.h>
9#include <linux/ioport.h>
10#include <linux/kernel.h>
11#include <linux/delay.h>
12#include <linux/init.h>
13#include <linux/io.h>
14#include <linux/spinlock.h>
15#include <linux/slab.h>
16#include <linux/leds.h>
17
18#include <asm/hardware/dec21285.h>
19#include <asm/mach-types.h>
20#include <asm/setup.h>
21#include <asm/system_misc.h>
22
23#include <asm/mach/arch.h>
24
25#include "common.h"
26
27#define IRDA_IO_BASE		0x180
28#define GP1_IO_BASE		0x338
29#define GP2_IO_BASE		0x33a
30
31/*
32 * Winbond WB83977F accessibility stuff
33 */
34static inline void wb977_open(void)
35{
36	outb(0x87, 0x370);
37	outb(0x87, 0x370);
38}
39
40static inline void wb977_close(void)
41{
42	outb(0xaa, 0x370);
43}
44
45static inline void wb977_wb(int reg, int val)
46{
47	outb(reg, 0x370);
48	outb(val, 0x371);
49}
50
51static inline void wb977_ww(int reg, int val)
52{
53	outb(reg, 0x370);
54	outb(val >> 8, 0x371);
55	outb(reg + 1, 0x370);
56	outb(val & 255, 0x371);
57}
58
59#define wb977_device_select(dev)	wb977_wb(0x07, dev)
60#define wb977_device_disable()		wb977_wb(0x30, 0x00)
61#define wb977_device_enable()		wb977_wb(0x30, 0x01)
62
63/*
64 * This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
65 */
66DEFINE_RAW_SPINLOCK(nw_gpio_lock);
67EXPORT_SYMBOL(nw_gpio_lock);
68
69static unsigned int current_gpio_op;
70static unsigned int current_gpio_io;
71static unsigned int current_cpld;
72
73void nw_gpio_modify_op(unsigned int mask, unsigned int set)
74{
75	unsigned int new_gpio, changed;
76
77	new_gpio = (current_gpio_op & ~mask) | set;
78	changed = new_gpio ^ current_gpio_op;
79	current_gpio_op = new_gpio;
80
81	if (changed & 0xff)
82		outb(new_gpio, GP1_IO_BASE);
83	if (changed & 0xff00)
84		outb(new_gpio >> 8, GP2_IO_BASE);
85}
86EXPORT_SYMBOL(nw_gpio_modify_op);
87
88static inline void __gpio_modify_io(int mask, int in)
89{
90	unsigned int new_gpio, changed;
91	int port;
92
93	new_gpio = (current_gpio_io & ~mask) | in;
94	changed = new_gpio ^ current_gpio_io;
95	current_gpio_io = new_gpio;
96
97	changed >>= 1;
98	new_gpio >>= 1;
99
100	wb977_device_select(7);
101
102	for (port = 0xe1; changed && port < 0xe8; changed >>= 1) {
103		wb977_wb(port, new_gpio & 1);
104
105		port += 1;
106		new_gpio >>= 1;
107	}
108
109	wb977_device_select(8);
110
111	for (port = 0xe8; changed && port < 0xec; changed >>= 1) {
112		wb977_wb(port, new_gpio & 1);
113
114		port += 1;
115		new_gpio >>= 1;
116	}
117}
118
119void nw_gpio_modify_io(unsigned int mask, unsigned int in)
120{
121	/* Open up the SuperIO chip */
122	wb977_open();
123
124	__gpio_modify_io(mask, in);
125
126	/* Close up the EFER gate */
127	wb977_close();
128}
129EXPORT_SYMBOL(nw_gpio_modify_io);
130
131unsigned int nw_gpio_read(void)
132{
133	return inb(GP1_IO_BASE) | inb(GP2_IO_BASE) << 8;
134}
135EXPORT_SYMBOL(nw_gpio_read);
136
137/*
138 * Initialise the Winbond W83977F global registers
139 */
140static inline void wb977_init_global(void)
141{
142	/*
143	 * Enable R/W config registers
144	 */
145	wb977_wb(0x26, 0x40);
146
147	/*
148	 * Power down FDC (not used)
149	 */
150	wb977_wb(0x22, 0xfe);
151
152	/*
153	 * GP12, GP11, CIRRX, IRRXH, GP10
154	 */
155	wb977_wb(0x2a, 0xc1);
156
157	/*
158	 * GP23, GP22, GP21, GP20, GP13
159	 */
160	wb977_wb(0x2b, 0x6b);
161
162	/*
163	 * GP17, GP16, GP15, GP14
164	 */
165	wb977_wb(0x2c, 0x55);
166}
167
168/*
169 * Initialise the Winbond W83977F printer port
170 */
171static inline void wb977_init_printer(void)
172{
173	wb977_device_select(1);
174
175	/*
176	 * mode 1 == EPP
177	 */
178	wb977_wb(0xf0, 0x01);
179}
180
181/*
182 * Initialise the Winbond W83977F keyboard controller
183 */
184static inline void wb977_init_keyboard(void)
185{
186	wb977_device_select(5);
187
188	/*
189	 * Keyboard controller address
190	 */
191	wb977_ww(0x60, 0x0060);
192	wb977_ww(0x62, 0x0064);
193
194	/*
195	 * Keyboard IRQ 1, active high, edge trigger
196	 */
197	wb977_wb(0x70, 1);
198	wb977_wb(0x71, 0x02);
199
200	/*
201	 * Mouse IRQ 5, active high, edge trigger
202	 */
203	wb977_wb(0x72, 5);
204	wb977_wb(0x73, 0x02);
205
206	/*
207	 * KBC 8MHz
208	 */
209	wb977_wb(0xf0, 0x40);
210
211	/*
212	 * Enable device
213	 */
214	wb977_device_enable();
215}
216
217/*
218 * Initialise the Winbond W83977F Infra-Red device
219 */
220static inline void wb977_init_irda(void)
221{
222	wb977_device_select(6);
223
224	/*
225	 * IR base address
226	 */
227	wb977_ww(0x60, IRDA_IO_BASE);
228
229	/*
230	 * IRDA IRQ 6, active high, edge trigger
231	 */
232	wb977_wb(0x70, 6);
233	wb977_wb(0x71, 0x02);
234
235	/*
236	 * RX DMA - ISA DMA 0
237	 */
238	wb977_wb(0x74, 0x00);
239
240	/*
241	 * TX DMA - Disable Tx DMA
242	 */
243	wb977_wb(0x75, 0x04);
244
245	/*
246	 * Append CRC, Enable bank selection
247	 */
248	wb977_wb(0xf0, 0x03);
249
250	/*
251	 * Enable device
252	 */
253	wb977_device_enable();
254}
255
256/*
257 * Initialise Winbond W83977F general purpose IO
258 */
259static inline void wb977_init_gpio(void)
260{
261	unsigned long flags;
262
263	/*
264	 * Set up initial I/O definitions
265	 */
266	current_gpio_io = -1;
267	__gpio_modify_io(-1, GPIO_DONE | GPIO_WDTIMER);
268
269	wb977_device_select(7);
270
271	/*
272	 * Group1 base address
273	 */
274	wb977_ww(0x60, GP1_IO_BASE);
275	wb977_ww(0x62, 0);
276	wb977_ww(0x64, 0);
277
278	/*
279	 * GP10 (Orage button) IRQ 10, active high, edge trigger
280	 */
281	wb977_wb(0x70, 10);
282	wb977_wb(0x71, 0x02);
283
284	/*
285	 * GP10: Debounce filter enabled, IRQ, input
286	 */
287	wb977_wb(0xe0, 0x19);
288
289	/*
290	 * Enable Group1
291	 */
292	wb977_device_enable();
293
294	wb977_device_select(8);
295
296	/*
297	 * Group2 base address
298	 */
299	wb977_ww(0x60, GP2_IO_BASE);
300
301	/*
302	 * Clear watchdog timer regs
303	 *  - timer disable
304	 */
305	wb977_wb(0xf2, 0x00);
306
307	/*
308	 *  - disable LED, no mouse nor keyboard IRQ
309	 */
310	wb977_wb(0xf3, 0x00);
311
312	/*
313	 *  - timer counting, disable power LED, disable timeouot
314	 */
315	wb977_wb(0xf4, 0x00);
316
317	/*
318	 * Enable group2
319	 */
320	wb977_device_enable();
321
322	/*
323	 * Set Group1/Group2 outputs
324	 */
325	raw_spin_lock_irqsave(&nw_gpio_lock, flags);
326	nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
327	raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
328}
329
330/*
331 * Initialise the Winbond W83977F chip.
332 */
333static void __init wb977_init(void)
334{
335	request_region(0x370, 2, "W83977AF configuration");
336
337	/*
338	 * Open up the SuperIO chip
339	 */
340	wb977_open();
341
342	/*
343	 * Initialise the global registers
344	 */
345	wb977_init_global();
346
347	/*
348	 * Initialise the various devices in
349	 * the multi-IO chip.
350	 */
351	wb977_init_printer();
352	wb977_init_keyboard();
353	wb977_init_irda();
354	wb977_init_gpio();
355
356	/*
357	 * Close up the EFER gate
358	 */
359	wb977_close();
360}
361
362void nw_cpld_modify(unsigned int mask, unsigned int set)
363{
364	int msk;
365
366	current_cpld = (current_cpld & ~mask) | set;
367
368	nw_gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0);
369	nw_gpio_modify_op(GPIO_IOLOAD, 0);
370
371	for (msk = 8; msk; msk >>= 1) {
372		int bit = current_cpld & msk;
373
374		nw_gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0);
375		nw_gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK);
376	}
377
378	nw_gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0);
379	nw_gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK);
380	nw_gpio_modify_op(GPIO_IOLOAD, 0);
381}
382EXPORT_SYMBOL(nw_cpld_modify);
383
384static void __init cpld_init(void)
385{
386	unsigned long flags;
387
388	raw_spin_lock_irqsave(&nw_gpio_lock, flags);
389	nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
390	raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
391}
392
393static unsigned char rwa_unlock[] __initdata =
394{ 0x00, 0x00, 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b,
395  0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74,
396  0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
397
398#ifndef DEBUG
399#define dprintk(x...)
400#else
401#define dprintk(x...) printk(x)
402#endif
403
404#define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0)
405
406static inline void rwa010_unlock(void)
407{
408	int i;
409
410	WRITE_RWA(2, 2);
411	mdelay(10);
412
413	for (i = 0; i < sizeof(rwa_unlock); i++) {
414		outb(rwa_unlock[i], 0x279);
415		udelay(10);
416	}
417}
418
419static inline void rwa010_read_ident(void)
420{
421	unsigned char si[9];
422	int i, j;
423
424	WRITE_RWA(3, 0);
425	WRITE_RWA(0, 128);
426
427	outb(1, 0x279);
428
429	mdelay(1);
430
431	dprintk("Identifier: ");
432	for (i = 0; i < 9; i++) {
433		si[i] = 0;
434		for (j = 0; j < 8; j++) {
435			int bit;
436			udelay(250);
437			inb(0x203);
438			udelay(250);
439			bit = inb(0x203);
440			dprintk("%02X ", bit);
441			bit = (bit == 0xaa) ? 1 : 0;
442			si[i] |= bit << j;
443		}
444		dprintk("(%02X) ", si[i]);
445	}
446	dprintk("\n");
447}
448
449static inline void rwa010_global_init(void)
450{
451	WRITE_RWA(6, 2);	// Assign a card no = 2
452
453	dprintk("Card no = %d\n", inb(0x203));
454
455	/* disable the modem section of the chip */
456	WRITE_RWA(7, 3);
457	WRITE_RWA(0x30, 0);
458
459	/* disable the cdrom section of the chip */
460	WRITE_RWA(7, 4);
461	WRITE_RWA(0x30, 0);
462
463	/* disable the MPU-401 section of the chip */
464	WRITE_RWA(7, 2);
465	WRITE_RWA(0x30, 0);
466}
467
468static inline void rwa010_game_port_init(void)
469{
470	int i;
471
472	WRITE_RWA(7, 5);
473
474	dprintk("Slider base: ");
475	WRITE_RWA(0x61, 1);
476	i = inb(0x203);
477
478	WRITE_RWA(0x60, 2);
479	dprintk("%02X%02X (201)\n", inb(0x203), i);
480
481	WRITE_RWA(0x30, 1);
482}
483
484static inline void rwa010_waveartist_init(int base, int irq, int dma)
485{
486	int i;
487
488	WRITE_RWA(7, 0);
489
490	dprintk("WaveArtist base: ");
491	WRITE_RWA(0x61, base & 255);
492	i = inb(0x203);
493
494	WRITE_RWA(0x60, base >> 8);
495	dprintk("%02X%02X (%X),", inb(0x203), i, base);
496
497	WRITE_RWA(0x70, irq);
498	dprintk(" irq: %d (%d),", inb(0x203), irq);
499
500	WRITE_RWA(0x74, dma);
501	dprintk(" dma: %d (%d)\n", inb(0x203), dma);
502
503	WRITE_RWA(0x30, 1);
504}
505
506static inline void rwa010_soundblaster_init(int sb_base, int al_base, int irq, int dma)
507{
508	int i;
509
510	WRITE_RWA(7, 1);
511
512	dprintk("SoundBlaster base: ");
513	WRITE_RWA(0x61, sb_base & 255);
514	i = inb(0x203);
515
516	WRITE_RWA(0x60, sb_base >> 8);
517	dprintk("%02X%02X (%X),", inb(0x203), i, sb_base);
518
519	dprintk(" irq: ");
520	WRITE_RWA(0x70, irq);
521	dprintk("%d (%d),", inb(0x203), irq);
522
523	dprintk(" 8-bit DMA: ");
524	WRITE_RWA(0x74, dma);
525	dprintk("%d (%d)\n", inb(0x203), dma);
526
527	dprintk("AdLib base: ");
528	WRITE_RWA(0x63, al_base & 255);
529	i = inb(0x203);
530
531	WRITE_RWA(0x62, al_base >> 8);
532	dprintk("%02X%02X (%X)\n", inb(0x203), i, al_base);
533
534	WRITE_RWA(0x30, 1);
535}
536
537static void rwa010_soundblaster_reset(void)
538{
539	int i;
540
541	outb(1, 0x226);
542	udelay(3);
543	outb(0, 0x226);
544
545	for (i = 0; i < 5; i++) {
546		if (inb(0x22e) & 0x80)
547			break;
548		mdelay(1);
549	}
550	if (i == 5)
551		printk("SoundBlaster: DSP reset failed\n");
552
553	dprintk("SoundBlaster DSP reset: %02X (AA)\n", inb(0x22a));
554
555	for (i = 0; i < 5; i++) {
556		if ((inb(0x22c) & 0x80) == 0)
557			break;
558		mdelay(1);
559	}
560
561	if (i == 5)
562		printk("SoundBlaster: DSP not ready\n");
563	else {
564		outb(0xe1, 0x22c);
565
566		dprintk("SoundBlaster DSP id: ");
567		i = inb(0x22a);
568		udelay(1);
569		i |= inb(0x22a) << 8;
570		dprintk("%04X\n", i);
571
572		for (i = 0; i < 5; i++) {
573			if ((inb(0x22c) & 0x80) == 0)
574				break;
575			mdelay(1);
576		}
577
578		if (i == 5)
579			printk("SoundBlaster: could not turn speaker off\n");
580
581		outb(0xd3, 0x22c);
582	}
583
584	/* turn on OPL3 */
585	outb(5, 0x38a);
586	outb(1, 0x38b);
587}
588
589static void __init rwa010_init(void)
590{
591	rwa010_unlock();
592	rwa010_read_ident();
593	rwa010_global_init();
594	rwa010_game_port_init();
595	rwa010_waveartist_init(0x250, 3, 7);
596	rwa010_soundblaster_init(0x220, 0x388, 3, 1);
597	rwa010_soundblaster_reset();
598}
599
600/*
601 * Initialise any other hardware after we've got the PCI bus
602 * initialised.  We may need the PCI bus to talk to this other
603 * hardware.
604 */
605static int __init nw_hw_init(void)
606{
607	if (machine_is_netwinder()) {
608		wb977_init();
609		cpld_init();
610		rwa010_init();
611	}
612	return 0;
613}
614
615__initcall(nw_hw_init);
616
617/*
618 * Older NeTTroms either do not provide a parameters
619 * page, or they don't supply correct information in
620 * the parameter page.
621 */
622static void __init
623fixup_netwinder(struct tag *tags, char **cmdline)
624{
625#ifdef CONFIG_ISAPNP
626	extern int isapnp_disable;
627
628	/*
629	 * We must not use the kernels ISAPnP code
630	 * on the NetWinder - it will reset the settings
631	 * for the WaveArtist chip and render it inoperable.
632	 */
633	isapnp_disable = 1;
634#endif
635}
636
637static void netwinder_restart(enum reboot_mode mode, const char *cmd)
638{
639	if (mode == REBOOT_SOFT) {
640		/* Jump into the ROM */
641		soft_restart(0x41000000);
642	} else {
643		local_irq_disable();
644		local_fiq_disable();
645
646		/* open up the SuperIO chip */
647		outb(0x87, 0x370);
648		outb(0x87, 0x370);
649
650		/* aux function group 1 (logical device 7) */
651		outb(0x07, 0x370);
652		outb(0x07, 0x371);
653
654		/* set GP16 for WD-TIMER output */
655		outb(0xe6, 0x370);
656		outb(0x00, 0x371);
657
658		/* set a RED LED and toggle WD_TIMER for rebooting */
659		outb(0xc4, 0x338);
660	}
661}
662
663/* LEDs */
664#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
665struct netwinder_led {
666	struct led_classdev     cdev;
667	u8                      mask;
668};
669
670/*
671 * The triggers lines up below will only be used if the
672 * LED triggers are compiled in.
673 */
674static const struct {
675	const char *name;
676	const char *trigger;
677} netwinder_leds[] = {
678	{ "netwinder:green", "heartbeat", },
679	{ "netwinder:red", "cpu0", },
680};
681
682/*
683 * The LED control in Netwinder is reversed:
684 *  - setting bit means turn off LED
685 *  - clearing bit means turn on LED
686 */
687static void netwinder_led_set(struct led_classdev *cdev,
688		enum led_brightness b)
689{
690	struct netwinder_led *led = container_of(cdev,
691			struct netwinder_led, cdev);
692	unsigned long flags;
693	u32 reg;
694
695	raw_spin_lock_irqsave(&nw_gpio_lock, flags);
696	reg = nw_gpio_read();
697	if (b != LED_OFF)
698		reg &= ~led->mask;
699	else
700		reg |= led->mask;
701	nw_gpio_modify_op(led->mask, reg);
702	raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
703}
704
705static enum led_brightness netwinder_led_get(struct led_classdev *cdev)
706{
707	struct netwinder_led *led = container_of(cdev,
708			struct netwinder_led, cdev);
709	unsigned long flags;
710	u32 reg;
711
712	raw_spin_lock_irqsave(&nw_gpio_lock, flags);
713	reg = nw_gpio_read();
714	raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
715
716	return (reg & led->mask) ? LED_OFF : LED_FULL;
717}
718
719static int __init netwinder_leds_init(void)
720{
721	int i;
722
723	if (!machine_is_netwinder())
724		return -ENODEV;
725
726	for (i = 0; i < ARRAY_SIZE(netwinder_leds); i++) {
727		struct netwinder_led *led;
728
729		led = kzalloc(sizeof(*led), GFP_KERNEL);
730		if (!led)
731			break;
732
733		led->cdev.name = netwinder_leds[i].name;
734		led->cdev.brightness_set = netwinder_led_set;
735		led->cdev.brightness_get = netwinder_led_get;
736		led->cdev.default_trigger = netwinder_leds[i].trigger;
737
738		if (i == 0)
739			led->mask = GPIO_GREEN_LED;
740		else
741			led->mask = GPIO_RED_LED;
742
743		if (led_classdev_register(NULL, &led->cdev) < 0) {
744			kfree(led);
745			break;
746		}
747	}
748
749	return 0;
750}
751
752/*
753 * Since we may have triggers on any subsystem, defer registration
754 * until after subsystem_init.
755 */
756fs_initcall(netwinder_leds_init);
757#endif
758
759MACHINE_START(NETWINDER, "Rebel-NetWinder")
760	/* Maintainer: Russell King/Rebel.com */
761	.atag_offset	= 0x100,
762	.video_start	= 0x000a0000,
763	.video_end	= 0x000bffff,
764	.reserve_lp0	= 1,
765	.reserve_lp2	= 1,
766	.fixup		= fixup_netwinder,
767	.map_io		= footbridge_map_io,
768	.init_irq	= footbridge_init_irq,
769	.init_time	= isa_timer_init,
770	.restart	= netwinder_restart,
771MACHINE_END
772