• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/pcmcia/
1/*======================================================================
2
3    Device driver for Intel 82365 and compatible PC Card controllers.
4
5    i82365.c 1.265 1999/11/10 18:36:21
6
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/
11
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.
16
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.
20
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.
31
32======================================================================*/
33
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/ioport.h>
44#include <linux/delay.h>
45#include <linux/workqueue.h>
46#include <linux/interrupt.h>
47#include <linux/platform_device.h>
48#include <linux/bitops.h>
49#include <asm/irq.h>
50#include <asm/io.h>
51#include <asm/system.h>
52
53#include <pcmcia/ss.h>
54#include <pcmcia/cs.h>
55
56#include <linux/isapnp.h>
57
58/* ISA-bus controllers */
59#include "i82365.h"
60#include "cirrus.h"
61#include "vg468.h"
62#include "ricoh.h"
63
64
65static irqreturn_t i365_count_irq(int, void *);
66static inline int _check_irq(int irq, int flags)
67{
68    if (request_irq(irq, i365_count_irq, flags, "x", i365_count_irq) != 0)
69	return -1;
70    free_irq(irq, i365_count_irq);
71    return 0;
72}
73
74/*====================================================================*/
75
76/* Parameters that can be set with 'insmod' */
77
78/* Default base address for i82365sl and other ISA chips */
79static unsigned long i365_base = 0x3e0;
80/* Should we probe at 0x3e2 for an extra ISA controller? */
81static int extra_sockets = 0;
82/* Specify a socket number to ignore */
83static int ignore = -1;
84/* Bit map or list of interrupts to choose from */
85static u_int irq_mask = 0xffff;
86static int irq_list[16];
87static unsigned int irq_list_count;
88/* The card status change interrupt -- 0 means autoselect */
89static int cs_irq = 0;
90
91/* Probe for safe interrupts? */
92static int do_scan = 1;
93/* Poll status interval -- 0 means default to interrupt */
94static int poll_interval = 0;
95/* External clock time, in nanoseconds.  120 ns = 8.33 MHz */
96static int cycle_time = 120;
97
98/* Cirrus options */
99static int has_dma = -1;
100static int has_led = -1;
101static int has_ring = -1;
102static int dynamic_mode = 0;
103static int freq_bypass = -1;
104static int setup_time = -1;
105static int cmd_time = -1;
106static int recov_time = -1;
107
108/* Vadem options */
109static int async_clock = -1;
110static int cable_mode = -1;
111static int wakeup = 0;
112
113module_param(i365_base, ulong, 0444);
114module_param(ignore, int, 0444);
115module_param(extra_sockets, int, 0444);
116module_param(irq_mask, int, 0444);
117module_param_array(irq_list, int, &irq_list_count, 0444);
118module_param(cs_irq, int, 0444);
119module_param(async_clock, int, 0444);
120module_param(cable_mode, int, 0444);
121module_param(wakeup, int, 0444);
122
123module_param(do_scan, int, 0444);
124module_param(poll_interval, int, 0444);
125module_param(cycle_time, int, 0444);
126module_param(has_dma, int, 0444);
127module_param(has_led, int, 0444);
128module_param(has_ring, int, 0444);
129module_param(dynamic_mode, int, 0444);
130module_param(freq_bypass, int, 0444);
131module_param(setup_time, int, 0444);
132module_param(cmd_time, int, 0444);
133module_param(recov_time, int, 0444);
134
135/*====================================================================*/
136
137typedef struct cirrus_state_t {
138    u_char		misc1, misc2;
139    u_char		timer[6];
140} cirrus_state_t;
141
142typedef struct vg46x_state_t {
143    u_char		ctl, ema;
144} vg46x_state_t;
145
146struct i82365_socket {
147    u_short		type, flags;
148    struct pcmcia_socket	socket;
149    unsigned int	number;
150    unsigned int	ioaddr;
151    u_short		psock;
152    u_char		cs_irq, intr;
153    union {
154	cirrus_state_t		cirrus;
155	vg46x_state_t		vg46x;
156    } state;
157};
158
159/* Where we keep track of our sockets... */
160static int sockets = 0;
161static struct i82365_socket socket[8] = {
162    { 0, }, /* ... */
163};
164
165/* Default ISA interrupt mask */
166#define I365_MASK	0xdeb8	/* irq 15,14,12,11,10,9,7,5,4,3 */
167
168static int grab_irq;
169static DEFINE_SPINLOCK(isa_lock);
170#define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f)
171#define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f)
172
173static struct timer_list poll_timer;
174
175/*====================================================================*/
176
177/* These definitions must match the pcic table! */
178typedef enum pcic_id {
179    IS_I82365A, IS_I82365B, IS_I82365DF,
180    IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
181    IS_PD6710, IS_PD672X, IS_VT83C469,
182} pcic_id;
183
184/* Flags for classifying groups of controllers */
185#define IS_VADEM	0x0001
186#define IS_CIRRUS	0x0002
187#define IS_VIA		0x0010
188#define IS_UNKNOWN	0x0400
189#define IS_VG_PWR	0x0800
190#define IS_DF_PWR	0x1000
191#define IS_REGISTERED	0x2000
192#define IS_ALIVE	0x8000
193
194typedef struct pcic_t {
195    char		*name;
196    u_short		flags;
197} pcic_t;
198
199static pcic_t pcic[] = {
200    { "Intel i82365sl A step", 0 },
201    { "Intel i82365sl B step", 0 },
202    { "Intel i82365sl DF", IS_DF_PWR },
203    { "IBM Clone", 0 },
204    { "Ricoh RF5C296/396", 0 },
205    { "VLSI 82C146", 0 },
206    { "Vadem VG-468", IS_VADEM },
207    { "Vadem VG-469", IS_VADEM|IS_VG_PWR },
208    { "Cirrus PD6710", IS_CIRRUS },
209    { "Cirrus PD672x", IS_CIRRUS },
210    { "VIA VT83C469", IS_CIRRUS|IS_VIA },
211};
212
213#define PCIC_COUNT	(sizeof(pcic)/sizeof(pcic_t))
214
215/*====================================================================*/
216
217static DEFINE_SPINLOCK(bus_lock);
218
219static u_char i365_get(u_short sock, u_short reg)
220{
221    unsigned long flags;
222    spin_lock_irqsave(&bus_lock,flags);
223    {
224	unsigned int port = socket[sock].ioaddr;
225	u_char val;
226	reg = I365_REG(socket[sock].psock, reg);
227	outb(reg, port); val = inb(port+1);
228	spin_unlock_irqrestore(&bus_lock,flags);
229	return val;
230    }
231}
232
233static void i365_set(u_short sock, u_short reg, u_char data)
234{
235    unsigned long flags;
236    spin_lock_irqsave(&bus_lock,flags);
237    {
238	unsigned int port = socket[sock].ioaddr;
239	u_char val = I365_REG(socket[sock].psock, reg);
240	outb(val, port); outb(data, port+1);
241	spin_unlock_irqrestore(&bus_lock,flags);
242    }
243}
244
245static void i365_bset(u_short sock, u_short reg, u_char mask)
246{
247    u_char d = i365_get(sock, reg);
248    d |= mask;
249    i365_set(sock, reg, d);
250}
251
252static void i365_bclr(u_short sock, u_short reg, u_char mask)
253{
254    u_char d = i365_get(sock, reg);
255    d &= ~mask;
256    i365_set(sock, reg, d);
257}
258
259static void i365_bflip(u_short sock, u_short reg, u_char mask, int b)
260{
261    u_char d = i365_get(sock, reg);
262    if (b)
263	d |= mask;
264    else
265	d &= ~mask;
266    i365_set(sock, reg, d);
267}
268
269static u_short i365_get_pair(u_short sock, u_short reg)
270{
271    u_short a, b;
272    a = i365_get(sock, reg);
273    b = i365_get(sock, reg+1);
274    return (a + (b<<8));
275}
276
277static void i365_set_pair(u_short sock, u_short reg, u_short data)
278{
279    i365_set(sock, reg, data & 0xff);
280    i365_set(sock, reg+1, data >> 8);
281}
282
283/*======================================================================
284
285    Code to save and restore global state information for Cirrus
286    PD67xx controllers, and to set and report global configuration
287    options.
288
289    The VIA controllers also use these routines, as they are mostly
290    Cirrus lookalikes, without the timing registers.
291
292======================================================================*/
293
294#define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
295
296static void cirrus_get_state(u_short s)
297{
298    int i;
299    cirrus_state_t *p = &socket[s].state.cirrus;
300    p->misc1 = i365_get(s, PD67_MISC_CTL_1);
301    p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
302    p->misc2 = i365_get(s, PD67_MISC_CTL_2);
303    for (i = 0; i < 6; i++)
304	p->timer[i] = i365_get(s, PD67_TIME_SETUP(0)+i);
305}
306
307static void cirrus_set_state(u_short s)
308{
309    int i;
310    u_char misc;
311    cirrus_state_t *p = &socket[s].state.cirrus;
312
313    misc = i365_get(s, PD67_MISC_CTL_2);
314    i365_set(s, PD67_MISC_CTL_2, p->misc2);
315    if (misc & PD67_MC2_SUSPEND) mdelay(50);
316    misc = i365_get(s, PD67_MISC_CTL_1);
317    misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
318    i365_set(s, PD67_MISC_CTL_1, misc | p->misc1);
319    for (i = 0; i < 6; i++)
320	i365_set(s, PD67_TIME_SETUP(0)+i, p->timer[i]);
321}
322
323static u_int __init cirrus_set_opts(u_short s, char *buf)
324{
325    struct i82365_socket *t = &socket[s];
326    cirrus_state_t *p = &socket[s].state.cirrus;
327    u_int mask = 0xffff;
328
329    if (has_ring == -1) has_ring = 1;
330    flip(p->misc2, PD67_MC2_IRQ15_RI, has_ring);
331    flip(p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode);
332    flip(p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass);
333    if (p->misc2 & PD67_MC2_IRQ15_RI)
334	strcat(buf, " [ring]");
335    if (p->misc2 & PD67_MC2_DYNAMIC_MODE)
336	strcat(buf, " [dyn mode]");
337    if (p->misc2 & PD67_MC2_FREQ_BYPASS)
338	strcat(buf, " [freq bypass]");
339    if (p->misc1 & PD67_MC1_INPACK_ENA)
340	strcat(buf, " [inpack]");
341    if (p->misc2 & PD67_MC2_IRQ15_RI)
342	mask &= ~0x8000;
343    if (has_led > 0) {
344	strcat(buf, " [led]");
345	mask &= ~0x1000;
346    }
347    if (has_dma > 0) {
348	strcat(buf, " [dma]");
349	mask &= ~0x0600;
350    }
351    if (!(t->flags & IS_VIA)) {
352	if (setup_time >= 0)
353	    p->timer[0] = p->timer[3] = setup_time;
354	if (cmd_time > 0) {
355	    p->timer[1] = cmd_time;
356	    p->timer[4] = cmd_time*2+4;
357	}
358	if (p->timer[1] == 0) {
359	    p->timer[1] = 6; p->timer[4] = 16;
360	    if (p->timer[0] == 0)
361		p->timer[0] = p->timer[3] = 1;
362	}
363	if (recov_time >= 0)
364	    p->timer[2] = p->timer[5] = recov_time;
365	buf += strlen(buf);
366	sprintf(buf, " [%d/%d/%d] [%d/%d/%d]", p->timer[0], p->timer[1],
367		p->timer[2], p->timer[3], p->timer[4], p->timer[5]);
368    }
369    return mask;
370}
371
372/*======================================================================
373
374    Code to save and restore global state information for Vadem VG468
375    and VG469 controllers, and to set and report global configuration
376    options.
377
378======================================================================*/
379
380static void vg46x_get_state(u_short s)
381{
382    vg46x_state_t *p = &socket[s].state.vg46x;
383    p->ctl = i365_get(s, VG468_CTL);
384    if (socket[s].type == IS_VG469)
385	p->ema = i365_get(s, VG469_EXT_MODE);
386}
387
388static void vg46x_set_state(u_short s)
389{
390    vg46x_state_t *p = &socket[s].state.vg46x;
391    i365_set(s, VG468_CTL, p->ctl);
392    if (socket[s].type == IS_VG469)
393	i365_set(s, VG469_EXT_MODE, p->ema);
394}
395
396static u_int __init vg46x_set_opts(u_short s, char *buf)
397{
398    vg46x_state_t *p = &socket[s].state.vg46x;
399
400    flip(p->ctl, VG468_CTL_ASYNC, async_clock);
401    flip(p->ema, VG469_MODE_CABLE, cable_mode);
402    if (p->ctl & VG468_CTL_ASYNC)
403	strcat(buf, " [async]");
404    if (p->ctl & VG468_CTL_INPACK)
405	strcat(buf, " [inpack]");
406    if (socket[s].type == IS_VG469) {
407	u_char vsel = i365_get(s, VG469_VSELECT);
408	if (vsel & VG469_VSEL_EXT_STAT) {
409	    strcat(buf, " [ext mode]");
410	    if (vsel & VG469_VSEL_EXT_BUS)
411		strcat(buf, " [isa buf]");
412	}
413	if (p->ema & VG469_MODE_CABLE)
414	    strcat(buf, " [cable]");
415	if (p->ema & VG469_MODE_COMPAT)
416	    strcat(buf, " [c step]");
417    }
418    return 0xffff;
419}
420
421/*======================================================================
422
423    Generic routines to get and set controller options
424
425======================================================================*/
426
427static void get_bridge_state(u_short s)
428{
429    struct i82365_socket *t = &socket[s];
430    if (t->flags & IS_CIRRUS)
431	cirrus_get_state(s);
432    else if (t->flags & IS_VADEM)
433	vg46x_get_state(s);
434}
435
436static void set_bridge_state(u_short s)
437{
438    struct i82365_socket *t = &socket[s];
439    if (t->flags & IS_CIRRUS)
440	cirrus_set_state(s);
441    else {
442	i365_set(s, I365_GBLCTL, 0x00);
443	i365_set(s, I365_GENCTL, 0x00);
444    }
445    i365_bflip(s, I365_INTCTL, I365_INTR_ENA, t->intr);
446    if (t->flags & IS_VADEM)
447	vg46x_set_state(s);
448}
449
450static u_int __init set_bridge_opts(u_short s, u_short ns)
451{
452    u_short i;
453    u_int m = 0xffff;
454    char buf[128];
455
456    for (i = s; i < s+ns; i++) {
457	if (socket[i].flags & IS_ALIVE) {
458	    printk(KERN_INFO "    host opts [%d]: already alive!\n", i);
459	    continue;
460	}
461	buf[0] = '\0';
462	get_bridge_state(i);
463	if (socket[i].flags & IS_CIRRUS)
464	    m = cirrus_set_opts(i, buf);
465	else if (socket[i].flags & IS_VADEM)
466	    m = vg46x_set_opts(i, buf);
467	set_bridge_state(i);
468	printk(KERN_INFO "    host opts [%d]:%s\n", i,
469	       (*buf) ? buf : " none");
470    }
471    return m;
472}
473
474/*======================================================================
475
476    Interrupt testing code, for ISA and PCI interrupts
477
478======================================================================*/
479
480static volatile u_int irq_hits;
481static u_short irq_sock;
482
483static irqreturn_t i365_count_irq(int irq, void *dev)
484{
485    i365_get(irq_sock, I365_CSC);
486    irq_hits++;
487    pr_debug("i82365: -> hit on irq %d\n", irq);
488    return IRQ_HANDLED;
489}
490
491static u_int __init test_irq(u_short sock, int irq)
492{
493    pr_debug("i82365:  testing ISA irq %d\n", irq);
494    if (request_irq(irq, i365_count_irq, IRQF_PROBE_SHARED, "scan",
495			i365_count_irq) != 0)
496	return 1;
497    irq_hits = 0; irq_sock = sock;
498    msleep(10);
499    if (irq_hits) {
500	free_irq(irq, i365_count_irq);
501	pr_debug("i82365:    spurious hit!\n");
502	return 1;
503    }
504
505    /* Generate one interrupt */
506    i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));
507    i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
508    udelay(1000);
509
510    free_irq(irq, i365_count_irq);
511
512    /* mask all interrupts */
513    i365_set(sock, I365_CSCINT, 0);
514    pr_debug("i82365:    hits = %d\n", irq_hits);
515
516    return (irq_hits != 1);
517}
518
519static u_int __init isa_scan(u_short sock, u_int mask0)
520{
521    u_int mask1 = 0;
522    int i;
523
524#ifdef __alpha__
525#define PIC 0x4d0
526    /* Don't probe level-triggered interrupts -- reserved for PCI */
527    mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));
528#endif
529
530    if (do_scan) {
531	set_bridge_state(sock);
532	i365_set(sock, I365_CSCINT, 0);
533	for (i = 0; i < 16; i++)
534	    if ((mask0 & (1 << i)) && (test_irq(sock, i) == 0))
535		mask1 |= (1 << i);
536	for (i = 0; i < 16; i++)
537	    if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))
538		mask1 ^= (1 << i);
539    }
540
541    printk(KERN_INFO "    ISA irqs (");
542    if (mask1) {
543	printk("scanned");
544    } else {
545	/* Fallback: just find interrupts that aren't in use */
546	for (i = 0; i < 16; i++)
547	    if ((mask0 & (1 << i)) && (_check_irq(i, IRQF_PROBE_SHARED) == 0))
548		mask1 |= (1 << i);
549	printk("default");
550	/* If scan failed, default to polled status */
551	if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;
552    }
553    printk(") = ");
554
555    for (i = 0; i < 16; i++)
556	if (mask1 & (1<<i))
557	    printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
558    if (mask1 == 0) printk("none!");
559
560    return mask1;
561}
562
563/*====================================================================*/
564
565/* Time conversion functions */
566
567static int to_cycles(int ns)
568{
569    return ns/cycle_time;
570}
571
572/*====================================================================*/
573
574static int __init identify(unsigned int port, u_short sock)
575{
576    u_char val;
577    int type = -1;
578
579    /* Use the next free entry in the socket table */
580    socket[sockets].ioaddr = port;
581    socket[sockets].psock = sock;
582
583    /* Wake up a sleepy Cirrus controller */
584    if (wakeup) {
585	i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
586	/* Pause at least 50 ms */
587	mdelay(50);
588    }
589
590    if ((val = i365_get(sockets, I365_IDENT)) & 0x70)
591	return -1;
592    switch (val) {
593    case 0x82:
594	type = IS_I82365A; break;
595    case 0x83:
596	type = IS_I82365B; break;
597    case 0x84:
598	type = IS_I82365DF; break;
599    case 0x88: case 0x89: case 0x8a:
600	type = IS_IBM; break;
601    }
602
603    /* Check for Vadem VG-468 chips */
604    outb(0x0e, port);
605    outb(0x37, port);
606    i365_bset(sockets, VG468_MISC, VG468_MISC_VADEMREV);
607    val = i365_get(sockets, I365_IDENT);
608    if (val & I365_IDENT_VADEM) {
609	i365_bclr(sockets, VG468_MISC, VG468_MISC_VADEMREV);
610	type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468;
611    }
612
613    /* Check for Ricoh chips */
614    val = i365_get(sockets, RF5C_CHIP_ID);
615    if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))
616	type = IS_RF5Cx96;
617
618    /* Check for Cirrus CL-PD67xx chips */
619    i365_set(sockets, PD67_CHIP_INFO, 0);
620    val = i365_get(sockets, PD67_CHIP_INFO);
621    if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
622	val = i365_get(sockets, PD67_CHIP_INFO);
623	if ((val & PD67_INFO_CHIP_ID) == 0) {
624	    type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
625	    i365_set(sockets, PD67_EXT_INDEX, 0xe5);
626	    if (i365_get(sockets, PD67_EXT_INDEX) != 0xe5)
627		type = IS_VT83C469;
628	}
629    }
630    return type;
631} /* identify */
632
633/*======================================================================
634
635    See if a card is present, powered up, in IO mode, and already
636    bound to a (non PC Card) Linux driver.  We leave these alone.
637
638    We make an exception for cards that seem to be serial devices.
639
640======================================================================*/
641
642static int __init is_alive(u_short sock)
643{
644    u_char stat;
645    unsigned int start, stop;
646
647    stat = i365_get(sock, I365_STATUS);
648    start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
649    stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP);
650    if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) &&
651	(i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) &&
652	(i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) &&
653	((start & 0xfeef) != 0x02e8)) {
654	if (!request_region(start, stop-start+1, "i82365"))
655	    return 1;
656	release_region(start, stop-start+1);
657    }
658
659    return 0;
660}
661
662/*====================================================================*/
663
664static void __init add_socket(unsigned int port, int psock, int type)
665{
666    socket[sockets].ioaddr = port;
667    socket[sockets].psock = psock;
668    socket[sockets].type = type;
669    socket[sockets].flags = pcic[type].flags;
670    if (is_alive(sockets))
671	socket[sockets].flags |= IS_ALIVE;
672    sockets++;
673}
674
675static void __init add_pcic(int ns, int type)
676{
677    u_int mask = 0, i, base;
678    int isa_irq = 0;
679    struct i82365_socket *t = &socket[sockets-ns];
680
681    base = sockets-ns;
682    if (base == 0) printk("\n");
683    printk(KERN_INFO "  %s", pcic[type].name);
684    printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
685	       t->ioaddr, t->psock*0x40);
686    printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
687
688    /* Set host options, build basic interrupt mask */
689    if (irq_list_count == 0)
690	mask = irq_mask;
691    else
692	for (i = mask = 0; i < irq_list_count; i++)
693	    mask |= (1<<irq_list[i]);
694    mask &= I365_MASK & set_bridge_opts(base, ns);
695    /* Scan for ISA interrupts */
696    mask = isa_scan(base, mask);
697
698    /* Poll if only two interrupts available */
699    if (!poll_interval) {
700	u_int tmp = (mask & 0xff20);
701	tmp = tmp & (tmp-1);
702	if ((tmp & (tmp-1)) == 0)
703	    poll_interval = HZ;
704    }
705    /* Only try an ISA cs_irq if this is the first controller */
706    if (!grab_irq && (cs_irq || !poll_interval)) {
707	/* Avoid irq 12 unless it is explicitly requested */
708	u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
709	for (cs_irq = 15; cs_irq > 0; cs_irq--)
710	    if ((cs_mask & (1 << cs_irq)) &&
711		(_check_irq(cs_irq, IRQF_PROBE_SHARED) == 0))
712		break;
713	if (cs_irq) {
714	    grab_irq = 1;
715	    isa_irq = cs_irq;
716	    printk(" status change on irq %d\n", cs_irq);
717	}
718    }
719
720    if (!isa_irq) {
721	if (poll_interval == 0)
722	    poll_interval = HZ;
723	printk(" polling interval = %d ms\n",
724	       poll_interval * 1000 / HZ);
725
726    }
727
728    /* Update socket interrupt information, capabilities */
729    for (i = 0; i < ns; i++) {
730	t[i].socket.features |= SS_CAP_PCCARD;
731	t[i].socket.map_size = 0x1000;
732	t[i].socket.irq_mask = mask;
733	t[i].cs_irq = isa_irq;
734    }
735
736} /* add_pcic */
737
738/*====================================================================*/
739
740#ifdef CONFIG_PNP
741static struct isapnp_device_id id_table[] __initdata = {
742	{ 	ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
743		ISAPNP_FUNCTION(0x0e00), (unsigned long) "Intel 82365-Compatible" },
744	{ 	ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
745		ISAPNP_FUNCTION(0x0e01), (unsigned long) "Cirrus Logic CL-PD6720" },
746	{ 	ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
747		ISAPNP_FUNCTION(0x0e02), (unsigned long) "VLSI VL82C146" },
748	{	0 }
749};
750MODULE_DEVICE_TABLE(isapnp, id_table);
751
752static struct pnp_dev *i82365_pnpdev;
753#endif
754
755static void __init isa_probe(void)
756{
757    int i, j, sock, k, ns, id;
758    unsigned int port;
759#ifdef CONFIG_PNP
760    struct isapnp_device_id *devid;
761    struct pnp_dev *dev;
762
763    for (devid = id_table; devid->vendor; devid++) {
764	if ((dev = pnp_find_dev(NULL, devid->vendor, devid->function, NULL))) {
765
766	    if (pnp_device_attach(dev) < 0)
767	    	continue;
768
769	    if (pnp_activate_dev(dev) < 0) {
770		printk("activate failed\n");
771		pnp_device_detach(dev);
772		break;
773	    }
774
775	    if (!pnp_port_valid(dev, 0)) {
776		printk("invalid resources ?\n");
777		pnp_device_detach(dev);
778		break;
779	    }
780	    i365_base = pnp_port_start(dev, 0);
781	    i82365_pnpdev = dev;
782	    break;
783	}
784    }
785#endif
786
787    if (!request_region(i365_base, 2, "i82365")) {
788	if (sockets == 0)
789	    printk("port conflict at %#lx\n", i365_base);
790	return;
791    }
792
793    id = identify(i365_base, 0);
794    if ((id == IS_I82365DF) && (identify(i365_base, 1) != id)) {
795	for (i = 0; i < 4; i++) {
796	    if (i == ignore) continue;
797	    port = i365_base + ((i & 1) << 2) + ((i & 2) << 1);
798	    sock = (i & 1) << 1;
799	    if (identify(port, sock) == IS_I82365DF) {
800		add_socket(port, sock, IS_VLSI);
801		add_pcic(1, IS_VLSI);
802	    }
803	}
804    } else {
805	for (i = 0; i < 8; i += 2) {
806	    if (sockets && !extra_sockets && (i == 4))
807		break;
808	    port = i365_base + 2*(i>>2);
809	    sock = (i & 3);
810	    id = identify(port, sock);
811	    if (id < 0) continue;
812
813	    for (j = ns = 0; j < 2; j++) {
814		/* Does the socket exist? */
815		if ((ignore == i+j) || (identify(port, sock+j) < 0))
816		    continue;
817		/* Check for bad socket decode */
818		for (k = 0; k <= sockets; k++)
819		    i365_set(k, I365_MEM(0)+I365_W_OFF, k);
820		for (k = 0; k <= sockets; k++)
821		    if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k)
822			break;
823		if (k <= sockets) break;
824		add_socket(port, sock+j, id); ns++;
825	    }
826	    if (ns != 0) add_pcic(ns, id);
827	}
828    }
829}
830
831/*====================================================================*/
832
833static irqreturn_t pcic_interrupt(int irq, void *dev)
834{
835    int i, j, csc;
836    u_int events, active;
837    u_long flags = 0;
838    int handled = 0;
839
840    pr_debug("pcic_interrupt(%d)\n", irq);
841
842    for (j = 0; j < 20; j++) {
843	active = 0;
844	for (i = 0; i < sockets; i++) {
845	    if (socket[i].cs_irq != irq)
846		continue;
847	    handled = 1;
848	    ISA_LOCK(i, flags);
849	    csc = i365_get(i, I365_CSC);
850	    if ((csc == 0) || (i365_get(i, I365_IDENT) & 0x70)) {
851		ISA_UNLOCK(i, flags);
852		continue;
853	    }
854	    events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
855
856	    if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
857		events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
858	    else {
859		events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
860		events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
861		events |= (csc & I365_CSC_READY) ? SS_READY : 0;
862	    }
863	    ISA_UNLOCK(i, flags);
864	    pr_debug("socket %d event 0x%02x\n", i, events);
865
866	    if (events)
867		pcmcia_parse_events(&socket[i].socket, events);
868
869	    active |= events;
870	}
871	if (!active) break;
872    }
873    if (j == 20)
874	printk(KERN_NOTICE "i82365: infinite loop in interrupt handler\n");
875
876    pr_debug("pcic_interrupt done\n");
877    return IRQ_RETVAL(handled);
878} /* pcic_interrupt */
879
880static void pcic_interrupt_wrapper(u_long data)
881{
882    pcic_interrupt(0, NULL);
883    poll_timer.expires = jiffies + poll_interval;
884    add_timer(&poll_timer);
885}
886
887/*====================================================================*/
888
889static int i365_get_status(u_short sock, u_int *value)
890{
891    u_int status;
892
893    status = i365_get(sock, I365_STATUS);
894    *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
895	? SS_DETECT : 0;
896
897    if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
898	*value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
899    else {
900	*value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
901	*value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
902    }
903    *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
904    *value |= (status & I365_CS_READY) ? SS_READY : 0;
905    *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
906
907    if (socket[sock].type == IS_VG469) {
908	status = i365_get(sock, VG469_VSENSE);
909	if (socket[sock].psock & 1) {
910	    *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD;
911	    *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD;
912	} else {
913	    *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD;
914	    *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
915	}
916    }
917
918    pr_debug("GetStatus(%d) = %#4.4x\n", sock, *value);
919    return 0;
920} /* i365_get_status */
921
922/*====================================================================*/
923
924static int i365_set_socket(u_short sock, socket_state_t *state)
925{
926    struct i82365_socket *t = &socket[sock];
927    u_char reg;
928
929    pr_debug("SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
930	  "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
931	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
932
933    /* First set global controller options */
934    set_bridge_state(sock);
935
936    /* IO card, RESET flag, IO interrupt */
937    reg = t->intr;
938    reg |= state->io_irq;
939    reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
940    reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
941    i365_set(sock, I365_INTCTL, reg);
942
943    reg = I365_PWR_NORESET;
944    if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
945    if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
946
947    if (t->flags & IS_CIRRUS) {
948	if (state->Vpp != 0) {
949	    if (state->Vpp == 120)
950		reg |= I365_VPP1_12V;
951	    else if (state->Vpp == state->Vcc)
952		reg |= I365_VPP1_5V;
953	    else return -EINVAL;
954	}
955	if (state->Vcc != 0) {
956	    reg |= I365_VCC_5V;
957	    if (state->Vcc == 33)
958		i365_bset(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
959	    else if (state->Vcc == 50)
960		i365_bclr(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
961	    else return -EINVAL;
962	}
963    } else if (t->flags & IS_VG_PWR) {
964	if (state->Vpp != 0) {
965	    if (state->Vpp == 120)
966		reg |= I365_VPP1_12V;
967	    else if (state->Vpp == state->Vcc)
968		reg |= I365_VPP1_5V;
969	    else return -EINVAL;
970	}
971	if (state->Vcc != 0) {
972	    reg |= I365_VCC_5V;
973	    if (state->Vcc == 33)
974		i365_bset(sock, VG469_VSELECT, VG469_VSEL_VCC);
975	    else if (state->Vcc == 50)
976		i365_bclr(sock, VG469_VSELECT, VG469_VSEL_VCC);
977	    else return -EINVAL;
978	}
979    } else if (t->flags & IS_DF_PWR) {
980	switch (state->Vcc) {
981	case 0:		break;
982	case 33:   	reg |= I365_VCC_3V; break;
983	case 50:	reg |= I365_VCC_5V; break;
984	default:	return -EINVAL;
985	}
986	switch (state->Vpp) {
987	case 0:		break;
988	case 50:   	reg |= I365_VPP1_5V; break;
989	case 120:	reg |= I365_VPP1_12V; break;
990	default:	return -EINVAL;
991	}
992    } else {
993	switch (state->Vcc) {
994	case 0:		break;
995	case 50:	reg |= I365_VCC_5V; break;
996	default:	return -EINVAL;
997	}
998	switch (state->Vpp) {
999	case 0:		break;
1000	case 50:	reg |= I365_VPP1_5V | I365_VPP2_5V; break;
1001	case 120:	reg |= I365_VPP1_12V | I365_VPP2_12V; break;
1002	default:	return -EINVAL;
1003	}
1004    }
1005
1006    if (reg != i365_get(sock, I365_POWER))
1007	i365_set(sock, I365_POWER, reg);
1008
1009    /* Chipset-specific functions */
1010    if (t->flags & IS_CIRRUS) {
1011	/* Speaker control */
1012	i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
1013		   state->flags & SS_SPKR_ENA);
1014    }
1015
1016    /* Card status change interrupt mask */
1017    reg = t->cs_irq << 4;
1018    if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
1019    if (state->flags & SS_IOCARD) {
1020	if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
1021    } else {
1022	if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1;
1023	if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
1024	if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
1025    }
1026    i365_set(sock, I365_CSCINT, reg);
1027    i365_get(sock, I365_CSC);
1028
1029    return 0;
1030} /* i365_set_socket */
1031
1032/*====================================================================*/
1033
1034static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
1035{
1036    u_char map, ioctl;
1037
1038    pr_debug("SetIOMap(%d, %d, %#2.2x, %d ns, "
1039	  "%#llx-%#llx)\n", sock, io->map, io->flags, io->speed,
1040	  (unsigned long long)io->start, (unsigned long long)io->stop);
1041    map = io->map;
1042    if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
1043	(io->stop < io->start)) return -EINVAL;
1044    /* Turn off the window before changing anything */
1045    if (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(map))
1046	i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map));
1047    i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start);
1048    i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop);
1049    ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map);
1050    if (io->speed) ioctl |= I365_IOCTL_WAIT(map);
1051    if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
1052    if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
1053    if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
1054    i365_set(sock, I365_IOCTL, ioctl);
1055    /* Turn on the window if necessary */
1056    if (io->flags & MAP_ACTIVE)
1057	i365_bset(sock, I365_ADDRWIN, I365_ENA_IO(map));
1058    return 0;
1059} /* i365_set_io_map */
1060
1061/*====================================================================*/
1062
1063static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
1064{
1065    u_short base, i;
1066    u_char map;
1067
1068    pr_debug("SetMemMap(%d, %d, %#2.2x, %d ns, %#llx-%#llx, "
1069	  "%#x)\n", sock, mem->map, mem->flags, mem->speed,
1070	  (unsigned long long)mem->res->start,
1071	  (unsigned long long)mem->res->end, mem->card_start);
1072
1073    map = mem->map;
1074    if ((map > 4) || (mem->card_start > 0x3ffffff) ||
1075	(mem->res->start > mem->res->end) || (mem->speed > 1000))
1076	return -EINVAL;
1077    if ((mem->res->start > 0xffffff) || (mem->res->end > 0xffffff))
1078	return -EINVAL;
1079
1080    /* Turn off the window before changing anything */
1081    if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
1082	i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
1083
1084    base = I365_MEM(map);
1085    i = (mem->res->start >> 12) & 0x0fff;
1086    if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
1087    if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
1088    i365_set_pair(sock, base+I365_W_START, i);
1089
1090    i = (mem->res->end >> 12) & 0x0fff;
1091    switch (to_cycles(mem->speed)) {
1092    case 0:	break;
1093    case 1:	i |= I365_MEM_WS0; break;
1094    case 2:	i |= I365_MEM_WS1; break;
1095    default:	i |= I365_MEM_WS1 | I365_MEM_WS0; break;
1096    }
1097    i365_set_pair(sock, base+I365_W_STOP, i);
1098
1099    i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
1100    if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
1101    if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
1102    i365_set_pair(sock, base+I365_W_OFF, i);
1103
1104    /* Turn on the window if necessary */
1105    if (mem->flags & MAP_ACTIVE)
1106	i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
1107    return 0;
1108} /* i365_set_mem_map */
1109
1110
1111/*====================================================================*/
1112
1113/* this is horribly ugly... proper locking needs to be done here at
1114 * some time... */
1115#define LOCKED(x) do { \
1116	int retval; \
1117	unsigned long flags; \
1118	spin_lock_irqsave(&isa_lock, flags); \
1119	retval = x; \
1120	spin_unlock_irqrestore(&isa_lock, flags); \
1121	return retval; \
1122} while (0)
1123
1124
1125static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
1126{
1127	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
1128
1129	if (socket[sock].flags & IS_ALIVE) {
1130		*value = 0;
1131		return -EINVAL;
1132	}
1133
1134	LOCKED(i365_get_status(sock, value));
1135}
1136
1137static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
1138{
1139	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
1140
1141	if (socket[sock].flags & IS_ALIVE)
1142		return -EINVAL;
1143
1144	LOCKED(i365_set_socket(sock, state));
1145}
1146
1147static int pcic_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
1148{
1149	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
1150	if (socket[sock].flags & IS_ALIVE)
1151		return -EINVAL;
1152
1153	LOCKED(i365_set_io_map(sock, io));
1154}
1155
1156static int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
1157{
1158	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
1159	if (socket[sock].flags & IS_ALIVE)
1160		return -EINVAL;
1161
1162	LOCKED(i365_set_mem_map(sock, mem));
1163}
1164
1165static int pcic_init(struct pcmcia_socket *s)
1166{
1167	int i;
1168	struct resource res = { .start = 0, .end = 0x1000 };
1169	pccard_io_map io = { 0, 0, 0, 0, 1 };
1170	pccard_mem_map mem = { .res = &res, };
1171
1172	for (i = 0; i < 2; i++) {
1173		io.map = i;
1174		pcic_set_io_map(s, &io);
1175	}
1176	for (i = 0; i < 5; i++) {
1177		mem.map = i;
1178		pcic_set_mem_map(s, &mem);
1179	}
1180	return 0;
1181}
1182
1183
1184static struct pccard_operations pcic_operations = {
1185	.init			= pcic_init,
1186	.get_status		= pcic_get_status,
1187	.set_socket		= pcic_set_socket,
1188	.set_io_map		= pcic_set_io_map,
1189	.set_mem_map		= pcic_set_mem_map,
1190};
1191
1192/*====================================================================*/
1193
1194static struct platform_driver i82365_driver = {
1195	.driver = {
1196		.name = "i82365",
1197		.owner		= THIS_MODULE,
1198	},
1199};
1200
1201static struct platform_device *i82365_device;
1202
1203static int __init init_i82365(void)
1204{
1205    int i, ret;
1206
1207    ret = platform_driver_register(&i82365_driver);
1208    if (ret)
1209	goto err_out;
1210
1211    i82365_device = platform_device_alloc("i82365", 0);
1212    if (i82365_device) {
1213	    ret = platform_device_add(i82365_device);
1214	    if (ret)
1215		    platform_device_put(i82365_device);
1216    } else
1217	    ret = -ENOMEM;
1218
1219    if (ret)
1220	goto err_driver_unregister;
1221
1222    printk(KERN_INFO "Intel ISA PCIC probe: ");
1223    sockets = 0;
1224
1225    isa_probe();
1226
1227    if (sockets == 0) {
1228	printk("not found.\n");
1229	ret = -ENODEV;
1230	goto err_dev_unregister;
1231    }
1232
1233    /* Set up interrupt handler(s) */
1234    if (grab_irq != 0)
1235	ret = request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
1236
1237    if (ret)
1238	goto err_socket_release;
1239
1240    /* register sockets with the pcmcia core */
1241    for (i = 0; i < sockets; i++) {
1242	    socket[i].socket.dev.parent = &i82365_device->dev;
1243	    socket[i].socket.ops = &pcic_operations;
1244	    socket[i].socket.resource_ops = &pccard_nonstatic_ops;
1245	    socket[i].socket.owner = THIS_MODULE;
1246	    socket[i].number = i;
1247	    ret = pcmcia_register_socket(&socket[i].socket);
1248	    if (!ret)
1249		    socket[i].flags |= IS_REGISTERED;
1250
1251    }
1252
1253    /* Finally, schedule a polling interrupt */
1254    if (poll_interval != 0) {
1255	poll_timer.function = pcic_interrupt_wrapper;
1256	poll_timer.data = 0;
1257	init_timer(&poll_timer);
1258    	poll_timer.expires = jiffies + poll_interval;
1259	add_timer(&poll_timer);
1260    }
1261
1262    return 0;
1263err_socket_release:
1264    for (i = 0; i < sockets; i++) {
1265	/* Turn off all interrupt sources! */
1266	i365_set(i, I365_CSCINT, 0);
1267	release_region(socket[i].ioaddr, 2);
1268    }
1269err_dev_unregister:
1270    platform_device_unregister(i82365_device);
1271    release_region(i365_base, 2);
1272#ifdef CONFIG_PNP
1273    if (i82365_pnpdev)
1274	pnp_disable_dev(i82365_pnpdev);
1275#endif
1276err_driver_unregister:
1277    platform_driver_unregister(&i82365_driver);
1278err_out:
1279    return ret;
1280} /* init_i82365 */
1281
1282static void __exit exit_i82365(void)
1283{
1284    int i;
1285
1286    for (i = 0; i < sockets; i++) {
1287	    if (socket[i].flags & IS_REGISTERED)
1288		    pcmcia_unregister_socket(&socket[i].socket);
1289    }
1290    platform_device_unregister(i82365_device);
1291    if (poll_interval != 0)
1292	del_timer_sync(&poll_timer);
1293    if (grab_irq != 0)
1294	free_irq(cs_irq, pcic_interrupt);
1295    for (i = 0; i < sockets; i++) {
1296	/* Turn off all interrupt sources! */
1297	i365_set(i, I365_CSCINT, 0);
1298	release_region(socket[i].ioaddr, 2);
1299    }
1300    release_region(i365_base, 2);
1301#ifdef CONFIG_PNP
1302    if (i82365_pnpdev)
1303    		pnp_disable_dev(i82365_pnpdev);
1304#endif
1305    platform_driver_unregister(&i82365_driver);
1306} /* exit_i82365 */
1307
1308module_init(init_i82365);
1309module_exit(exit_i82365);
1310MODULE_LICENSE("Dual MPL/GPL");
1311/*====================================================================*/
1312