Contents of /alx-src/tags/kernel26-2.6.12-alx-r9/drivers/parisc/lasi.c
Parent Directory | Revision Log
Revision 630 -
(show annotations)
(download)
Wed Mar 4 11:03:09 2009 UTC (15 years, 6 months ago) by niro
File MIME type: text/plain
File size: 6256 byte(s)
Wed Mar 4 11:03:09 2009 UTC (15 years, 6 months ago) by niro
File MIME type: text/plain
File size: 6256 byte(s)
Tag kernel26-2.6.12-alx-r9
1 | /* |
2 | * LASI Device Driver |
3 | * |
4 | * (c) Copyright 1999 Red Hat Software |
5 | * Portions (c) Copyright 1999 The Puffin Group Inc. |
6 | * Portions (c) Copyright 1999 Hewlett-Packard |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. |
12 | * |
13 | * by Alan Cox <alan@redhat.com> and |
14 | * Alex deVries <alex@onefishtwo.ca> |
15 | */ |
16 | |
17 | #include <linux/errno.h> |
18 | #include <linux/init.h> |
19 | #include <linux/interrupt.h> |
20 | #include <linux/slab.h> |
21 | #include <linux/module.h> |
22 | #include <linux/pm.h> |
23 | #include <linux/slab.h> |
24 | #include <linux/types.h> |
25 | |
26 | #include <asm/io.h> |
27 | #include <asm/hardware.h> |
28 | #include <asm/led.h> |
29 | |
30 | #include "gsc.h" |
31 | |
32 | |
33 | #define LASI_VER 0xC008 /* LASI Version */ |
34 | |
35 | #define LASI_IO_CONF 0x7FFFE /* LASI primary configuration register */ |
36 | #define LASI_IO_CONF2 0x7FFFF /* LASI secondary configuration register */ |
37 | |
38 | static void lasi_choose_irq(struct parisc_device *dev, void *ctrl) |
39 | { |
40 | int irq; |
41 | |
42 | switch (dev->id.sversion) { |
43 | case 0x74: irq = 7; break; /* Centronics */ |
44 | case 0x7B: irq = 13; break; /* Audio */ |
45 | case 0x81: irq = 14; break; /* Lasi itself */ |
46 | case 0x82: irq = 9; break; /* SCSI */ |
47 | case 0x83: irq = 20; break; /* Floppy */ |
48 | case 0x84: irq = 26; break; /* PS/2 Keyboard */ |
49 | case 0x87: irq = 18; break; /* ISDN */ |
50 | case 0x8A: irq = 8; break; /* LAN */ |
51 | case 0x8C: irq = 5; break; /* RS232 */ |
52 | case 0x8D: irq = (dev->hw_path == 13) ? 16 : 17; break; |
53 | /* Telephone */ |
54 | default: return; /* unknown */ |
55 | } |
56 | |
57 | gsc_asic_assign_irq(ctrl, irq, &dev->irq); |
58 | } |
59 | |
60 | static void __init |
61 | lasi_init_irq(struct gsc_asic *this_lasi) |
62 | { |
63 | unsigned long lasi_base = this_lasi->hpa; |
64 | |
65 | /* Stop LASI barking for a bit */ |
66 | gsc_writel(0x00000000, lasi_base+OFFSET_IMR); |
67 | |
68 | /* clear pending interrupts */ |
69 | gsc_readl(lasi_base+OFFSET_IRR); |
70 | |
71 | /* We're not really convinced we want to reset the onboard |
72 | * devices. Firmware does it for us... |
73 | */ |
74 | |
75 | /* Resets */ |
76 | /* gsc_writel(0xFFFFFFFF, lasi_base+0x2000);*/ /* Parallel */ |
77 | if(pdc_add_valid(lasi_base+0x4004) == PDC_OK) |
78 | gsc_writel(0xFFFFFFFF, lasi_base+0x4004); /* Audio */ |
79 | /* gsc_writel(0xFFFFFFFF, lasi_base+0x5000);*/ /* Serial */ |
80 | /* gsc_writel(0xFFFFFFFF, lasi_base+0x6000);*/ /* SCSI */ |
81 | gsc_writel(0xFFFFFFFF, lasi_base+0x7000); /* LAN */ |
82 | gsc_writel(0xFFFFFFFF, lasi_base+0x8000); /* Keyboard */ |
83 | gsc_writel(0xFFFFFFFF, lasi_base+0xA000); /* FDC */ |
84 | |
85 | /* Ok we hit it on the head with a hammer, our Dog is now |
86 | ** comatose and muzzled. Devices will now unmask LASI |
87 | ** interrupts as they are registered as irq's in the LASI range. |
88 | */ |
89 | /* XXX: I thought it was `awks that got `it on the `ead with an |
90 | * `ammer. -- willy |
91 | */ |
92 | } |
93 | |
94 | |
95 | /* |
96 | ** lasi_led_init() |
97 | ** |
98 | ** lasi_led_init() initializes the LED controller on the LASI. |
99 | ** |
100 | ** Since Mirage and Electra machines use a different LED |
101 | ** address register, we need to check for these machines |
102 | ** explicitly. |
103 | */ |
104 | |
105 | #ifndef CONFIG_CHASSIS_LCD_LED |
106 | |
107 | #define lasi_led_init(x) /* nothing */ |
108 | |
109 | #else |
110 | |
111 | void __init lasi_led_init(unsigned long lasi_hpa) |
112 | { |
113 | unsigned long datareg; |
114 | |
115 | switch (CPU_HVERSION) { |
116 | /* Gecko machines have only one single LED, which can be permanently |
117 | turned on by writing a zero into the power control register. */ |
118 | case 0x600: /* Gecko (712/60) */ |
119 | case 0x601: /* Gecko (712/80) */ |
120 | case 0x602: /* Gecko (712/100) */ |
121 | case 0x603: /* Anole 64 (743/64) */ |
122 | case 0x604: /* Anole 100 (743/100) */ |
123 | case 0x605: /* Gecko (712/120) */ |
124 | datareg = lasi_hpa + 0x0000C000; |
125 | gsc_writeb(0, datareg); |
126 | return; /* no need to register the LED interrupt-function */ |
127 | |
128 | /* Mirage and Electra machines need special offsets */ |
129 | case 0x60A: /* Mirage Jr (715/64) */ |
130 | case 0x60B: /* Mirage 100 */ |
131 | case 0x60C: /* Mirage 100+ */ |
132 | case 0x60D: /* Electra 100 */ |
133 | case 0x60E: /* Electra 120 */ |
134 | datareg = lasi_hpa - 0x00020000; |
135 | break; |
136 | |
137 | default: |
138 | datareg = lasi_hpa + 0x0000C000; |
139 | break; |
140 | } |
141 | |
142 | register_led_driver(DISPLAY_MODEL_LASI, LED_CMD_REG_NONE, datareg); |
143 | } |
144 | #endif |
145 | |
146 | /* |
147 | * lasi_power_off |
148 | * |
149 | * Function for lasi to turn off the power. This is accomplished by setting a |
150 | * 1 to PWR_ON_L in the Power Control Register |
151 | * |
152 | */ |
153 | |
154 | static unsigned long lasi_power_off_hpa; |
155 | |
156 | static void lasi_power_off(void) |
157 | { |
158 | unsigned long datareg; |
159 | |
160 | /* calculate addr of the Power Control Register */ |
161 | datareg = lasi_power_off_hpa + 0x0000C000; |
162 | |
163 | /* Power down the machine */ |
164 | gsc_writel(0x02, datareg); |
165 | } |
166 | |
167 | int __init |
168 | lasi_init_chip(struct parisc_device *dev) |
169 | { |
170 | struct gsc_asic *lasi; |
171 | struct gsc_irq gsc_irq; |
172 | int ret; |
173 | |
174 | lasi = kmalloc(sizeof(*lasi), GFP_KERNEL); |
175 | if (!lasi) |
176 | return -ENOMEM; |
177 | |
178 | lasi->name = "Lasi"; |
179 | lasi->hpa = dev->hpa; |
180 | |
181 | /* Check the 4-bit (yes, only 4) version register */ |
182 | lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf; |
183 | printk(KERN_INFO "%s version %d at 0x%lx found.\n", |
184 | lasi->name, lasi->version, lasi->hpa); |
185 | |
186 | /* initialize the chassis LEDs really early */ |
187 | lasi_led_init(lasi->hpa); |
188 | |
189 | /* Stop LASI barking for a bit */ |
190 | lasi_init_irq(lasi); |
191 | |
192 | /* the IRQ lasi should use */ |
193 | dev->irq = gsc_alloc_irq(&gsc_irq); |
194 | if (dev->irq < 0) { |
195 | printk(KERN_ERR "%s(): cannot get GSC irq\n", |
196 | __FUNCTION__); |
197 | kfree(lasi); |
198 | return -EBUSY; |
199 | } |
200 | |
201 | lasi->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; |
202 | |
203 | ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi); |
204 | if (ret < 0) { |
205 | kfree(lasi); |
206 | return ret; |
207 | } |
208 | |
209 | /* enable IRQ's for devices below LASI */ |
210 | gsc_writel(lasi->eim, lasi->hpa + OFFSET_IAR); |
211 | |
212 | /* Done init'ing, register this driver */ |
213 | ret = gsc_common_setup(dev, lasi); |
214 | if (ret) { |
215 | kfree(lasi); |
216 | return ret; |
217 | } |
218 | |
219 | gsc_fixup_irqs(dev, lasi, lasi_choose_irq); |
220 | |
221 | /* initialize the power off function */ |
222 | /* FIXME: Record the LASI HPA for the power off function. This should |
223 | * ensure that only the first LASI (the one controlling the power off) |
224 | * should set the HPA here */ |
225 | lasi_power_off_hpa = lasi->hpa; |
226 | pm_power_off = lasi_power_off; |
227 | |
228 | return ret; |
229 | } |
230 | |
231 | static struct parisc_device_id lasi_tbl[] = { |
232 | { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00081 }, |
233 | { 0, } |
234 | }; |
235 | |
236 | struct parisc_driver lasi_driver = { |
237 | .name = "Lasi", |
238 | .id_table = lasi_tbl, |
239 | .probe = lasi_init_chip, |
240 | }; |