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