x86, apic: Fix spurious error interrupts triggering on all non-boot APs
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / pcmcia / i82365.c
blobc13fd9360511b89fe3b52f37477bb86a6dab5f1a
1 /*======================================================================
3 Device driver for Intel 82365 and compatible PC Card controllers.
5 i82365.c 1.265 1999/11/10 18:36:21
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in which
23 case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
32 ======================================================================*/
34 #include <linux/module.h>
35 #include <linux/moduleparam.h>
36 #include <linux/init.h>
37 #include <linux/types.h>
38 #include <linux/fcntl.h>
39 #include <linux/string.h>
40 #include <linux/kernel.h>
41 #include <linux/errno.h>
42 #include <linux/timer.h>
43 #include <linux/slab.h>
44 #include <linux/ioport.h>
45 #include <linux/delay.h>
46 #include <linux/workqueue.h>
47 #include <linux/interrupt.h>
48 #include <linux/platform_device.h>
49 #include <linux/bitops.h>
50 #include <asm/irq.h>
51 #include <asm/io.h>
52 #include <asm/system.h>
54 #include <pcmcia/cs_types.h>
55 #include <pcmcia/ss.h>
56 #include <pcmcia/cs.h>
58 #include <linux/isapnp.h>
60 /* ISA-bus controllers */
61 #include "i82365.h"
62 #include "cirrus.h"
63 #include "vg468.h"
64 #include "ricoh.h"
67 static irqreturn_t i365_count_irq(int, void *);
68 static inline int _check_irq(int irq, int flags)
70 if (request_irq(irq, i365_count_irq, flags, "x", i365_count_irq) != 0)
71 return -1;
72 free_irq(irq, i365_count_irq);
73 return 0;
76 /*====================================================================*/
78 /* Parameters that can be set with 'insmod' */
80 /* Default base address for i82365sl and other ISA chips */
81 static unsigned long i365_base = 0x3e0;
82 /* Should we probe at 0x3e2 for an extra ISA controller? */
83 static int extra_sockets = 0;
84 /* Specify a socket number to ignore */
85 static int ignore = -1;
86 /* Bit map or list of interrupts to choose from */
87 static u_int irq_mask = 0xffff;
88 static int irq_list[16];
89 static unsigned int irq_list_count;
90 /* The card status change interrupt -- 0 means autoselect */
91 static int cs_irq = 0;
93 /* Probe for safe interrupts? */
94 static int do_scan = 1;
95 /* Poll status interval -- 0 means default to interrupt */
96 static int poll_interval = 0;
97 /* External clock time, in nanoseconds. 120 ns = 8.33 MHz */
98 static int cycle_time = 120;
100 /* Cirrus options */
101 static int has_dma = -1;
102 static int has_led = -1;
103 static int has_ring = -1;
104 static int dynamic_mode = 0;
105 static int freq_bypass = -1;
106 static int setup_time = -1;
107 static int cmd_time = -1;
108 static int recov_time = -1;
110 /* Vadem options */
111 static int async_clock = -1;
112 static int cable_mode = -1;
113 static int wakeup = 0;
115 module_param(i365_base, ulong, 0444);
116 module_param(ignore, int, 0444);
117 module_param(extra_sockets, int, 0444);
118 module_param(irq_mask, int, 0444);
119 module_param_array(irq_list, int, &irq_list_count, 0444);
120 module_param(cs_irq, int, 0444);
121 module_param(async_clock, int, 0444);
122 module_param(cable_mode, int, 0444);
123 module_param(wakeup, int, 0444);
125 module_param(do_scan, int, 0444);
126 module_param(poll_interval, int, 0444);
127 module_param(cycle_time, int, 0444);
128 module_param(has_dma, int, 0444);
129 module_param(has_led, int, 0444);
130 module_param(has_ring, int, 0444);
131 module_param(dynamic_mode, int, 0444);
132 module_param(freq_bypass, int, 0444);
133 module_param(setup_time, int, 0444);
134 module_param(cmd_time, int, 0444);
135 module_param(recov_time, int, 0444);
137 /*====================================================================*/
139 typedef struct cirrus_state_t {
140 u_char misc1, misc2;
141 u_char timer[6];
142 } cirrus_state_t;
144 typedef struct vg46x_state_t {
145 u_char ctl, ema;
146 } vg46x_state_t;
148 struct i82365_socket {
149 u_short type, flags;
150 struct pcmcia_socket socket;
151 unsigned int number;
152 unsigned int ioaddr;
153 u_short psock;
154 u_char cs_irq, intr;
155 union {
156 cirrus_state_t cirrus;
157 vg46x_state_t vg46x;
158 } state;
161 /* Where we keep track of our sockets... */
162 static int sockets = 0;
163 static struct i82365_socket socket[8] = {
164 { 0, }, /* ... */
167 /* Default ISA interrupt mask */
168 #define I365_MASK 0xdeb8 /* irq 15,14,12,11,10,9,7,5,4,3 */
170 static int grab_irq;
171 static DEFINE_SPINLOCK(isa_lock);
172 #define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f)
173 #define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f)
175 static struct timer_list poll_timer;
177 /*====================================================================*/
179 /* These definitions must match the pcic table! */
180 typedef enum pcic_id {
181 IS_I82365A, IS_I82365B, IS_I82365DF,
182 IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
183 IS_PD6710, IS_PD672X, IS_VT83C469,
184 } pcic_id;
186 /* Flags for classifying groups of controllers */
187 #define IS_VADEM 0x0001
188 #define IS_CIRRUS 0x0002
189 #define IS_VIA 0x0010
190 #define IS_UNKNOWN 0x0400
191 #define IS_VG_PWR 0x0800
192 #define IS_DF_PWR 0x1000
193 #define IS_REGISTERED 0x2000
194 #define IS_ALIVE 0x8000
196 typedef struct pcic_t {
197 char *name;
198 u_short flags;
199 } pcic_t;
201 static pcic_t pcic[] = {
202 { "Intel i82365sl A step", 0 },
203 { "Intel i82365sl B step", 0 },
204 { "Intel i82365sl DF", IS_DF_PWR },
205 { "IBM Clone", 0 },
206 { "Ricoh RF5C296/396", 0 },
207 { "VLSI 82C146", 0 },
208 { "Vadem VG-468", IS_VADEM },
209 { "Vadem VG-469", IS_VADEM|IS_VG_PWR },
210 { "Cirrus PD6710", IS_CIRRUS },
211 { "Cirrus PD672x", IS_CIRRUS },
212 { "VIA VT83C469", IS_CIRRUS|IS_VIA },
215 #define PCIC_COUNT (sizeof(pcic)/sizeof(pcic_t))
217 /*====================================================================*/
219 static DEFINE_SPINLOCK(bus_lock);
221 static u_char i365_get(u_short sock, u_short reg)
223 unsigned long flags;
224 spin_lock_irqsave(&bus_lock,flags);
226 unsigned int port = socket[sock].ioaddr;
227 u_char val;
228 reg = I365_REG(socket[sock].psock, reg);
229 outb(reg, port); val = inb(port+1);
230 spin_unlock_irqrestore(&bus_lock,flags);
231 return val;
235 static void i365_set(u_short sock, u_short reg, u_char data)
237 unsigned long flags;
238 spin_lock_irqsave(&bus_lock,flags);
240 unsigned int port = socket[sock].ioaddr;
241 u_char val = I365_REG(socket[sock].psock, reg);
242 outb(val, port); outb(data, port+1);
243 spin_unlock_irqrestore(&bus_lock,flags);
247 static void i365_bset(u_short sock, u_short reg, u_char mask)
249 u_char d = i365_get(sock, reg);
250 d |= mask;
251 i365_set(sock, reg, d);
254 static void i365_bclr(u_short sock, u_short reg, u_char mask)
256 u_char d = i365_get(sock, reg);
257 d &= ~mask;
258 i365_set(sock, reg, d);
261 static void i365_bflip(u_short sock, u_short reg, u_char mask, int b)
263 u_char d = i365_get(sock, reg);
264 if (b)
265 d |= mask;
266 else
267 d &= ~mask;
268 i365_set(sock, reg, d);
271 static u_short i365_get_pair(u_short sock, u_short reg)
273 u_short a, b;
274 a = i365_get(sock, reg);
275 b = i365_get(sock, reg+1);
276 return (a + (b<<8));
279 static void i365_set_pair(u_short sock, u_short reg, u_short data)
281 i365_set(sock, reg, data & 0xff);
282 i365_set(sock, reg+1, data >> 8);
285 /*======================================================================
287 Code to save and restore global state information for Cirrus
288 PD67xx controllers, and to set and report global configuration
289 options.
291 The VIA controllers also use these routines, as they are mostly
292 Cirrus lookalikes, without the timing registers.
294 ======================================================================*/
296 #define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
298 static void cirrus_get_state(u_short s)
300 int i;
301 cirrus_state_t *p = &socket[s].state.cirrus;
302 p->misc1 = i365_get(s, PD67_MISC_CTL_1);
303 p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
304 p->misc2 = i365_get(s, PD67_MISC_CTL_2);
305 for (i = 0; i < 6; i++)
306 p->timer[i] = i365_get(s, PD67_TIME_SETUP(0)+i);
309 static void cirrus_set_state(u_short s)
311 int i;
312 u_char misc;
313 cirrus_state_t *p = &socket[s].state.cirrus;
315 misc = i365_get(s, PD67_MISC_CTL_2);
316 i365_set(s, PD67_MISC_CTL_2, p->misc2);
317 if (misc & PD67_MC2_SUSPEND) mdelay(50);
318 misc = i365_get(s, PD67_MISC_CTL_1);
319 misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
320 i365_set(s, PD67_MISC_CTL_1, misc | p->misc1);
321 for (i = 0; i < 6; i++)
322 i365_set(s, PD67_TIME_SETUP(0)+i, p->timer[i]);
325 static u_int __init cirrus_set_opts(u_short s, char *buf)
327 struct i82365_socket *t = &socket[s];
328 cirrus_state_t *p = &socket[s].state.cirrus;
329 u_int mask = 0xffff;
331 if (has_ring == -1) has_ring = 1;
332 flip(p->misc2, PD67_MC2_IRQ15_RI, has_ring);
333 flip(p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode);
334 flip(p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass);
335 if (p->misc2 & PD67_MC2_IRQ15_RI)
336 strcat(buf, " [ring]");
337 if (p->misc2 & PD67_MC2_DYNAMIC_MODE)
338 strcat(buf, " [dyn mode]");
339 if (p->misc2 & PD67_MC2_FREQ_BYPASS)
340 strcat(buf, " [freq bypass]");
341 if (p->misc1 & PD67_MC1_INPACK_ENA)
342 strcat(buf, " [inpack]");
343 if (p->misc2 & PD67_MC2_IRQ15_RI)
344 mask &= ~0x8000;
345 if (has_led > 0) {
346 strcat(buf, " [led]");
347 mask &= ~0x1000;
349 if (has_dma > 0) {
350 strcat(buf, " [dma]");
351 mask &= ~0x0600;
353 if (!(t->flags & IS_VIA)) {
354 if (setup_time >= 0)
355 p->timer[0] = p->timer[3] = setup_time;
356 if (cmd_time > 0) {
357 p->timer[1] = cmd_time;
358 p->timer[4] = cmd_time*2+4;
360 if (p->timer[1] == 0) {
361 p->timer[1] = 6; p->timer[4] = 16;
362 if (p->timer[0] == 0)
363 p->timer[0] = p->timer[3] = 1;
365 if (recov_time >= 0)
366 p->timer[2] = p->timer[5] = recov_time;
367 buf += strlen(buf);
368 sprintf(buf, " [%d/%d/%d] [%d/%d/%d]", p->timer[0], p->timer[1],
369 p->timer[2], p->timer[3], p->timer[4], p->timer[5]);
371 return mask;
374 /*======================================================================
376 Code to save and restore global state information for Vadem VG468
377 and VG469 controllers, and to set and report global configuration
378 options.
380 ======================================================================*/
382 static void vg46x_get_state(u_short s)
384 vg46x_state_t *p = &socket[s].state.vg46x;
385 p->ctl = i365_get(s, VG468_CTL);
386 if (socket[s].type == IS_VG469)
387 p->ema = i365_get(s, VG469_EXT_MODE);
390 static void vg46x_set_state(u_short s)
392 vg46x_state_t *p = &socket[s].state.vg46x;
393 i365_set(s, VG468_CTL, p->ctl);
394 if (socket[s].type == IS_VG469)
395 i365_set(s, VG469_EXT_MODE, p->ema);
398 static u_int __init vg46x_set_opts(u_short s, char *buf)
400 vg46x_state_t *p = &socket[s].state.vg46x;
402 flip(p->ctl, VG468_CTL_ASYNC, async_clock);
403 flip(p->ema, VG469_MODE_CABLE, cable_mode);
404 if (p->ctl & VG468_CTL_ASYNC)
405 strcat(buf, " [async]");
406 if (p->ctl & VG468_CTL_INPACK)
407 strcat(buf, " [inpack]");
408 if (socket[s].type == IS_VG469) {
409 u_char vsel = i365_get(s, VG469_VSELECT);
410 if (vsel & VG469_VSEL_EXT_STAT) {
411 strcat(buf, " [ext mode]");
412 if (vsel & VG469_VSEL_EXT_BUS)
413 strcat(buf, " [isa buf]");
415 if (p->ema & VG469_MODE_CABLE)
416 strcat(buf, " [cable]");
417 if (p->ema & VG469_MODE_COMPAT)
418 strcat(buf, " [c step]");
420 return 0xffff;
423 /*======================================================================
425 Generic routines to get and set controller options
427 ======================================================================*/
429 static void get_bridge_state(u_short s)
431 struct i82365_socket *t = &socket[s];
432 if (t->flags & IS_CIRRUS)
433 cirrus_get_state(s);
434 else if (t->flags & IS_VADEM)
435 vg46x_get_state(s);
438 static void set_bridge_state(u_short s)
440 struct i82365_socket *t = &socket[s];
441 if (t->flags & IS_CIRRUS)
442 cirrus_set_state(s);
443 else {
444 i365_set(s, I365_GBLCTL, 0x00);
445 i365_set(s, I365_GENCTL, 0x00);
447 i365_bflip(s, I365_INTCTL, I365_INTR_ENA, t->intr);
448 if (t->flags & IS_VADEM)
449 vg46x_set_state(s);
452 static u_int __init set_bridge_opts(u_short s, u_short ns)
454 u_short i;
455 u_int m = 0xffff;
456 char buf[128];
458 for (i = s; i < s+ns; i++) {
459 if (socket[i].flags & IS_ALIVE) {
460 printk(KERN_INFO " host opts [%d]: already alive!\n", i);
461 continue;
463 buf[0] = '\0';
464 get_bridge_state(i);
465 if (socket[i].flags & IS_CIRRUS)
466 m = cirrus_set_opts(i, buf);
467 else if (socket[i].flags & IS_VADEM)
468 m = vg46x_set_opts(i, buf);
469 set_bridge_state(i);
470 printk(KERN_INFO " host opts [%d]:%s\n", i,
471 (*buf) ? buf : " none");
473 return m;
476 /*======================================================================
478 Interrupt testing code, for ISA and PCI interrupts
480 ======================================================================*/
482 static volatile u_int irq_hits;
483 static u_short irq_sock;
485 static irqreturn_t i365_count_irq(int irq, void *dev)
487 i365_get(irq_sock, I365_CSC);
488 irq_hits++;
489 pr_debug("i82365: -> hit on irq %d\n", irq);
490 return IRQ_HANDLED;
493 static u_int __init test_irq(u_short sock, int irq)
495 pr_debug("i82365: testing ISA irq %d\n", irq);
496 if (request_irq(irq, i365_count_irq, IRQF_PROBE_SHARED, "scan",
497 i365_count_irq) != 0)
498 return 1;
499 irq_hits = 0; irq_sock = sock;
500 msleep(10);
501 if (irq_hits) {
502 free_irq(irq, i365_count_irq);
503 pr_debug("i82365: spurious hit!\n");
504 return 1;
507 /* Generate one interrupt */
508 i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));
509 i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
510 udelay(1000);
512 free_irq(irq, i365_count_irq);
514 /* mask all interrupts */
515 i365_set(sock, I365_CSCINT, 0);
516 pr_debug("i82365: hits = %d\n", irq_hits);
518 return (irq_hits != 1);
521 static u_int __init isa_scan(u_short sock, u_int mask0)
523 u_int mask1 = 0;
524 int i;
526 #ifdef __alpha__
527 #define PIC 0x4d0
528 /* Don't probe level-triggered interrupts -- reserved for PCI */
529 mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));
530 #endif
532 if (do_scan) {
533 set_bridge_state(sock);
534 i365_set(sock, I365_CSCINT, 0);
535 for (i = 0; i < 16; i++)
536 if ((mask0 & (1 << i)) && (test_irq(sock, i) == 0))
537 mask1 |= (1 << i);
538 for (i = 0; i < 16; i++)
539 if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))
540 mask1 ^= (1 << i);
543 printk(KERN_INFO " ISA irqs (");
544 if (mask1) {
545 printk("scanned");
546 } else {
547 /* Fallback: just find interrupts that aren't in use */
548 for (i = 0; i < 16; i++)
549 if ((mask0 & (1 << i)) && (_check_irq(i, IRQF_PROBE_SHARED) == 0))
550 mask1 |= (1 << i);
551 printk("default");
552 /* If scan failed, default to polled status */
553 if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;
555 printk(") = ");
557 for (i = 0; i < 16; i++)
558 if (mask1 & (1<<i))
559 printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
560 if (mask1 == 0) printk("none!");
562 return mask1;
565 /*====================================================================*/
567 /* Time conversion functions */
569 static int to_cycles(int ns)
571 return ns/cycle_time;
574 /*====================================================================*/
576 static int __init identify(unsigned int port, u_short sock)
578 u_char val;
579 int type = -1;
581 /* Use the next free entry in the socket table */
582 socket[sockets].ioaddr = port;
583 socket[sockets].psock = sock;
585 /* Wake up a sleepy Cirrus controller */
586 if (wakeup) {
587 i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
588 /* Pause at least 50 ms */
589 mdelay(50);
592 if ((val = i365_get(sockets, I365_IDENT)) & 0x70)
593 return -1;
594 switch (val) {
595 case 0x82:
596 type = IS_I82365A; break;
597 case 0x83:
598 type = IS_I82365B; break;
599 case 0x84:
600 type = IS_I82365DF; break;
601 case 0x88: case 0x89: case 0x8a:
602 type = IS_IBM; break;
605 /* Check for Vadem VG-468 chips */
606 outb(0x0e, port);
607 outb(0x37, port);
608 i365_bset(sockets, VG468_MISC, VG468_MISC_VADEMREV);
609 val = i365_get(sockets, I365_IDENT);
610 if (val & I365_IDENT_VADEM) {
611 i365_bclr(sockets, VG468_MISC, VG468_MISC_VADEMREV);
612 type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468;
615 /* Check for Ricoh chips */
616 val = i365_get(sockets, RF5C_CHIP_ID);
617 if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))
618 type = IS_RF5Cx96;
620 /* Check for Cirrus CL-PD67xx chips */
621 i365_set(sockets, PD67_CHIP_INFO, 0);
622 val = i365_get(sockets, PD67_CHIP_INFO);
623 if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
624 val = i365_get(sockets, PD67_CHIP_INFO);
625 if ((val & PD67_INFO_CHIP_ID) == 0) {
626 type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
627 i365_set(sockets, PD67_EXT_INDEX, 0xe5);
628 if (i365_get(sockets, PD67_EXT_INDEX) != 0xe5)
629 type = IS_VT83C469;
632 return type;
633 } /* identify */
635 /*======================================================================
637 See if a card is present, powered up, in IO mode, and already
638 bound to a (non PC Card) Linux driver. We leave these alone.
640 We make an exception for cards that seem to be serial devices.
642 ======================================================================*/
644 static int __init is_alive(u_short sock)
646 u_char stat;
647 unsigned int start, stop;
649 stat = i365_get(sock, I365_STATUS);
650 start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
651 stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP);
652 if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) &&
653 (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) &&
654 (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) &&
655 ((start & 0xfeef) != 0x02e8)) {
656 if (!request_region(start, stop-start+1, "i82365"))
657 return 1;
658 release_region(start, stop-start+1);
661 return 0;
664 /*====================================================================*/
666 static void __init add_socket(unsigned int port, int psock, int type)
668 socket[sockets].ioaddr = port;
669 socket[sockets].psock = psock;
670 socket[sockets].type = type;
671 socket[sockets].flags = pcic[type].flags;
672 if (is_alive(sockets))
673 socket[sockets].flags |= IS_ALIVE;
674 sockets++;
677 static void __init add_pcic(int ns, int type)
679 u_int mask = 0, i, base;
680 int isa_irq = 0;
681 struct i82365_socket *t = &socket[sockets-ns];
683 base = sockets-ns;
684 if (base == 0) printk("\n");
685 printk(KERN_INFO " %s", pcic[type].name);
686 printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
687 t->ioaddr, t->psock*0x40);
688 printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
690 /* Set host options, build basic interrupt mask */
691 if (irq_list_count == 0)
692 mask = irq_mask;
693 else
694 for (i = mask = 0; i < irq_list_count; i++)
695 mask |= (1<<irq_list[i]);
696 mask &= I365_MASK & set_bridge_opts(base, ns);
697 /* Scan for ISA interrupts */
698 mask = isa_scan(base, mask);
700 /* Poll if only two interrupts available */
701 if (!poll_interval) {
702 u_int tmp = (mask & 0xff20);
703 tmp = tmp & (tmp-1);
704 if ((tmp & (tmp-1)) == 0)
705 poll_interval = HZ;
707 /* Only try an ISA cs_irq if this is the first controller */
708 if (!grab_irq && (cs_irq || !poll_interval)) {
709 /* Avoid irq 12 unless it is explicitly requested */
710 u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
711 for (cs_irq = 15; cs_irq > 0; cs_irq--)
712 if ((cs_mask & (1 << cs_irq)) &&
713 (_check_irq(cs_irq, IRQF_PROBE_SHARED) == 0))
714 break;
715 if (cs_irq) {
716 grab_irq = 1;
717 isa_irq = cs_irq;
718 printk(" status change on irq %d\n", cs_irq);
722 if (!isa_irq) {
723 if (poll_interval == 0)
724 poll_interval = HZ;
725 printk(" polling interval = %d ms\n",
726 poll_interval * 1000 / HZ);
730 /* Update socket interrupt information, capabilities */
731 for (i = 0; i < ns; i++) {
732 t[i].socket.features |= SS_CAP_PCCARD;
733 t[i].socket.map_size = 0x1000;
734 t[i].socket.irq_mask = mask;
735 t[i].cs_irq = isa_irq;
738 } /* add_pcic */
740 /*====================================================================*/
742 #ifdef CONFIG_PNP
743 static struct isapnp_device_id id_table[] __initdata = {
744 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
745 ISAPNP_FUNCTION(0x0e00), (unsigned long) "Intel 82365-Compatible" },
746 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
747 ISAPNP_FUNCTION(0x0e01), (unsigned long) "Cirrus Logic CL-PD6720" },
748 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
749 ISAPNP_FUNCTION(0x0e02), (unsigned long) "VLSI VL82C146" },
750 { 0 }
752 MODULE_DEVICE_TABLE(isapnp, id_table);
754 static struct pnp_dev *i82365_pnpdev;
755 #endif
757 static void __init isa_probe(void)
759 int i, j, sock, k, ns, id;
760 unsigned int port;
761 #ifdef CONFIG_PNP
762 struct isapnp_device_id *devid;
763 struct pnp_dev *dev;
765 for (devid = id_table; devid->vendor; devid++) {
766 if ((dev = pnp_find_dev(NULL, devid->vendor, devid->function, NULL))) {
768 if (pnp_device_attach(dev) < 0)
769 continue;
771 if (pnp_activate_dev(dev) < 0) {
772 printk("activate failed\n");
773 pnp_device_detach(dev);
774 break;
777 if (!pnp_port_valid(dev, 0)) {
778 printk("invalid resources ?\n");
779 pnp_device_detach(dev);
780 break;
782 i365_base = pnp_port_start(dev, 0);
783 i82365_pnpdev = dev;
784 break;
787 #endif
789 if (!request_region(i365_base, 2, "i82365")) {
790 if (sockets == 0)
791 printk("port conflict at %#lx\n", i365_base);
792 return;
795 id = identify(i365_base, 0);
796 if ((id == IS_I82365DF) && (identify(i365_base, 1) != id)) {
797 for (i = 0; i < 4; i++) {
798 if (i == ignore) continue;
799 port = i365_base + ((i & 1) << 2) + ((i & 2) << 1);
800 sock = (i & 1) << 1;
801 if (identify(port, sock) == IS_I82365DF) {
802 add_socket(port, sock, IS_VLSI);
803 add_pcic(1, IS_VLSI);
806 } else {
807 for (i = 0; i < 8; i += 2) {
808 if (sockets && !extra_sockets && (i == 4))
809 break;
810 port = i365_base + 2*(i>>2);
811 sock = (i & 3);
812 id = identify(port, sock);
813 if (id < 0) continue;
815 for (j = ns = 0; j < 2; j++) {
816 /* Does the socket exist? */
817 if ((ignore == i+j) || (identify(port, sock+j) < 0))
818 continue;
819 /* Check for bad socket decode */
820 for (k = 0; k <= sockets; k++)
821 i365_set(k, I365_MEM(0)+I365_W_OFF, k);
822 for (k = 0; k <= sockets; k++)
823 if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k)
824 break;
825 if (k <= sockets) break;
826 add_socket(port, sock+j, id); ns++;
828 if (ns != 0) add_pcic(ns, id);
833 /*====================================================================*/
835 static irqreturn_t pcic_interrupt(int irq, void *dev)
837 int i, j, csc;
838 u_int events, active;
839 u_long flags = 0;
840 int handled = 0;
842 pr_debug("pcic_interrupt(%d)\n", irq);
844 for (j = 0; j < 20; j++) {
845 active = 0;
846 for (i = 0; i < sockets; i++) {
847 if (socket[i].cs_irq != irq)
848 continue;
849 handled = 1;
850 ISA_LOCK(i, flags);
851 csc = i365_get(i, I365_CSC);
852 if ((csc == 0) || (i365_get(i, I365_IDENT) & 0x70)) {
853 ISA_UNLOCK(i, flags);
854 continue;
856 events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
858 if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
859 events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
860 else {
861 events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
862 events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
863 events |= (csc & I365_CSC_READY) ? SS_READY : 0;
865 ISA_UNLOCK(i, flags);
866 pr_debug("socket %d event 0x%02x\n", i, events);
868 if (events)
869 pcmcia_parse_events(&socket[i].socket, events);
871 active |= events;
873 if (!active) break;
875 if (j == 20)
876 printk(KERN_NOTICE "i82365: infinite loop in interrupt handler\n");
878 pr_debug("pcic_interrupt done\n");
879 return IRQ_RETVAL(handled);
880 } /* pcic_interrupt */
882 static void pcic_interrupt_wrapper(u_long data)
884 pcic_interrupt(0, NULL);
885 poll_timer.expires = jiffies + poll_interval;
886 add_timer(&poll_timer);
889 /*====================================================================*/
891 static int i365_get_status(u_short sock, u_int *value)
893 u_int status;
895 status = i365_get(sock, I365_STATUS);
896 *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
897 ? SS_DETECT : 0;
899 if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
900 *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
901 else {
902 *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
903 *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
905 *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
906 *value |= (status & I365_CS_READY) ? SS_READY : 0;
907 *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
909 if (socket[sock].type == IS_VG469) {
910 status = i365_get(sock, VG469_VSENSE);
911 if (socket[sock].psock & 1) {
912 *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD;
913 *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD;
914 } else {
915 *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD;
916 *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
920 pr_debug("GetStatus(%d) = %#4.4x\n", sock, *value);
921 return 0;
922 } /* i365_get_status */
924 /*====================================================================*/
926 static int i365_set_socket(u_short sock, socket_state_t *state)
928 struct i82365_socket *t = &socket[sock];
929 u_char reg;
931 pr_debug("SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
932 "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
933 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
935 /* First set global controller options */
936 set_bridge_state(sock);
938 /* IO card, RESET flag, IO interrupt */
939 reg = t->intr;
940 reg |= state->io_irq;
941 reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
942 reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
943 i365_set(sock, I365_INTCTL, reg);
945 reg = I365_PWR_NORESET;
946 if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
947 if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
949 if (t->flags & IS_CIRRUS) {
950 if (state->Vpp != 0) {
951 if (state->Vpp == 120)
952 reg |= I365_VPP1_12V;
953 else if (state->Vpp == state->Vcc)
954 reg |= I365_VPP1_5V;
955 else return -EINVAL;
957 if (state->Vcc != 0) {
958 reg |= I365_VCC_5V;
959 if (state->Vcc == 33)
960 i365_bset(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
961 else if (state->Vcc == 50)
962 i365_bclr(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
963 else return -EINVAL;
965 } else if (t->flags & IS_VG_PWR) {
966 if (state->Vpp != 0) {
967 if (state->Vpp == 120)
968 reg |= I365_VPP1_12V;
969 else if (state->Vpp == state->Vcc)
970 reg |= I365_VPP1_5V;
971 else return -EINVAL;
973 if (state->Vcc != 0) {
974 reg |= I365_VCC_5V;
975 if (state->Vcc == 33)
976 i365_bset(sock, VG469_VSELECT, VG469_VSEL_VCC);
977 else if (state->Vcc == 50)
978 i365_bclr(sock, VG469_VSELECT, VG469_VSEL_VCC);
979 else return -EINVAL;
981 } else if (t->flags & IS_DF_PWR) {
982 switch (state->Vcc) {
983 case 0: break;
984 case 33: reg |= I365_VCC_3V; break;
985 case 50: reg |= I365_VCC_5V; break;
986 default: return -EINVAL;
988 switch (state->Vpp) {
989 case 0: break;
990 case 50: reg |= I365_VPP1_5V; break;
991 case 120: reg |= I365_VPP1_12V; break;
992 default: return -EINVAL;
994 } else {
995 switch (state->Vcc) {
996 case 0: break;
997 case 50: reg |= I365_VCC_5V; break;
998 default: return -EINVAL;
1000 switch (state->Vpp) {
1001 case 0: break;
1002 case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break;
1003 case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break;
1004 default: return -EINVAL;
1008 if (reg != i365_get(sock, I365_POWER))
1009 i365_set(sock, I365_POWER, reg);
1011 /* Chipset-specific functions */
1012 if (t->flags & IS_CIRRUS) {
1013 /* Speaker control */
1014 i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
1015 state->flags & SS_SPKR_ENA);
1018 /* Card status change interrupt mask */
1019 reg = t->cs_irq << 4;
1020 if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
1021 if (state->flags & SS_IOCARD) {
1022 if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
1023 } else {
1024 if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1;
1025 if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
1026 if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
1028 i365_set(sock, I365_CSCINT, reg);
1029 i365_get(sock, I365_CSC);
1031 return 0;
1032 } /* i365_set_socket */
1034 /*====================================================================*/
1036 static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
1038 u_char map, ioctl;
1040 pr_debug("SetIOMap(%d, %d, %#2.2x, %d ns, "
1041 "%#llx-%#llx)\n", sock, io->map, io->flags, io->speed,
1042 (unsigned long long)io->start, (unsigned long long)io->stop);
1043 map = io->map;
1044 if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
1045 (io->stop < io->start)) return -EINVAL;
1046 /* Turn off the window before changing anything */
1047 if (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(map))
1048 i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map));
1049 i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start);
1050 i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop);
1051 ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map);
1052 if (io->speed) ioctl |= I365_IOCTL_WAIT(map);
1053 if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
1054 if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
1055 if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
1056 i365_set(sock, I365_IOCTL, ioctl);
1057 /* Turn on the window if necessary */
1058 if (io->flags & MAP_ACTIVE)
1059 i365_bset(sock, I365_ADDRWIN, I365_ENA_IO(map));
1060 return 0;
1061 } /* i365_set_io_map */
1063 /*====================================================================*/
1065 static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
1067 u_short base, i;
1068 u_char map;
1070 pr_debug("SetMemMap(%d, %d, %#2.2x, %d ns, %#llx-%#llx, "
1071 "%#x)\n", sock, mem->map, mem->flags, mem->speed,
1072 (unsigned long long)mem->res->start,
1073 (unsigned long long)mem->res->end, mem->card_start);
1075 map = mem->map;
1076 if ((map > 4) || (mem->card_start > 0x3ffffff) ||
1077 (mem->res->start > mem->res->end) || (mem->speed > 1000))
1078 return -EINVAL;
1079 if ((mem->res->start > 0xffffff) || (mem->res->end > 0xffffff))
1080 return -EINVAL;
1082 /* Turn off the window before changing anything */
1083 if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
1084 i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
1086 base = I365_MEM(map);
1087 i = (mem->res->start >> 12) & 0x0fff;
1088 if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
1089 if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
1090 i365_set_pair(sock, base+I365_W_START, i);
1092 i = (mem->res->end >> 12) & 0x0fff;
1093 switch (to_cycles(mem->speed)) {
1094 case 0: break;
1095 case 1: i |= I365_MEM_WS0; break;
1096 case 2: i |= I365_MEM_WS1; break;
1097 default: i |= I365_MEM_WS1 | I365_MEM_WS0; break;
1099 i365_set_pair(sock, base+I365_W_STOP, i);
1101 i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
1102 if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
1103 if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
1104 i365_set_pair(sock, base+I365_W_OFF, i);
1106 /* Turn on the window if necessary */
1107 if (mem->flags & MAP_ACTIVE)
1108 i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
1109 return 0;
1110 } /* i365_set_mem_map */
1112 #if 0 /* driver model ordering issue */
1113 /*======================================================================
1115 Routines for accessing socket information and register dumps via
1116 /sys/class/pcmcia_socket/...
1118 ======================================================================*/
1120 static ssize_t show_info(struct class_device *class_dev, char *buf)
1122 struct i82365_socket *s = container_of(class_dev, struct i82365_socket, socket.dev);
1123 return sprintf(buf, "type: %s\npsock: %d\n",
1124 pcic[s->type].name, s->psock);
1127 static ssize_t show_exca(struct class_device *class_dev, char *buf)
1129 struct i82365_socket *s = container_of(class_dev, struct i82365_socket, socket.dev);
1130 unsigned short sock;
1131 int i;
1132 ssize_t ret = 0;
1133 unsigned long flags = 0;
1135 sock = s->number;
1137 ISA_LOCK(sock, flags);
1138 for (i = 0; i < 0x40; i += 4) {
1139 ret += sprintf(buf, "%02x %02x %02x %02x%s",
1140 i365_get(sock,i), i365_get(sock,i+1),
1141 i365_get(sock,i+2), i365_get(sock,i+3),
1142 ((i % 16) == 12) ? "\n" : " ");
1143 buf += ret;
1145 ISA_UNLOCK(sock, flags);
1147 return ret;
1150 static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL);
1151 static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);
1152 #endif
1154 /*====================================================================*/
1156 /* this is horribly ugly... proper locking needs to be done here at
1157 * some time... */
1158 #define LOCKED(x) do { \
1159 int retval; \
1160 unsigned long flags; \
1161 spin_lock_irqsave(&isa_lock, flags); \
1162 retval = x; \
1163 spin_unlock_irqrestore(&isa_lock, flags); \
1164 return retval; \
1165 } while (0)
1168 static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
1170 unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
1172 if (socket[sock].flags & IS_ALIVE) {
1173 *value = 0;
1174 return -EINVAL;
1177 LOCKED(i365_get_status(sock, value));
1180 static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
1182 unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
1184 if (socket[sock].flags & IS_ALIVE)
1185 return -EINVAL;
1187 LOCKED(i365_set_socket(sock, state));
1190 static int pcic_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
1192 unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
1193 if (socket[sock].flags & IS_ALIVE)
1194 return -EINVAL;
1196 LOCKED(i365_set_io_map(sock, io));
1199 static int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
1201 unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
1202 if (socket[sock].flags & IS_ALIVE)
1203 return -EINVAL;
1205 LOCKED(i365_set_mem_map(sock, mem));
1208 static int pcic_init(struct pcmcia_socket *s)
1210 int i;
1211 struct resource res = { .start = 0, .end = 0x1000 };
1212 pccard_io_map io = { 0, 0, 0, 0, 1 };
1213 pccard_mem_map mem = { .res = &res, };
1215 for (i = 0; i < 2; i++) {
1216 io.map = i;
1217 pcic_set_io_map(s, &io);
1219 for (i = 0; i < 5; i++) {
1220 mem.map = i;
1221 pcic_set_mem_map(s, &mem);
1223 return 0;
1226 static int i82365_drv_pcmcia_suspend(struct platform_device *dev,
1227 pm_message_t state)
1229 return pcmcia_socket_dev_suspend(&dev->dev);
1232 static int i82365_drv_pcmcia_resume(struct platform_device *dev)
1234 return pcmcia_socket_dev_resume(&dev->dev);
1236 static struct pccard_operations pcic_operations = {
1237 .init = pcic_init,
1238 .get_status = pcic_get_status,
1239 .set_socket = pcic_set_socket,
1240 .set_io_map = pcic_set_io_map,
1241 .set_mem_map = pcic_set_mem_map,
1244 /*====================================================================*/
1246 static struct platform_driver i82365_driver = {
1247 .driver = {
1248 .name = "i82365",
1249 .owner = THIS_MODULE,
1251 .suspend = i82365_drv_pcmcia_suspend,
1252 .resume = i82365_drv_pcmcia_resume,
1255 static struct platform_device *i82365_device;
1257 static int __init init_i82365(void)
1259 int i, ret;
1261 ret = platform_driver_register(&i82365_driver);
1262 if (ret)
1263 goto err_out;
1265 i82365_device = platform_device_alloc("i82365", 0);
1266 if (i82365_device) {
1267 ret = platform_device_add(i82365_device);
1268 if (ret)
1269 platform_device_put(i82365_device);
1270 } else
1271 ret = -ENOMEM;
1273 if (ret)
1274 goto err_driver_unregister;
1276 printk(KERN_INFO "Intel ISA PCIC probe: ");
1277 sockets = 0;
1279 isa_probe();
1281 if (sockets == 0) {
1282 printk("not found.\n");
1283 ret = -ENODEV;
1284 goto err_dev_unregister;
1287 /* Set up interrupt handler(s) */
1288 if (grab_irq != 0)
1289 ret = request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
1291 if (ret)
1292 goto err_socket_release;
1294 /* register sockets with the pcmcia core */
1295 for (i = 0; i < sockets; i++) {
1296 socket[i].socket.dev.parent = &i82365_device->dev;
1297 socket[i].socket.ops = &pcic_operations;
1298 socket[i].socket.resource_ops = &pccard_nonstatic_ops;
1299 socket[i].socket.owner = THIS_MODULE;
1300 socket[i].number = i;
1301 ret = pcmcia_register_socket(&socket[i].socket);
1302 if (!ret)
1303 socket[i].flags |= IS_REGISTERED;
1305 #if 0 /* driver model ordering issue */
1306 class_device_create_file(&socket[i].socket.dev,
1307 &class_device_attr_info);
1308 class_device_create_file(&socket[i].socket.dev,
1309 &class_device_attr_exca);
1310 #endif
1313 /* Finally, schedule a polling interrupt */
1314 if (poll_interval != 0) {
1315 poll_timer.function = pcic_interrupt_wrapper;
1316 poll_timer.data = 0;
1317 init_timer(&poll_timer);
1318 poll_timer.expires = jiffies + poll_interval;
1319 add_timer(&poll_timer);
1322 return 0;
1323 err_socket_release:
1324 for (i = 0; i < sockets; i++) {
1325 /* Turn off all interrupt sources! */
1326 i365_set(i, I365_CSCINT, 0);
1327 release_region(socket[i].ioaddr, 2);
1329 err_dev_unregister:
1330 platform_device_unregister(i82365_device);
1331 release_region(i365_base, 2);
1332 #ifdef CONFIG_PNP
1333 if (i82365_pnpdev)
1334 pnp_disable_dev(i82365_pnpdev);
1335 #endif
1336 err_driver_unregister:
1337 platform_driver_unregister(&i82365_driver);
1338 err_out:
1339 return ret;
1340 } /* init_i82365 */
1342 static void __exit exit_i82365(void)
1344 int i;
1346 for (i = 0; i < sockets; i++) {
1347 if (socket[i].flags & IS_REGISTERED)
1348 pcmcia_unregister_socket(&socket[i].socket);
1350 platform_device_unregister(i82365_device);
1351 if (poll_interval != 0)
1352 del_timer_sync(&poll_timer);
1353 if (grab_irq != 0)
1354 free_irq(cs_irq, pcic_interrupt);
1355 for (i = 0; i < sockets; i++) {
1356 /* Turn off all interrupt sources! */
1357 i365_set(i, I365_CSCINT, 0);
1358 release_region(socket[i].ioaddr, 2);
1360 release_region(i365_base, 2);
1361 #ifdef CONFIG_PNP
1362 if (i82365_pnpdev)
1363 pnp_disable_dev(i82365_pnpdev);
1364 #endif
1365 platform_driver_unregister(&i82365_driver);
1366 } /* exit_i82365 */
1368 module_init(init_i82365);
1369 module_exit(exit_i82365);
1370 MODULE_LICENSE("Dual MPL/GPL");
1371 /*====================================================================*/