diff options
Diffstat (limited to 'drivers/pcmcia/yenta_socket.c')
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 6404d97a12eb..bee05362fd24 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -32,6 +32,14 @@ static int disable_clkrun; | |||
32 | module_param(disable_clkrun, bool, 0444); | 32 | module_param(disable_clkrun, bool, 0444); |
33 | MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option"); | 33 | MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option"); |
34 | 34 | ||
35 | static int isa_probe = 1; | ||
36 | module_param(isa_probe, bool, 0444); | ||
37 | MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing"); | ||
38 | |||
39 | static int pwr_irqs_off; | ||
40 | module_param(pwr_irqs_off, bool, 0644); | ||
41 | MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!"); | ||
42 | |||
35 | #if 0 | 43 | #if 0 |
36 | #define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args) | 44 | #define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args) |
37 | #else | 45 | #else |
@@ -150,15 +158,16 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) | |||
150 | 158 | ||
151 | val = (state & CB_3VCARD) ? SS_3VCARD : 0; | 159 | val = (state & CB_3VCARD) ? SS_3VCARD : 0; |
152 | val |= (state & CB_XVCARD) ? SS_XVCARD : 0; | 160 | val |= (state & CB_XVCARD) ? SS_XVCARD : 0; |
153 | val |= (state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD | 161 | val |= (state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; |
154 | | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; | 162 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? SS_PENDING : 0; |
163 | |||
155 | 164 | ||
156 | if (state & CB_CBCARD) { | 165 | if (state & CB_CBCARD) { |
157 | val |= SS_CARDBUS; | 166 | val |= SS_CARDBUS; |
158 | val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; | 167 | val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; |
159 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; | 168 | val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; |
160 | val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; | 169 | val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; |
161 | } else { | 170 | } else if (state & CB_16BITCARD) { |
162 | u8 status = exca_readb(socket, I365_STATUS); | 171 | u8 status = exca_readb(socket, I365_STATUS); |
163 | val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; | 172 | val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; |
164 | if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { | 173 | if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { |
@@ -405,11 +414,13 @@ static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map * | |||
405 | } | 414 | } |
406 | 415 | ||
407 | 416 | ||
408 | static unsigned int yenta_events(struct yenta_socket *socket) | 417 | |
418 | static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
409 | { | 419 | { |
420 | unsigned int events; | ||
421 | struct yenta_socket *socket = (struct yenta_socket *) dev_id; | ||
410 | u8 csc; | 422 | u8 csc; |
411 | u32 cb_event; | 423 | u32 cb_event; |
412 | unsigned int events; | ||
413 | 424 | ||
414 | /* Clear interrupt status for the event */ | 425 | /* Clear interrupt status for the event */ |
415 | cb_event = cb_readl(socket, CB_SOCKET_EVENT); | 426 | cb_event = cb_readl(socket, CB_SOCKET_EVENT); |
@@ -426,20 +437,13 @@ static unsigned int yenta_events(struct yenta_socket *socket) | |||
426 | events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; | 437 | events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; |
427 | events |= (csc & I365_CSC_READY) ? SS_READY : 0; | 438 | events |= (csc & I365_CSC_READY) ? SS_READY : 0; |
428 | } | 439 | } |
429 | return events; | ||
430 | } | ||
431 | |||
432 | |||
433 | static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
434 | { | ||
435 | unsigned int events; | ||
436 | struct yenta_socket *socket = (struct yenta_socket *) dev_id; | ||
437 | 440 | ||
438 | events = yenta_events(socket); | 441 | if (events) |
439 | if (events) { | ||
440 | pcmcia_parse_events(&socket->socket, events); | 442 | pcmcia_parse_events(&socket->socket, events); |
443 | |||
444 | if (cb_event || csc) | ||
441 | return IRQ_HANDLED; | 445 | return IRQ_HANDLED; |
442 | } | 446 | |
443 | return IRQ_NONE; | 447 | return IRQ_NONE; |
444 | } | 448 | } |
445 | 449 | ||
@@ -470,11 +474,22 @@ static void yenta_clear_maps(struct yenta_socket *socket) | |||
470 | } | 474 | } |
471 | } | 475 | } |
472 | 476 | ||
477 | /* redoes voltage interrogation if required */ | ||
478 | static void yenta_interrogate(struct yenta_socket *socket) | ||
479 | { | ||
480 | u32 state; | ||
481 | |||
482 | state = cb_readl(socket, CB_SOCKET_STATE); | ||
483 | if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) || | ||
484 | (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) || | ||
485 | ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD))) | ||
486 | cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); | ||
487 | } | ||
488 | |||
473 | /* Called at resume and initialization events */ | 489 | /* Called at resume and initialization events */ |
474 | static int yenta_sock_init(struct pcmcia_socket *sock) | 490 | static int yenta_sock_init(struct pcmcia_socket *sock) |
475 | { | 491 | { |
476 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | 492 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); |
477 | u32 state; | ||
478 | u16 bridge; | 493 | u16 bridge; |
479 | 494 | ||
480 | bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR; | 495 | bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR; |
@@ -486,10 +501,7 @@ static int yenta_sock_init(struct pcmcia_socket *sock) | |||
486 | exca_writeb(socket, I365_GENCTL, 0x00); | 501 | exca_writeb(socket, I365_GENCTL, 0x00); |
487 | 502 | ||
488 | /* Redo card voltage interrogation */ | 503 | /* Redo card voltage interrogation */ |
489 | state = cb_readl(socket, CB_SOCKET_STATE); | 504 | yenta_interrogate(socket); |
490 | if (!(state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | | ||
491 | CB_3VCARD | CB_XVCARD | CB_YVCARD))) | ||
492 | cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); | ||
493 | 505 | ||
494 | yenta_clear_maps(socket); | 506 | yenta_clear_maps(socket); |
495 | 507 | ||
@@ -856,7 +868,10 @@ static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_i | |||
856 | socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS; | 868 | socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS; |
857 | socket->socket.map_size = 0x1000; | 869 | socket->socket.map_size = 0x1000; |
858 | socket->socket.pci_irq = socket->cb_irq; | 870 | socket->socket.pci_irq = socket->cb_irq; |
859 | socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); | 871 | if (isa_probe) |
872 | socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); | ||
873 | else | ||
874 | socket->socket.irq_mask = 0; | ||
860 | socket->socket.cb_dev = socket->dev; | 875 | socket->socket.cb_dev = socket->dev; |
861 | 876 | ||
862 | printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n", | 877 | printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n", |
@@ -996,6 +1011,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i | |||
996 | } | 1011 | } |
997 | 1012 | ||
998 | /* Figure out what the dang thing can do for the PCMCIA layer... */ | 1013 | /* Figure out what the dang thing can do for the PCMCIA layer... */ |
1014 | yenta_interrogate(socket); | ||
999 | yenta_get_socket_capabilities(socket, isa_interrupts); | 1015 | yenta_get_socket_capabilities(socket, isa_interrupts); |
1000 | printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); | 1016 | printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); |
1001 | 1017 | ||