11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Driver for the Cirrus PD6729 PCI-PCMCIA bridge. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Based on the i82092.c driver. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This software may be used and distributed according to the terms of 71da177e4SLinus Torvalds * the GNU General Public License, incorporated herein by reference. 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds 101da177e4SLinus Torvalds #include <linux/kernel.h> 111da177e4SLinus Torvalds #include <linux/config.h> 121da177e4SLinus Torvalds #include <linux/module.h> 131da177e4SLinus Torvalds #include <linux/pci.h> 141da177e4SLinus Torvalds #include <linux/init.h> 151da177e4SLinus Torvalds #include <linux/workqueue.h> 161da177e4SLinus Torvalds #include <linux/interrupt.h> 171da177e4SLinus Torvalds #include <linux/device.h> 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds #include <pcmcia/cs_types.h> 201da177e4SLinus Torvalds #include <pcmcia/ss.h> 211da177e4SLinus Torvalds #include <pcmcia/cs.h> 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds #include <asm/system.h> 241da177e4SLinus Torvalds #include <asm/io.h> 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds #include "pd6729.h" 271da177e4SLinus Torvalds #include "i82365.h" 281da177e4SLinus Torvalds #include "cirrus.h" 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 311da177e4SLinus Torvalds MODULE_DESCRIPTION("Driver for the Cirrus PD6729 PCI-PCMCIA bridge"); 321da177e4SLinus Torvalds MODULE_AUTHOR("Jun Komuro <komurojun-mbn@nifty.com>"); 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds #define MAX_SOCKETS 2 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds /* 371da177e4SLinus Torvalds * simple helper functions 381da177e4SLinus Torvalds * External clock time, in nanoseconds. 120 ns = 8.33 MHz 391da177e4SLinus Torvalds */ 401da177e4SLinus Torvalds #define to_cycles(ns) ((ns)/120) 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds #ifndef NO_IRQ 431da177e4SLinus Torvalds #define NO_IRQ ((unsigned int)(0)) 441da177e4SLinus Torvalds #endif 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds /* 471da177e4SLinus Torvalds * PARAMETERS 481da177e4SLinus Torvalds * irq_mode=n 491da177e4SLinus Torvalds * Specifies the interrupt delivery mode. The default (1) is to use PCI 501da177e4SLinus Torvalds * interrupts; a value of 0 selects ISA interrupts. This must be set for 511da177e4SLinus Torvalds * correct operation of PCI card readers. 521da177e4SLinus Torvalds * 531da177e4SLinus Torvalds * irq_list=i,j,... 541da177e4SLinus Torvalds * This list limits the set of interrupts that can be used by PCMCIA 551da177e4SLinus Torvalds * cards. 561da177e4SLinus Torvalds * The default list is 3,4,5,7,9,10,11. 571da177e4SLinus Torvalds * (irq_list parameter is not used, if irq_mode = 1) 581da177e4SLinus Torvalds */ 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds static int irq_mode = 1; /* 0 = ISA interrupt, 1 = PCI interrupt */ 611da177e4SLinus Torvalds static int irq_list[16]; 621da177e4SLinus Torvalds static int irq_list_count = 0; 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds module_param(irq_mode, int, 0444); 651da177e4SLinus Torvalds module_param_array(irq_list, int, &irq_list_count, 0444); 661da177e4SLinus Torvalds MODULE_PARM_DESC(irq_mode, 671da177e4SLinus Torvalds "interrupt delivery mode. 0 = ISA, 1 = PCI. default is 1"); 681da177e4SLinus Torvalds MODULE_PARM_DESC(irq_list, "interrupts that can be used by PCMCIA cards"); 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds static DEFINE_SPINLOCK(port_lock); 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds /* basic value read/write functions */ 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds static unsigned char indirect_read(struct pd6729_socket *socket, 751da177e4SLinus Torvalds unsigned short reg) 761da177e4SLinus Torvalds { 771da177e4SLinus Torvalds unsigned long port; 781da177e4SLinus Torvalds unsigned char val; 791da177e4SLinus Torvalds unsigned long flags; 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds spin_lock_irqsave(&port_lock, flags); 821da177e4SLinus Torvalds reg += socket->number * 0x40; 831da177e4SLinus Torvalds port = socket->io_base; 841da177e4SLinus Torvalds outb(reg, port); 851da177e4SLinus Torvalds val = inb(port + 1); 861da177e4SLinus Torvalds spin_unlock_irqrestore(&port_lock, flags); 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds return val; 891da177e4SLinus Torvalds } 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds static unsigned short indirect_read16(struct pd6729_socket *socket, 921da177e4SLinus Torvalds unsigned short reg) 931da177e4SLinus Torvalds { 941da177e4SLinus Torvalds unsigned long port; 951da177e4SLinus Torvalds unsigned short tmp; 961da177e4SLinus Torvalds unsigned long flags; 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds spin_lock_irqsave(&port_lock, flags); 991da177e4SLinus Torvalds reg = reg + socket->number * 0x40; 1001da177e4SLinus Torvalds port = socket->io_base; 1011da177e4SLinus Torvalds outb(reg, port); 1021da177e4SLinus Torvalds tmp = inb(port + 1); 1031da177e4SLinus Torvalds reg++; 1041da177e4SLinus Torvalds outb(reg, port); 1051da177e4SLinus Torvalds tmp = tmp | (inb(port + 1) << 8); 1061da177e4SLinus Torvalds spin_unlock_irqrestore(&port_lock, flags); 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds return tmp; 1091da177e4SLinus Torvalds } 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds static void indirect_write(struct pd6729_socket *socket, unsigned short reg, 1121da177e4SLinus Torvalds unsigned char value) 1131da177e4SLinus Torvalds { 1141da177e4SLinus Torvalds unsigned long port; 1151da177e4SLinus Torvalds unsigned long flags; 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds spin_lock_irqsave(&port_lock, flags); 1181da177e4SLinus Torvalds reg = reg + socket->number * 0x40; 1191da177e4SLinus Torvalds port = socket->io_base; 1201da177e4SLinus Torvalds outb(reg, port); 1211da177e4SLinus Torvalds outb(value, port + 1); 1221da177e4SLinus Torvalds spin_unlock_irqrestore(&port_lock, flags); 1231da177e4SLinus Torvalds } 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg, 1261da177e4SLinus Torvalds unsigned char mask) 1271da177e4SLinus Torvalds { 1281da177e4SLinus Torvalds unsigned long port; 1291da177e4SLinus Torvalds unsigned char val; 1301da177e4SLinus Torvalds unsigned long flags; 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds spin_lock_irqsave(&port_lock, flags); 1331da177e4SLinus Torvalds reg = reg + socket->number * 0x40; 1341da177e4SLinus Torvalds port = socket->io_base; 1351da177e4SLinus Torvalds outb(reg, port); 1361da177e4SLinus Torvalds val = inb(port + 1); 1371da177e4SLinus Torvalds val |= mask; 1381da177e4SLinus Torvalds outb(reg, port); 1391da177e4SLinus Torvalds outb(val, port + 1); 1401da177e4SLinus Torvalds spin_unlock_irqrestore(&port_lock, flags); 1411da177e4SLinus Torvalds } 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg, 1441da177e4SLinus Torvalds unsigned char mask) 1451da177e4SLinus Torvalds { 1461da177e4SLinus Torvalds unsigned long port; 1471da177e4SLinus Torvalds unsigned char val; 1481da177e4SLinus Torvalds unsigned long flags; 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds spin_lock_irqsave(&port_lock, flags); 1511da177e4SLinus Torvalds reg = reg + socket->number * 0x40; 1521da177e4SLinus Torvalds port = socket->io_base; 1531da177e4SLinus Torvalds outb(reg, port); 1541da177e4SLinus Torvalds val = inb(port + 1); 1551da177e4SLinus Torvalds val &= ~mask; 1561da177e4SLinus Torvalds outb(reg, port); 1571da177e4SLinus Torvalds outb(val, port + 1); 1581da177e4SLinus Torvalds spin_unlock_irqrestore(&port_lock, flags); 1591da177e4SLinus Torvalds } 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds static void indirect_write16(struct pd6729_socket *socket, unsigned short reg, 1621da177e4SLinus Torvalds unsigned short value) 1631da177e4SLinus Torvalds { 1641da177e4SLinus Torvalds unsigned long port; 1651da177e4SLinus Torvalds unsigned char val; 1661da177e4SLinus Torvalds unsigned long flags; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds spin_lock_irqsave(&port_lock, flags); 1691da177e4SLinus Torvalds reg = reg + socket->number * 0x40; 1701da177e4SLinus Torvalds port = socket->io_base; 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds outb(reg, port); 1731da177e4SLinus Torvalds val = value & 255; 1741da177e4SLinus Torvalds outb(val, port + 1); 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds reg++; 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds outb(reg, port); 1791da177e4SLinus Torvalds val = value >> 8; 1801da177e4SLinus Torvalds outb(val, port + 1); 1811da177e4SLinus Torvalds spin_unlock_irqrestore(&port_lock, flags); 1821da177e4SLinus Torvalds } 1831da177e4SLinus Torvalds 1841da177e4SLinus Torvalds /* Interrupt handler functionality */ 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs) 1871da177e4SLinus Torvalds { 1881da177e4SLinus Torvalds struct pd6729_socket *socket = (struct pd6729_socket *)dev; 1891da177e4SLinus Torvalds int i; 1901da177e4SLinus Torvalds int loopcount = 0; 1911da177e4SLinus Torvalds int handled = 0; 1921da177e4SLinus Torvalds unsigned int events, active = 0; 1931da177e4SLinus Torvalds 1941da177e4SLinus Torvalds while (1) { 1951da177e4SLinus Torvalds loopcount++; 1961da177e4SLinus Torvalds if (loopcount > 20) { 1971da177e4SLinus Torvalds printk(KERN_ERR "pd6729: infinite eventloop " 1981da177e4SLinus Torvalds "in interrupt\n"); 1991da177e4SLinus Torvalds break; 2001da177e4SLinus Torvalds } 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds active = 0; 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds for (i = 0; i < MAX_SOCKETS; i++) { 2051da177e4SLinus Torvalds unsigned int csc; 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds /* card status change register */ 2081da177e4SLinus Torvalds csc = indirect_read(&socket[i], I365_CSC); 2091da177e4SLinus Torvalds if (csc == 0) /* no events on this socket */ 2101da177e4SLinus Torvalds continue; 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds handled = 1; 2131da177e4SLinus Torvalds events = 0; 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds if (csc & I365_CSC_DETECT) { 2161da177e4SLinus Torvalds events |= SS_DETECT; 2171da177e4SLinus Torvalds dprintk("Card detected in socket %i!\n", i); 2181da177e4SLinus Torvalds } 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds if (indirect_read(&socket[i], I365_INTCTL) 2211da177e4SLinus Torvalds & I365_PC_IOCARD) { 2221da177e4SLinus Torvalds /* For IO/CARDS, bit 0 means "read the card" */ 2231da177e4SLinus Torvalds events |= (csc & I365_CSC_STSCHG) 2241da177e4SLinus Torvalds ? SS_STSCHG : 0; 2251da177e4SLinus Torvalds } else { 2261da177e4SLinus Torvalds /* Check for battery/ready events */ 2271da177e4SLinus Torvalds events |= (csc & I365_CSC_BVD1) 2281da177e4SLinus Torvalds ? SS_BATDEAD : 0; 2291da177e4SLinus Torvalds events |= (csc & I365_CSC_BVD2) 2301da177e4SLinus Torvalds ? SS_BATWARN : 0; 2311da177e4SLinus Torvalds events |= (csc & I365_CSC_READY) 2321da177e4SLinus Torvalds ? SS_READY : 0; 2331da177e4SLinus Torvalds } 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds if (events) { 2361da177e4SLinus Torvalds pcmcia_parse_events(&socket[i].socket, events); 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds active |= events; 2391da177e4SLinus Torvalds } 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds if (active == 0) /* no more events to handle */ 2421da177e4SLinus Torvalds break; 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds return IRQ_RETVAL(handled); 2451da177e4SLinus Torvalds } 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds /* socket functions */ 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds static void pd6729_interrupt_wrapper(unsigned long data) 2501da177e4SLinus Torvalds { 2511da177e4SLinus Torvalds struct pd6729_socket *socket = (struct pd6729_socket *) data; 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds pd6729_interrupt(0, (void *)socket, NULL); 2541da177e4SLinus Torvalds mod_timer(&socket->poll_timer, jiffies + HZ); 2551da177e4SLinus Torvalds } 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value) 2581da177e4SLinus Torvalds { 2591da177e4SLinus Torvalds struct pd6729_socket *socket 2601da177e4SLinus Torvalds = container_of(sock, struct pd6729_socket, socket); 2611da177e4SLinus Torvalds unsigned int status; 2621da177e4SLinus Torvalds unsigned int data; 2631da177e4SLinus Torvalds struct pd6729_socket *t; 2641da177e4SLinus Torvalds 2651da177e4SLinus Torvalds /* Interface Status Register */ 2661da177e4SLinus Torvalds status = indirect_read(socket, I365_STATUS); 2671da177e4SLinus Torvalds *value = 0; 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds if ((status & I365_CS_DETECT) == I365_CS_DETECT) { 2701da177e4SLinus Torvalds *value |= SS_DETECT; 2711da177e4SLinus Torvalds } 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds /* 2741da177e4SLinus Torvalds * IO cards have a different meaning of bits 0,1 2751da177e4SLinus Torvalds * Also notice the inverse-logic on the bits 2761da177e4SLinus Torvalds */ 2771da177e4SLinus Torvalds if (indirect_read(socket, I365_INTCTL) & I365_PC_IOCARD) { 2781da177e4SLinus Torvalds /* IO card */ 2791da177e4SLinus Torvalds if (!(status & I365_CS_STSCHG)) 2801da177e4SLinus Torvalds *value |= SS_STSCHG; 2811da177e4SLinus Torvalds } else { 2821da177e4SLinus Torvalds /* non I/O card */ 2831da177e4SLinus Torvalds if (!(status & I365_CS_BVD1)) 2841da177e4SLinus Torvalds *value |= SS_BATDEAD; 2851da177e4SLinus Torvalds if (!(status & I365_CS_BVD2)) 2861da177e4SLinus Torvalds *value |= SS_BATWARN; 2871da177e4SLinus Torvalds } 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds if (status & I365_CS_WRPROT) 2901da177e4SLinus Torvalds *value |= SS_WRPROT; /* card is write protected */ 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds if (status & I365_CS_READY) 2931da177e4SLinus Torvalds *value |= SS_READY; /* card is not busy */ 2941da177e4SLinus Torvalds 2951da177e4SLinus Torvalds if (status & I365_CS_POWERON) 2961da177e4SLinus Torvalds *value |= SS_POWERON; /* power is applied to the card */ 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds t = (socket->number) ? socket : socket + 1; 2991da177e4SLinus Torvalds indirect_write(t, PD67_EXT_INDEX, PD67_EXTERN_DATA); 3001da177e4SLinus Torvalds data = indirect_read16(t, PD67_EXT_DATA); 3011da177e4SLinus Torvalds *value |= (data & PD67_EXD_VS1(socket->number)) ? 0 : SS_3VCARD; 3021da177e4SLinus Torvalds 3031da177e4SLinus Torvalds return 0; 3041da177e4SLinus Torvalds } 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds 3071da177e4SLinus Torvalds static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state) 3081da177e4SLinus Torvalds { 3091da177e4SLinus Torvalds struct pd6729_socket *socket 3101da177e4SLinus Torvalds = container_of(sock, struct pd6729_socket, socket); 3111da177e4SLinus Torvalds unsigned char reg, vcc, vpp; 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds state->flags = 0; 3141da177e4SLinus Torvalds state->Vcc = 0; 3151da177e4SLinus Torvalds state->Vpp = 0; 3161da177e4SLinus Torvalds state->io_irq = 0; 3171da177e4SLinus Torvalds state->csc_mask = 0; 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds /* First the power status of the socket */ 3201da177e4SLinus Torvalds reg = indirect_read(socket, I365_POWER); 3211da177e4SLinus Torvalds 3221da177e4SLinus Torvalds if (reg & I365_PWR_AUTO) 3231da177e4SLinus Torvalds state->flags |= SS_PWR_AUTO; /* Automatic Power Switch */ 3241da177e4SLinus Torvalds 3251da177e4SLinus Torvalds if (reg & I365_PWR_OUT) 3261da177e4SLinus Torvalds state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */ 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK; 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds if (reg & I365_VCC_5V) { 3311da177e4SLinus Torvalds state->Vcc = (indirect_read(socket, PD67_MISC_CTL_1) & 3321da177e4SLinus Torvalds PD67_MC1_VCC_3V) ? 33 : 50; 3331da177e4SLinus Torvalds 3341da177e4SLinus Torvalds if (vpp == I365_VPP1_5V) { 3351da177e4SLinus Torvalds if (state->Vcc == 50) 3361da177e4SLinus Torvalds state->Vpp = 50; 3371da177e4SLinus Torvalds else 3381da177e4SLinus Torvalds state->Vpp = 33; 3391da177e4SLinus Torvalds } 3401da177e4SLinus Torvalds if (vpp == I365_VPP1_12V) 3411da177e4SLinus Torvalds state->Vpp = 120; 3421da177e4SLinus Torvalds } 3431da177e4SLinus Torvalds 3441da177e4SLinus Torvalds /* Now the IO card, RESET flags and IO interrupt */ 3451da177e4SLinus Torvalds reg = indirect_read(socket, I365_INTCTL); 3461da177e4SLinus Torvalds 3471da177e4SLinus Torvalds if ((reg & I365_PC_RESET) == 0) 3481da177e4SLinus Torvalds state->flags |= SS_RESET; 3491da177e4SLinus Torvalds if (reg & I365_PC_IOCARD) 3501da177e4SLinus Torvalds state->flags |= SS_IOCARD; /* This is an IO card */ 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds /* Set the IRQ number */ 3531da177e4SLinus Torvalds state->io_irq = socket->card_irq; 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds /* Card status change */ 3561da177e4SLinus Torvalds reg = indirect_read(socket, I365_CSCINT); 3571da177e4SLinus Torvalds 3581da177e4SLinus Torvalds if (reg & I365_CSC_DETECT) 3591da177e4SLinus Torvalds state->csc_mask |= SS_DETECT; /* Card detect is enabled */ 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds if (state->flags & SS_IOCARD) {/* IO Cards behave different */ 3621da177e4SLinus Torvalds if (reg & I365_CSC_STSCHG) 3631da177e4SLinus Torvalds state->csc_mask |= SS_STSCHG; 3641da177e4SLinus Torvalds } else { 3651da177e4SLinus Torvalds if (reg & I365_CSC_BVD1) 3661da177e4SLinus Torvalds state->csc_mask |= SS_BATDEAD; 3671da177e4SLinus Torvalds if (reg & I365_CSC_BVD2) 3681da177e4SLinus Torvalds state->csc_mask |= SS_BATWARN; 3691da177e4SLinus Torvalds if (reg & I365_CSC_READY) 3701da177e4SLinus Torvalds state->csc_mask |= SS_READY; 3711da177e4SLinus Torvalds } 3721da177e4SLinus Torvalds 3731da177e4SLinus Torvalds return 0; 3741da177e4SLinus Torvalds } 3751da177e4SLinus Torvalds 3761da177e4SLinus Torvalds static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state) 3771da177e4SLinus Torvalds { 3781da177e4SLinus Torvalds struct pd6729_socket *socket 3791da177e4SLinus Torvalds = container_of(sock, struct pd6729_socket, socket); 3801da177e4SLinus Torvalds unsigned char reg, data; 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds /* First, set the global controller options */ 3831da177e4SLinus Torvalds indirect_write(socket, I365_GBLCTL, 0x00); 3841da177e4SLinus Torvalds indirect_write(socket, I365_GENCTL, 0x00); 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds /* Values for the IGENC register */ 3871da177e4SLinus Torvalds socket->card_irq = state->io_irq; 3881da177e4SLinus Torvalds 3891da177e4SLinus Torvalds reg = 0; 3901da177e4SLinus Torvalds /* The reset bit has "inverse" logic */ 3911da177e4SLinus Torvalds if (!(state->flags & SS_RESET)) 3921da177e4SLinus Torvalds reg |= I365_PC_RESET; 3931da177e4SLinus Torvalds if (state->flags & SS_IOCARD) 3941da177e4SLinus Torvalds reg |= I365_PC_IOCARD; 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds /* IGENC, Interrupt and General Control Register */ 3971da177e4SLinus Torvalds indirect_write(socket, I365_INTCTL, reg); 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds /* Power registers */ 4001da177e4SLinus Torvalds 4011da177e4SLinus Torvalds reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */ 4021da177e4SLinus Torvalds 4031da177e4SLinus Torvalds if (state->flags & SS_PWR_AUTO) { 4041da177e4SLinus Torvalds dprintk("Auto power\n"); 4051da177e4SLinus Torvalds reg |= I365_PWR_AUTO; /* automatic power mngmnt */ 4061da177e4SLinus Torvalds } 4071da177e4SLinus Torvalds if (state->flags & SS_OUTPUT_ENA) { 4081da177e4SLinus Torvalds dprintk("Power Enabled\n"); 4091da177e4SLinus Torvalds reg |= I365_PWR_OUT; /* enable power */ 4101da177e4SLinus Torvalds } 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds switch (state->Vcc) { 4131da177e4SLinus Torvalds case 0: 4141da177e4SLinus Torvalds break; 4151da177e4SLinus Torvalds case 33: 4161da177e4SLinus Torvalds dprintk("setting voltage to Vcc to 3.3V on socket %i\n", 4171da177e4SLinus Torvalds socket->number); 4181da177e4SLinus Torvalds reg |= I365_VCC_5V; 4191da177e4SLinus Torvalds indirect_setbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); 4201da177e4SLinus Torvalds break; 4211da177e4SLinus Torvalds case 50: 4221da177e4SLinus Torvalds dprintk("setting voltage to Vcc to 5V on socket %i\n", 4231da177e4SLinus Torvalds socket->number); 4241da177e4SLinus Torvalds reg |= I365_VCC_5V; 4251da177e4SLinus Torvalds indirect_resetbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); 4261da177e4SLinus Torvalds break; 4271da177e4SLinus Torvalds default: 4281da177e4SLinus Torvalds dprintk("pd6729: pd6729_set_socket called with " 4291da177e4SLinus Torvalds "invalid VCC power value: %i\n", 4301da177e4SLinus Torvalds state->Vcc); 4311da177e4SLinus Torvalds return -EINVAL; 4321da177e4SLinus Torvalds } 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds switch (state->Vpp) { 4351da177e4SLinus Torvalds case 0: 4361da177e4SLinus Torvalds dprintk("not setting Vpp on socket %i\n", socket->number); 4371da177e4SLinus Torvalds break; 4381da177e4SLinus Torvalds case 33: 4391da177e4SLinus Torvalds case 50: 4401da177e4SLinus Torvalds dprintk("setting Vpp to Vcc for socket %i\n", socket->number); 4411da177e4SLinus Torvalds reg |= I365_VPP1_5V; 4421da177e4SLinus Torvalds break; 4431da177e4SLinus Torvalds case 120: 4441da177e4SLinus Torvalds dprintk("setting Vpp to 12.0\n"); 4451da177e4SLinus Torvalds reg |= I365_VPP1_12V; 4461da177e4SLinus Torvalds break; 4471da177e4SLinus Torvalds default: 4481da177e4SLinus Torvalds dprintk("pd6729: pd6729_set_socket called with invalid VPP power value: %i\n", 4491da177e4SLinus Torvalds state->Vpp); 4501da177e4SLinus Torvalds return -EINVAL; 4511da177e4SLinus Torvalds } 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds /* only write if changed */ 4541da177e4SLinus Torvalds if (reg != indirect_read(socket, I365_POWER)) 4551da177e4SLinus Torvalds indirect_write(socket, I365_POWER, reg); 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds if (irq_mode == 1) { 4581da177e4SLinus Torvalds /* all interrupts are to be done as PCI interrupts */ 4591da177e4SLinus Torvalds data = PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ; 4601da177e4SLinus Torvalds } else 4611da177e4SLinus Torvalds data = 0; 4621da177e4SLinus Torvalds 4631da177e4SLinus Torvalds indirect_write(socket, PD67_EXT_INDEX, PD67_EXT_CTL_1); 4641da177e4SLinus Torvalds indirect_write(socket, PD67_EXT_DATA, data); 4651da177e4SLinus Torvalds 4661da177e4SLinus Torvalds /* Enable specific interrupt events */ 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds reg = 0x00; 4691da177e4SLinus Torvalds if (state->csc_mask & SS_DETECT) { 4701da177e4SLinus Torvalds reg |= I365_CSC_DETECT; 4711da177e4SLinus Torvalds } 4721da177e4SLinus Torvalds if (state->flags & SS_IOCARD) { 4731da177e4SLinus Torvalds if (state->csc_mask & SS_STSCHG) 4741da177e4SLinus Torvalds reg |= I365_CSC_STSCHG; 4751da177e4SLinus Torvalds } else { 4761da177e4SLinus Torvalds if (state->csc_mask & SS_BATDEAD) 4771da177e4SLinus Torvalds reg |= I365_CSC_BVD1; 4781da177e4SLinus Torvalds if (state->csc_mask & SS_BATWARN) 4791da177e4SLinus Torvalds reg |= I365_CSC_BVD2; 4801da177e4SLinus Torvalds if (state->csc_mask & SS_READY) 4811da177e4SLinus Torvalds reg |= I365_CSC_READY; 4821da177e4SLinus Torvalds } 4831da177e4SLinus Torvalds if (irq_mode == 1) 4841da177e4SLinus Torvalds reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */ 4851da177e4SLinus Torvalds indirect_write(socket, I365_CSCINT, reg); 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds reg = indirect_read(socket, I365_INTCTL); 4881da177e4SLinus Torvalds if (irq_mode == 1) 4891da177e4SLinus Torvalds reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */ 4901da177e4SLinus Torvalds else 4911da177e4SLinus Torvalds reg |= socket->card_irq; 4921da177e4SLinus Torvalds indirect_write(socket, I365_INTCTL, reg); 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds /* now clear the (probably bogus) pending stuff by doing a dummy read */ 4951da177e4SLinus Torvalds (void)indirect_read(socket, I365_CSC); 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds return 0; 4981da177e4SLinus Torvalds } 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds static int pd6729_set_io_map(struct pcmcia_socket *sock, 5011da177e4SLinus Torvalds struct pccard_io_map *io) 5021da177e4SLinus Torvalds { 5031da177e4SLinus Torvalds struct pd6729_socket *socket 5041da177e4SLinus Torvalds = container_of(sock, struct pd6729_socket, socket); 5051da177e4SLinus Torvalds unsigned char map, ioctl; 5061da177e4SLinus Torvalds 5071da177e4SLinus Torvalds map = io->map; 5081da177e4SLinus Torvalds 5091da177e4SLinus Torvalds /* Check error conditions */ 5101da177e4SLinus Torvalds if (map > 1) { 5111da177e4SLinus Torvalds dprintk("pd6729_set_io_map with invalid map"); 5121da177e4SLinus Torvalds return -EINVAL; 5131da177e4SLinus Torvalds } 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds /* Turn off the window before changing anything */ 5161da177e4SLinus Torvalds if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_IO(map)) 5171da177e4SLinus Torvalds indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_IO(map)); 5181da177e4SLinus Torvalds 5191da177e4SLinus Torvalds /* dprintk("set_io_map: Setting range to %x - %x\n", 5201da177e4SLinus Torvalds io->start, io->stop);*/ 5211da177e4SLinus Torvalds 5221da177e4SLinus Torvalds /* write the new values */ 5231da177e4SLinus Torvalds indirect_write16(socket, I365_IO(map)+I365_W_START, io->start); 5241da177e4SLinus Torvalds indirect_write16(socket, I365_IO(map)+I365_W_STOP, io->stop); 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds ioctl = indirect_read(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); 5291da177e4SLinus Torvalds if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); 5301da177e4SLinus Torvalds if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds indirect_write(socket, I365_IOCTL, ioctl); 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds /* Turn the window back on if needed */ 5351da177e4SLinus Torvalds if (io->flags & MAP_ACTIVE) 5361da177e4SLinus Torvalds indirect_setbit(socket, I365_ADDRWIN, I365_ENA_IO(map)); 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds return 0; 5391da177e4SLinus Torvalds } 5401da177e4SLinus Torvalds 5411da177e4SLinus Torvalds static int pd6729_set_mem_map(struct pcmcia_socket *sock, 5421da177e4SLinus Torvalds struct pccard_mem_map *mem) 5431da177e4SLinus Torvalds { 5441da177e4SLinus Torvalds struct pd6729_socket *socket 5451da177e4SLinus Torvalds = container_of(sock, struct pd6729_socket, socket); 5461da177e4SLinus Torvalds unsigned short base, i; 5471da177e4SLinus Torvalds unsigned char map; 5481da177e4SLinus Torvalds 5491da177e4SLinus Torvalds map = mem->map; 5501da177e4SLinus Torvalds if (map > 4) { 5511da177e4SLinus Torvalds printk("pd6729_set_mem_map: invalid map"); 5521da177e4SLinus Torvalds return -EINVAL; 5531da177e4SLinus Torvalds } 5541da177e4SLinus Torvalds 5551da177e4SLinus Torvalds if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) { 5561da177e4SLinus Torvalds printk("pd6729_set_mem_map: invalid address / speed"); 5571da177e4SLinus Torvalds return -EINVAL; 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds /* Turn off the window before changing anything */ 5611da177e4SLinus Torvalds if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_MEM(map)) 5621da177e4SLinus Torvalds indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_MEM(map)); 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds /* write the start address */ 5651da177e4SLinus Torvalds base = I365_MEM(map); 5661da177e4SLinus Torvalds i = (mem->res->start >> 12) & 0x0fff; 5671da177e4SLinus Torvalds if (mem->flags & MAP_16BIT) 5681da177e4SLinus Torvalds i |= I365_MEM_16BIT; 5691da177e4SLinus Torvalds if (mem->flags & MAP_0WS) 5701da177e4SLinus Torvalds i |= I365_MEM_0WS; 5711da177e4SLinus Torvalds indirect_write16(socket, base + I365_W_START, i); 5721da177e4SLinus Torvalds 5731da177e4SLinus Torvalds /* write the stop address */ 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds i= (mem->res->end >> 12) & 0x0fff; 5761da177e4SLinus Torvalds switch (to_cycles(mem->speed)) { 5771da177e4SLinus Torvalds case 0: 5781da177e4SLinus Torvalds break; 5791da177e4SLinus Torvalds case 1: 5801da177e4SLinus Torvalds i |= I365_MEM_WS0; 5811da177e4SLinus Torvalds break; 5821da177e4SLinus Torvalds case 2: 5831da177e4SLinus Torvalds i |= I365_MEM_WS1; 5841da177e4SLinus Torvalds break; 5851da177e4SLinus Torvalds default: 5861da177e4SLinus Torvalds i |= I365_MEM_WS1 | I365_MEM_WS0; 5871da177e4SLinus Torvalds break; 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds indirect_write16(socket, base + I365_W_STOP, i); 5911da177e4SLinus Torvalds 5921da177e4SLinus Torvalds /* Take care of high byte */ 5931da177e4SLinus Torvalds indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map)); 5941da177e4SLinus Torvalds indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24); 5951da177e4SLinus Torvalds 5961da177e4SLinus Torvalds /* card start */ 5971da177e4SLinus Torvalds 5981da177e4SLinus Torvalds i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff; 5991da177e4SLinus Torvalds if (mem->flags & MAP_WRPROT) 6001da177e4SLinus Torvalds i |= I365_MEM_WRPROT; 6011da177e4SLinus Torvalds if (mem->flags & MAP_ATTRIB) { 6021da177e4SLinus Torvalds /* dprintk("requesting attribute memory for socket %i\n", 6031da177e4SLinus Torvalds socket->number);*/ 6041da177e4SLinus Torvalds i |= I365_MEM_REG; 6051da177e4SLinus Torvalds } else { 6061da177e4SLinus Torvalds /* dprintk("requesting normal memory for socket %i\n", 6071da177e4SLinus Torvalds socket->number);*/ 6081da177e4SLinus Torvalds } 6091da177e4SLinus Torvalds indirect_write16(socket, base + I365_W_OFF, i); 6101da177e4SLinus Torvalds 6111da177e4SLinus Torvalds /* Enable the window if necessary */ 6121da177e4SLinus Torvalds if (mem->flags & MAP_ACTIVE) 6131da177e4SLinus Torvalds indirect_setbit(socket, I365_ADDRWIN, I365_ENA_MEM(map)); 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds return 0; 6161da177e4SLinus Torvalds } 6171da177e4SLinus Torvalds 6181da177e4SLinus Torvalds static int pd6729_init(struct pcmcia_socket *sock) 6191da177e4SLinus Torvalds { 6201da177e4SLinus Torvalds int i; 6211da177e4SLinus Torvalds struct resource res = { .end = 0x0fff }; 6221da177e4SLinus Torvalds pccard_io_map io = { 0, 0, 0, 0, 1 }; 6231da177e4SLinus Torvalds pccard_mem_map mem = { .res = &res, }; 6241da177e4SLinus Torvalds 6251da177e4SLinus Torvalds pd6729_set_socket(sock, &dead_socket); 6261da177e4SLinus Torvalds for (i = 0; i < 2; i++) { 6271da177e4SLinus Torvalds io.map = i; 6281da177e4SLinus Torvalds pd6729_set_io_map(sock, &io); 6291da177e4SLinus Torvalds } 6301da177e4SLinus Torvalds for (i = 0; i < 5; i++) { 6311da177e4SLinus Torvalds mem.map = i; 6321da177e4SLinus Torvalds pd6729_set_mem_map(sock, &mem); 6331da177e4SLinus Torvalds } 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds return 0; 6361da177e4SLinus Torvalds } 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds 6391da177e4SLinus Torvalds /* the pccard structure and its functions */ 6401da177e4SLinus Torvalds static struct pccard_operations pd6729_operations = { 6411da177e4SLinus Torvalds .init = pd6729_init, 6421da177e4SLinus Torvalds .get_status = pd6729_get_status, 6431da177e4SLinus Torvalds .get_socket = pd6729_get_socket, 6441da177e4SLinus Torvalds .set_socket = pd6729_set_socket, 6451da177e4SLinus Torvalds .set_io_map = pd6729_set_io_map, 6461da177e4SLinus Torvalds .set_mem_map = pd6729_set_mem_map, 6471da177e4SLinus Torvalds }; 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds static irqreturn_t pd6729_test(int irq, void *dev, struct pt_regs *regs) 6501da177e4SLinus Torvalds { 6511da177e4SLinus Torvalds dprintk("-> hit on irq %d\n", irq); 6521da177e4SLinus Torvalds return IRQ_HANDLED; 6531da177e4SLinus Torvalds } 6541da177e4SLinus Torvalds 6551da177e4SLinus Torvalds static int pd6729_check_irq(int irq, int flags) 6561da177e4SLinus Torvalds { 6571da177e4SLinus Torvalds if (request_irq(irq, pd6729_test, flags, "x", pd6729_test) != 0) 6581da177e4SLinus Torvalds return -1; 6591da177e4SLinus Torvalds free_irq(irq, pd6729_test); 6601da177e4SLinus Torvalds return 0; 6611da177e4SLinus Torvalds } 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds static u_int __init pd6729_isa_scan(void) 6641da177e4SLinus Torvalds { 6651da177e4SLinus Torvalds u_int mask0, mask = 0; 6661da177e4SLinus Torvalds int i; 6671da177e4SLinus Torvalds 6681da177e4SLinus Torvalds if (irq_mode == 1) { 6691da177e4SLinus Torvalds printk(KERN_INFO "pd6729: PCI card interrupts, " 6701da177e4SLinus Torvalds "PCI status changes\n"); 6711da177e4SLinus Torvalds return 0; 6721da177e4SLinus Torvalds } 6731da177e4SLinus Torvalds 6741da177e4SLinus Torvalds if (irq_list_count == 0) 6751da177e4SLinus Torvalds mask0 = 0xffff; 6761da177e4SLinus Torvalds else 6771da177e4SLinus Torvalds for (i = mask0 = 0; i < irq_list_count; i++) 6781da177e4SLinus Torvalds mask0 |= (1<<irq_list[i]); 6791da177e4SLinus Torvalds 6801da177e4SLinus Torvalds mask0 &= PD67_MASK; 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds /* just find interrupts that aren't in use */ 6831da177e4SLinus Torvalds for (i = 0; i < 16; i++) 6841da177e4SLinus Torvalds if ((mask0 & (1 << i)) && (pd6729_check_irq(i, 0) == 0)) 6851da177e4SLinus Torvalds mask |= (1 << i); 6861da177e4SLinus Torvalds 6871da177e4SLinus Torvalds printk(KERN_INFO "pd6729: ISA irqs = "); 6881da177e4SLinus Torvalds for (i = 0; i < 16; i++) 6891da177e4SLinus Torvalds if (mask & (1<<i)) 6901da177e4SLinus Torvalds printk("%s%d", ((mask & ((1<<i)-1)) ? "," : ""), i); 6911da177e4SLinus Torvalds 6921da177e4SLinus Torvalds if (mask == 0) printk("none!"); 6931da177e4SLinus Torvalds 6941da177e4SLinus Torvalds printk(" polling status changes.\n"); 6951da177e4SLinus Torvalds 6961da177e4SLinus Torvalds return mask; 6971da177e4SLinus Torvalds } 6981da177e4SLinus Torvalds 6991da177e4SLinus Torvalds static int __devinit pd6729_pci_probe(struct pci_dev *dev, 7001da177e4SLinus Torvalds const struct pci_device_id *id) 7011da177e4SLinus Torvalds { 7021da177e4SLinus Torvalds int i, j, ret; 7031da177e4SLinus Torvalds u_int mask; 7041da177e4SLinus Torvalds char configbyte; 7051da177e4SLinus Torvalds struct pd6729_socket *socket; 7061da177e4SLinus Torvalds 7071da177e4SLinus Torvalds socket = kmalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS, 7081da177e4SLinus Torvalds GFP_KERNEL); 7091da177e4SLinus Torvalds if (!socket) 7101da177e4SLinus Torvalds return -ENOMEM; 7111da177e4SLinus Torvalds 7121da177e4SLinus Torvalds memset(socket, 0, sizeof(struct pd6729_socket) * MAX_SOCKETS); 7131da177e4SLinus Torvalds 7141da177e4SLinus Torvalds if ((ret = pci_enable_device(dev))) 7151da177e4SLinus Torvalds goto err_out_free_mem; 7161da177e4SLinus Torvalds 7171da177e4SLinus Torvalds printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge " 7181da177e4SLinus Torvalds "at 0x%lx on irq %d\n", pci_resource_start(dev, 0), dev->irq); 7191da177e4SLinus Torvalds /* 7201da177e4SLinus Torvalds * Since we have no memory BARs some firmware may not 7211da177e4SLinus Torvalds * have had PCI_COMMAND_MEMORY enabled, yet the device needs it. 7221da177e4SLinus Torvalds */ 7231da177e4SLinus Torvalds pci_read_config_byte(dev, PCI_COMMAND, &configbyte); 7241da177e4SLinus Torvalds if (!(configbyte & PCI_COMMAND_MEMORY)) { 7251da177e4SLinus Torvalds printk(KERN_DEBUG "pd6729: Enabling PCI_COMMAND_MEMORY.\n"); 7261da177e4SLinus Torvalds configbyte |= PCI_COMMAND_MEMORY; 7271da177e4SLinus Torvalds pci_write_config_byte(dev, PCI_COMMAND, configbyte); 7281da177e4SLinus Torvalds } 7291da177e4SLinus Torvalds 7301da177e4SLinus Torvalds ret = pci_request_regions(dev, "pd6729"); 7311da177e4SLinus Torvalds if (ret) { 7321da177e4SLinus Torvalds printk(KERN_INFO "pd6729: pci request region failed.\n"); 7331da177e4SLinus Torvalds goto err_out_disable; 7341da177e4SLinus Torvalds } 7351da177e4SLinus Torvalds 7361da177e4SLinus Torvalds if (dev->irq == NO_IRQ) 7371da177e4SLinus Torvalds irq_mode = 0; /* fall back to ISA interrupt mode */ 7381da177e4SLinus Torvalds 7391da177e4SLinus Torvalds mask = pd6729_isa_scan(); 7401da177e4SLinus Torvalds if (irq_mode == 0 && mask == 0) { 7411da177e4SLinus Torvalds printk(KERN_INFO "pd6729: no ISA interrupt is available.\n"); 7421da177e4SLinus Torvalds goto err_out_free_res; 7431da177e4SLinus Torvalds } 7441da177e4SLinus Torvalds 7451da177e4SLinus Torvalds for (i = 0; i < MAX_SOCKETS; i++) { 7461da177e4SLinus Torvalds socket[i].io_base = pci_resource_start(dev, 0); 747c35e66a4SDominik Brodowski socket[i].socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD; 7481da177e4SLinus Torvalds socket[i].socket.map_size = 0x1000; 7491da177e4SLinus Torvalds socket[i].socket.irq_mask = mask; 7501da177e4SLinus Torvalds socket[i].socket.pci_irq = dev->irq; 7511da177e4SLinus Torvalds socket[i].socket.owner = THIS_MODULE; 7521da177e4SLinus Torvalds 7531da177e4SLinus Torvalds socket[i].number = i; 7541da177e4SLinus Torvalds 7551da177e4SLinus Torvalds socket[i].socket.ops = &pd6729_operations; 7561da177e4SLinus Torvalds socket[i].socket.resource_ops = &pccard_nonstatic_ops; 7571da177e4SLinus Torvalds socket[i].socket.dev.dev = &dev->dev; 7581da177e4SLinus Torvalds socket[i].socket.driver_data = &socket[i]; 7591da177e4SLinus Torvalds } 7601da177e4SLinus Torvalds 7611da177e4SLinus Torvalds pci_set_drvdata(dev, socket); 7621da177e4SLinus Torvalds if (irq_mode == 1) { 7631da177e4SLinus Torvalds /* Register the interrupt handler */ 7641da177e4SLinus Torvalds if ((ret = request_irq(dev->irq, pd6729_interrupt, SA_SHIRQ, 7651da177e4SLinus Torvalds "pd6729", socket))) { 7661da177e4SLinus Torvalds printk(KERN_ERR "pd6729: Failed to register irq %d, " 7671da177e4SLinus Torvalds "aborting\n", dev->irq); 7681da177e4SLinus Torvalds goto err_out_free_res; 7691da177e4SLinus Torvalds } 7701da177e4SLinus Torvalds } else { 7711da177e4SLinus Torvalds /* poll Card status change */ 7721da177e4SLinus Torvalds init_timer(&socket->poll_timer); 7731da177e4SLinus Torvalds socket->poll_timer.function = pd6729_interrupt_wrapper; 7741da177e4SLinus Torvalds socket->poll_timer.data = (unsigned long)socket; 7751da177e4SLinus Torvalds socket->poll_timer.expires = jiffies + HZ; 7761da177e4SLinus Torvalds add_timer(&socket->poll_timer); 7771da177e4SLinus Torvalds } 7781da177e4SLinus Torvalds 7791da177e4SLinus Torvalds for (i = 0; i < MAX_SOCKETS; i++) { 7801da177e4SLinus Torvalds ret = pcmcia_register_socket(&socket[i].socket); 7811da177e4SLinus Torvalds if (ret) { 7821da177e4SLinus Torvalds printk(KERN_INFO "pd6729: pcmcia_register_socket " 7831da177e4SLinus Torvalds "failed.\n"); 7841da177e4SLinus Torvalds for (j = 0; j < i ; j++) 7851da177e4SLinus Torvalds pcmcia_unregister_socket(&socket[j].socket); 7861da177e4SLinus Torvalds goto err_out_free_res2; 7871da177e4SLinus Torvalds } 7881da177e4SLinus Torvalds } 7891da177e4SLinus Torvalds 7901da177e4SLinus Torvalds return 0; 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds err_out_free_res2: 7931da177e4SLinus Torvalds if (irq_mode == 1) 7941da177e4SLinus Torvalds free_irq(dev->irq, socket); 7951da177e4SLinus Torvalds else 7961da177e4SLinus Torvalds del_timer_sync(&socket->poll_timer); 7971da177e4SLinus Torvalds err_out_free_res: 7981da177e4SLinus Torvalds pci_release_regions(dev); 7991da177e4SLinus Torvalds err_out_disable: 8001da177e4SLinus Torvalds pci_disable_device(dev); 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds err_out_free_mem: 8031da177e4SLinus Torvalds kfree(socket); 8041da177e4SLinus Torvalds return ret; 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds 8071da177e4SLinus Torvalds static void __devexit pd6729_pci_remove(struct pci_dev *dev) 8081da177e4SLinus Torvalds { 8091da177e4SLinus Torvalds int i; 8101da177e4SLinus Torvalds struct pd6729_socket *socket = pci_get_drvdata(dev); 8111da177e4SLinus Torvalds 8121da177e4SLinus Torvalds for (i = 0; i < MAX_SOCKETS; i++) { 8131da177e4SLinus Torvalds /* Turn off all interrupt sources */ 8141da177e4SLinus Torvalds indirect_write(&socket[i], I365_CSCINT, 0); 8151da177e4SLinus Torvalds indirect_write(&socket[i], I365_INTCTL, 0); 8161da177e4SLinus Torvalds 8171da177e4SLinus Torvalds pcmcia_unregister_socket(&socket[i].socket); 8181da177e4SLinus Torvalds } 8191da177e4SLinus Torvalds 8201da177e4SLinus Torvalds if (irq_mode == 1) 8211da177e4SLinus Torvalds free_irq(dev->irq, socket); 8221da177e4SLinus Torvalds else 8231da177e4SLinus Torvalds del_timer_sync(&socket->poll_timer); 8241da177e4SLinus Torvalds pci_release_regions(dev); 8251da177e4SLinus Torvalds pci_disable_device(dev); 8261da177e4SLinus Torvalds 8271da177e4SLinus Torvalds kfree(socket); 8281da177e4SLinus Torvalds } 8291da177e4SLinus Torvalds 8301da177e4SLinus Torvalds static int pd6729_socket_suspend(struct pci_dev *dev, pm_message_t state) 8311da177e4SLinus Torvalds { 8321da177e4SLinus Torvalds return pcmcia_socket_dev_suspend(&dev->dev, state); 8331da177e4SLinus Torvalds } 8341da177e4SLinus Torvalds 8351da177e4SLinus Torvalds static int pd6729_socket_resume(struct pci_dev *dev) 8361da177e4SLinus Torvalds { 8371da177e4SLinus Torvalds return pcmcia_socket_dev_resume(&dev->dev); 8381da177e4SLinus Torvalds } 8391da177e4SLinus Torvalds 8401da177e4SLinus Torvalds static struct pci_device_id pd6729_pci_ids[] = { 8411da177e4SLinus Torvalds { 8421da177e4SLinus Torvalds .vendor = PCI_VENDOR_ID_CIRRUS, 8431da177e4SLinus Torvalds .device = PCI_DEVICE_ID_CIRRUS_6729, 8441da177e4SLinus Torvalds .subvendor = PCI_ANY_ID, 8451da177e4SLinus Torvalds .subdevice = PCI_ANY_ID, 8461da177e4SLinus Torvalds }, 8471da177e4SLinus Torvalds { } 8481da177e4SLinus Torvalds }; 8491da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, pd6729_pci_ids); 8501da177e4SLinus Torvalds 8511da177e4SLinus Torvalds static struct pci_driver pd6729_pci_drv = { 8521da177e4SLinus Torvalds .name = "pd6729", 8531da177e4SLinus Torvalds .id_table = pd6729_pci_ids, 8541da177e4SLinus Torvalds .probe = pd6729_pci_probe, 8551da177e4SLinus Torvalds .remove = __devexit_p(pd6729_pci_remove), 8561da177e4SLinus Torvalds .suspend = pd6729_socket_suspend, 8571da177e4SLinus Torvalds .resume = pd6729_socket_resume, 8581da177e4SLinus Torvalds }; 8591da177e4SLinus Torvalds 8601da177e4SLinus Torvalds static int pd6729_module_init(void) 8611da177e4SLinus Torvalds { 8621da177e4SLinus Torvalds return pci_register_driver(&pd6729_pci_drv); 8631da177e4SLinus Torvalds } 8641da177e4SLinus Torvalds 8651da177e4SLinus Torvalds static void pd6729_module_exit(void) 8661da177e4SLinus Torvalds { 8671da177e4SLinus Torvalds pci_unregister_driver(&pd6729_pci_drv); 8681da177e4SLinus Torvalds } 8691da177e4SLinus Torvalds 8701da177e4SLinus Torvalds module_init(pd6729_module_init); 8711da177e4SLinus Torvalds module_exit(pd6729_module_exit); 872