10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/pci.h>
17 #include <linux/device.h>
37 #define to_cycles(ns) ((ns)/120)
40 #define NO_IRQ ((unsigned int)(0))
51 static int irq_mode = 1;
55 "interrupt delivery mode. 0 = ISA, 1 = PCI. default is 1");
69 reg += socket->
number * 0x40;
73 spin_unlock_irqrestore(&port_lock, flags);
86 reg = reg + socket->
number * 0x40;
92 tmp = tmp | (
inb(port + 1) << 8);
93 spin_unlock_irqrestore(&port_lock, flags);
105 reg = reg + socket->
number * 0x40;
108 outb(value, port + 1);
109 spin_unlock_irqrestore(&port_lock, flags);
120 reg = reg + socket->
number * 0x40;
127 spin_unlock_irqrestore(&port_lock, flags);
138 reg = reg + socket->
number * 0x40;
145 spin_unlock_irqrestore(&port_lock, flags);
149 unsigned short value)
156 reg = reg + socket->
number * 0x40;
168 spin_unlock_irqrestore(&port_lock, flags);
183 if (loopcount > 20) {
195 csc = indirect_read(&socket[i],
I365_CSC);
205 "Card detected in socket %i!\n", i);
237 static void pd6729_interrupt_wrapper(
unsigned long data)
241 pd6729_interrupt(0, (
void *)socket);
285 t = (socket->
number) ? socket : socket + 1;
330 switch (state->
Vcc) {
335 "setting voltage to Vcc to 3.3V on socket %i\n",
342 "setting voltage to Vcc to 5V on socket %i\n",
349 "pd6729_set_socket called with invalid VCC power "
350 "value: %i\n", state->
Vcc);
354 switch (state->
Vpp) {
356 dev_dbg(&sock->
dev,
"not setting Vpp on socket %i\n",
361 dev_dbg(&sock->
dev,
"setting Vpp to Vcc for socket %i\n",
370 dev_dbg(&sock->
dev,
"pd6729: pd6729_set_socket called with "
371 "invalid VPP power value: %i\n", state->
Vpp);
427 unsigned char map, ioctl;
433 dev_dbg(&sock->
dev,
"pd6729_set_io_map with invalid map\n");
471 unsigned short base,
i;
480 if ((mem->
res->start > mem->
res->end) || (mem->
speed > 1000)) {
481 dev_warn(&sock->
dev,
"invalid invalid address / speed\n");
491 i = (mem->
res->start >> 12) & 0x0fff;
500 i = (mem->
res->end >> 12) & 0x0fff;
534 indirect_write16(socket, base +
I365_W_OFF, i);
551 for (i = 0; i < 2; i++) {
553 pd6729_set_io_map(sock, &io);
555 for (i = 0; i < 5; i++) {
557 pd6729_set_mem_map(sock, &mem);
567 .get_status = pd6729_get_status,
568 .set_socket = pd6729_set_socket,
569 .set_io_map = pd6729_set_io_map,
570 .set_mem_map = pd6729_set_mem_map,
575 pr_devel(
"-> hit on irq %d\n", irq);
579 static int pd6729_check_irq(
int irq)
599 "PCI status changes\n");
606 for (i = 0; i < 16; i++)
607 if ((mask0 & (1 << i)) && (pd6729_check_irq(i) == 0))
611 for (i = 0; i < 16; i++)
613 printk(
"%s%d", ((mask & ((1<<i)-1)) ?
"," :
""), i);
618 printk(
" polling status changes.\n");
634 dev_warn(&dev->
dev,
"failed to kzalloc socket.\n");
640 dev_warn(&dev->
dev,
"failed to enable pci_device.\n");
641 goto err_out_free_mem;
645 dev_warn(&dev->
dev,
"refusing to load the driver as the "
646 "io_base is NULL.\n");
647 goto err_out_disable;
650 dev_info(&dev->
dev,
"Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx "
657 pci_read_config_byte(dev,
PCI_COMMAND, &configbyte);
659 dev_dbg(&dev->
dev,
"pd6729: Enabling PCI_COMMAND_MEMORY.\n");
661 pci_write_config_byte(dev,
PCI_COMMAND, configbyte);
666 dev_warn(&dev->
dev,
"pci request region failed.\n");
667 goto err_out_disable;
673 mask = pd6729_isa_scan();
674 if (irq_mode == 0 && mask == 0) {
675 dev_warn(&dev->
dev,
"no ISA interrupt is available.\n");
676 goto err_out_free_res;
682 socket[
i].
socket.map_size = 0x1000;
690 socket[
i].
socket.ops = &pd6729_operations;
693 socket[
i].
socket.driver_data = &socket[
i];
696 pci_set_drvdata(dev, socket);
702 dev_err(&dev->
dev,
"Failed to register irq %d\n",
704 goto err_out_free_res;
709 socket->
poll_timer.function = pd6729_interrupt_wrapper;
718 dev_warn(&dev->
dev,
"pcmcia_register_socket failed.\n");
719 for (j = 0; j <
i ; j++)
721 goto err_out_free_res2;
771 static struct pci_driver pd6729_pci_driver = {
773 .id_table = pd6729_pci_ids,
774 .probe = pd6729_pci_probe,
778 static int pd6729_module_init(
void)
780 return pci_register_driver(&pd6729_pci_driver);
783 static void pd6729_module_exit(
void)