11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Regular cardbus driver ("yenta_socket") 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * (C) Copyright 1999, 2000 Linus Torvalds 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Changelog: 71da177e4SLinus Torvalds * Aug 2002: Manfred Spraul <manfred@colorfullife.com> 81da177e4SLinus Torvalds * Dynamically adjust the size of the bridge resource 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * May 2003: Dominik Brodowski <linux@brodo.de> 111da177e4SLinus Torvalds * Merge pci_socket.c and yenta.c into one file 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds #include <linux/init.h> 141da177e4SLinus Torvalds #include <linux/pci.h> 151da177e4SLinus Torvalds #include <linux/sched.h> 161da177e4SLinus Torvalds #include <linux/workqueue.h> 171da177e4SLinus Torvalds #include <linux/interrupt.h> 181da177e4SLinus Torvalds #include <linux/delay.h> 191da177e4SLinus Torvalds #include <linux/module.h> 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds #include <pcmcia/cs_types.h> 221da177e4SLinus Torvalds #include <pcmcia/ss.h> 231da177e4SLinus Torvalds #include <pcmcia/cs.h> 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #include <asm/io.h> 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include "yenta_socket.h" 281da177e4SLinus Torvalds #include "i82365.h" 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds static int disable_clkrun; 311da177e4SLinus Torvalds module_param(disable_clkrun, bool, 0444); 321da177e4SLinus Torvalds MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option"); 331da177e4SLinus Torvalds 34fa912bcbSDaniel Ritz static int isa_probe = 1; 35fa912bcbSDaniel Ritz module_param(isa_probe, bool, 0444); 36fa912bcbSDaniel Ritz MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing"); 37fa912bcbSDaniel Ritz 38fa912bcbSDaniel Ritz static int pwr_irqs_off; 39fa912bcbSDaniel Ritz module_param(pwr_irqs_off, bool, 0644); 40fa912bcbSDaniel Ritz MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!"); 41fa912bcbSDaniel Ritz 421da177e4SLinus Torvalds #if 0 431da177e4SLinus Torvalds #define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args) 441da177e4SLinus Torvalds #else 451da177e4SLinus Torvalds #define debug(x,args...) 461da177e4SLinus Torvalds #endif 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds /* Don't ask.. */ 491da177e4SLinus Torvalds #define to_cycles(ns) ((ns)/120) 501da177e4SLinus Torvalds #define to_ns(cycles) ((cycles)*120) 511da177e4SLinus Torvalds 5263e7ebd0SDaniel Ritz /** 5363e7ebd0SDaniel Ritz * yenta PCI irq probing. 5463e7ebd0SDaniel Ritz * currently only used in the TI/EnE initialization code 5563e7ebd0SDaniel Ritz */ 5663e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 571da177e4SLinus Torvalds static int yenta_probe_cb_irq(struct yenta_socket *socket); 5863e7ebd0SDaniel Ritz #endif 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds static unsigned int override_bios; 621da177e4SLinus Torvalds module_param(override_bios, uint, 0000); 631da177e4SLinus Torvalds MODULE_PARM_DESC (override_bios, "yenta ignore bios resource allocation"); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds /* 661da177e4SLinus Torvalds * Generate easy-to-use ways of reading a cardbus sockets 671da177e4SLinus Torvalds * regular memory space ("cb_xxx"), configuration space 681da177e4SLinus Torvalds * ("config_xxx") and compatibility space ("exca_xxxx") 691da177e4SLinus Torvalds */ 701da177e4SLinus Torvalds static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg) 711da177e4SLinus Torvalds { 721da177e4SLinus Torvalds u32 val = readl(socket->base + reg); 731da177e4SLinus Torvalds debug("%p %04x %08x\n", socket, reg, val); 741da177e4SLinus Torvalds return val; 751da177e4SLinus Torvalds } 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val) 781da177e4SLinus Torvalds { 791da177e4SLinus Torvalds debug("%p %04x %08x\n", socket, reg, val); 801da177e4SLinus Torvalds writel(val, socket->base + reg); 81c8751e4cSDaniel Ritz readl(socket->base + reg); /* avoid problems with PCI write posting */ 821da177e4SLinus Torvalds } 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds static inline u8 config_readb(struct yenta_socket *socket, unsigned offset) 851da177e4SLinus Torvalds { 861da177e4SLinus Torvalds u8 val; 871da177e4SLinus Torvalds pci_read_config_byte(socket->dev, offset, &val); 881da177e4SLinus Torvalds debug("%p %04x %02x\n", socket, offset, val); 891da177e4SLinus Torvalds return val; 901da177e4SLinus Torvalds } 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds static inline u16 config_readw(struct yenta_socket *socket, unsigned offset) 931da177e4SLinus Torvalds { 941da177e4SLinus Torvalds u16 val; 951da177e4SLinus Torvalds pci_read_config_word(socket->dev, offset, &val); 961da177e4SLinus Torvalds debug("%p %04x %04x\n", socket, offset, val); 971da177e4SLinus Torvalds return val; 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds static inline u32 config_readl(struct yenta_socket *socket, unsigned offset) 1011da177e4SLinus Torvalds { 1021da177e4SLinus Torvalds u32 val; 1031da177e4SLinus Torvalds pci_read_config_dword(socket->dev, offset, &val); 1041da177e4SLinus Torvalds debug("%p %04x %08x\n", socket, offset, val); 1051da177e4SLinus Torvalds return val; 1061da177e4SLinus Torvalds } 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val) 1091da177e4SLinus Torvalds { 1101da177e4SLinus Torvalds debug("%p %04x %02x\n", socket, offset, val); 1111da177e4SLinus Torvalds pci_write_config_byte(socket->dev, offset, val); 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val) 1151da177e4SLinus Torvalds { 1161da177e4SLinus Torvalds debug("%p %04x %04x\n", socket, offset, val); 1171da177e4SLinus Torvalds pci_write_config_word(socket->dev, offset, val); 1181da177e4SLinus Torvalds } 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val) 1211da177e4SLinus Torvalds { 1221da177e4SLinus Torvalds debug("%p %04x %08x\n", socket, offset, val); 1231da177e4SLinus Torvalds pci_write_config_dword(socket->dev, offset, val); 1241da177e4SLinus Torvalds } 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg) 1271da177e4SLinus Torvalds { 1281da177e4SLinus Torvalds u8 val = readb(socket->base + 0x800 + reg); 1291da177e4SLinus Torvalds debug("%p %04x %02x\n", socket, reg, val); 1301da177e4SLinus Torvalds return val; 1311da177e4SLinus Torvalds } 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg) 1341da177e4SLinus Torvalds { 1351da177e4SLinus Torvalds u16 val; 1361da177e4SLinus Torvalds val = readb(socket->base + 0x800 + reg); 1371da177e4SLinus Torvalds val |= readb(socket->base + 0x800 + reg + 1) << 8; 1381da177e4SLinus Torvalds debug("%p %04x %04x\n", socket, reg, val); 1391da177e4SLinus Torvalds return val; 1401da177e4SLinus Torvalds } 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val) 1431da177e4SLinus Torvalds { 1441da177e4SLinus Torvalds debug("%p %04x %02x\n", socket, reg, val); 1451da177e4SLinus Torvalds writeb(val, socket->base + 0x800 + reg); 146c8751e4cSDaniel Ritz readb(socket->base + 0x800 + reg); /* PCI write posting... */ 1471da177e4SLinus Torvalds } 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val) 1501da177e4SLinus Torvalds { 1511da177e4SLinus Torvalds debug("%p %04x %04x\n", socket, reg, val); 1521da177e4SLinus Torvalds writeb(val, socket->base + 0x800 + reg); 1531da177e4SLinus Torvalds writeb(val >> 8, socket->base + 0x800 + reg + 1); 154c8751e4cSDaniel Ritz 155c8751e4cSDaniel Ritz /* PCI write posting... */ 156c8751e4cSDaniel Ritz readb(socket->base + 0x800 + reg); 157c8751e4cSDaniel Ritz readb(socket->base + 0x800 + reg + 1); 1581da177e4SLinus Torvalds } 1591da177e4SLinus Torvalds 160030ee39cSLinus Torvalds static ssize_t show_yenta_registers(struct device *yentadev, struct device_attribute *attr, char *buf) 161030ee39cSLinus Torvalds { 162030ee39cSLinus Torvalds struct pci_dev *dev = to_pci_dev(yentadev); 163030ee39cSLinus Torvalds struct yenta_socket *socket = pci_get_drvdata(dev); 164030ee39cSLinus Torvalds int offset = 0, i; 165030ee39cSLinus Torvalds 166030ee39cSLinus Torvalds offset = snprintf(buf, PAGE_SIZE, "CB registers:"); 167030ee39cSLinus Torvalds for (i = 0; i < 0x24; i += 4) { 168030ee39cSLinus Torvalds unsigned val; 169030ee39cSLinus Torvalds if (!(i & 15)) 170030ee39cSLinus Torvalds offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i); 171030ee39cSLinus Torvalds val = cb_readl(socket, i); 172030ee39cSLinus Torvalds offset += snprintf(buf + offset, PAGE_SIZE - offset, " %08x", val); 173030ee39cSLinus Torvalds } 174030ee39cSLinus Torvalds 175030ee39cSLinus Torvalds offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n\nExCA registers:"); 176030ee39cSLinus Torvalds for (i = 0; i < 0x45; i++) { 177030ee39cSLinus Torvalds unsigned char val; 178030ee39cSLinus Torvalds if (!(i & 7)) { 179030ee39cSLinus Torvalds if (i & 8) { 180030ee39cSLinus Torvalds memcpy(buf + offset, " -", 2); 181030ee39cSLinus Torvalds offset += 2; 182030ee39cSLinus Torvalds } else 183030ee39cSLinus Torvalds offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i); 184030ee39cSLinus Torvalds } 185030ee39cSLinus Torvalds val = exca_readb(socket, i); 186030ee39cSLinus Torvalds offset += snprintf(buf + offset, PAGE_SIZE - offset, " %02x", val); 187030ee39cSLinus Torvalds } 188030ee39cSLinus Torvalds buf[offset++] = '\n'; 189030ee39cSLinus Torvalds return offset; 190030ee39cSLinus Torvalds } 191030ee39cSLinus Torvalds 192030ee39cSLinus Torvalds static DEVICE_ATTR(yenta_registers, S_IRUSR, show_yenta_registers, NULL); 193030ee39cSLinus Torvalds 1941da177e4SLinus Torvalds /* 1951da177e4SLinus Torvalds * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend 1961da177e4SLinus Torvalds * on what kind of card is inserted.. 1971da177e4SLinus Torvalds */ 1981da177e4SLinus Torvalds static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) 1991da177e4SLinus Torvalds { 2001da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 2011da177e4SLinus Torvalds unsigned int val; 2021da177e4SLinus Torvalds u32 state = cb_readl(socket, CB_SOCKET_STATE); 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds val = (state & CB_3VCARD) ? SS_3VCARD : 0; 2051da177e4SLinus Torvalds val |= (state & CB_XVCARD) ? SS_XVCARD : 0; 206fa912bcbSDaniel Ritz val |= (state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; 207fa912bcbSDaniel Ritz val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? SS_PENDING : 0; 208fa912bcbSDaniel Ritz 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds if (state & CB_CBCARD) { 2111da177e4SLinus Torvalds val |= SS_CARDBUS; 2121da177e4SLinus Torvalds val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; 2131da177e4SLinus Torvalds val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; 2141da177e4SLinus Torvalds val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; 215fa912bcbSDaniel Ritz } else if (state & CB_16BITCARD) { 2161da177e4SLinus Torvalds u8 status = exca_readb(socket, I365_STATUS); 2171da177e4SLinus Torvalds val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; 2181da177e4SLinus Torvalds if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { 2191da177e4SLinus Torvalds val |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; 2201da177e4SLinus Torvalds } else { 2211da177e4SLinus Torvalds val |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; 2221da177e4SLinus Torvalds val |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; 2231da177e4SLinus Torvalds } 2241da177e4SLinus Torvalds val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; 2251da177e4SLinus Torvalds val |= (status & I365_CS_READY) ? SS_READY : 0; 2261da177e4SLinus Torvalds val |= (status & I365_CS_POWERON) ? SS_POWERON : 0; 2271da177e4SLinus Torvalds } 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds *value = val; 2301da177e4SLinus Torvalds return 0; 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) 2341da177e4SLinus Torvalds { 235ea2f1590SDaniel Ritz /* some birdges require to use the ExCA registers to power 16bit cards */ 236ea2f1590SDaniel Ritz if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) && 237ea2f1590SDaniel Ritz (socket->flags & YENTA_16BIT_POWER_EXCA)) { 238ea2f1590SDaniel Ritz u8 reg, old; 239ea2f1590SDaniel Ritz reg = old = exca_readb(socket, I365_POWER); 240ea2f1590SDaniel Ritz reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK); 241ea2f1590SDaniel Ritz 242ea2f1590SDaniel Ritz /* i82365SL-DF style */ 243ea2f1590SDaniel Ritz if (socket->flags & YENTA_16BIT_POWER_DF) { 244ea2f1590SDaniel Ritz switch (state->Vcc) { 245ea2f1590SDaniel Ritz case 33: reg |= I365_VCC_3V; break; 246ea2f1590SDaniel Ritz case 50: reg |= I365_VCC_5V; break; 247ea2f1590SDaniel Ritz default: reg = 0; break; 248ea2f1590SDaniel Ritz } 249ea2f1590SDaniel Ritz switch (state->Vpp) { 250ea2f1590SDaniel Ritz case 33: 251ea2f1590SDaniel Ritz case 50: reg |= I365_VPP1_5V; break; 252ea2f1590SDaniel Ritz case 120: reg |= I365_VPP1_12V; break; 253ea2f1590SDaniel Ritz } 254ea2f1590SDaniel Ritz } else { 255ea2f1590SDaniel Ritz /* i82365SL-B style */ 256ea2f1590SDaniel Ritz switch (state->Vcc) { 257ea2f1590SDaniel Ritz case 50: reg |= I365_VCC_5V; break; 258ea2f1590SDaniel Ritz default: reg = 0; break; 259ea2f1590SDaniel Ritz } 260ea2f1590SDaniel Ritz switch (state->Vpp) { 261ea2f1590SDaniel Ritz case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break; 262ea2f1590SDaniel Ritz case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break; 263ea2f1590SDaniel Ritz } 264ea2f1590SDaniel Ritz } 265ea2f1590SDaniel Ritz 266ea2f1590SDaniel Ritz if (reg != old) 267ea2f1590SDaniel Ritz exca_writeb(socket, I365_POWER, reg); 268ea2f1590SDaniel Ritz } else { 2691da177e4SLinus Torvalds u32 reg = 0; /* CB_SC_STPCLK? */ 2701da177e4SLinus Torvalds switch (state->Vcc) { 2711da177e4SLinus Torvalds case 33: reg = CB_SC_VCC_3V; break; 2721da177e4SLinus Torvalds case 50: reg = CB_SC_VCC_5V; break; 2731da177e4SLinus Torvalds default: reg = 0; break; 2741da177e4SLinus Torvalds } 2751da177e4SLinus Torvalds switch (state->Vpp) { 2761da177e4SLinus Torvalds case 33: reg |= CB_SC_VPP_3V; break; 2771da177e4SLinus Torvalds case 50: reg |= CB_SC_VPP_5V; break; 2781da177e4SLinus Torvalds case 120: reg |= CB_SC_VPP_12V; break; 2791da177e4SLinus Torvalds } 2801da177e4SLinus Torvalds if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) 2811da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_CONTROL, reg); 2821da177e4SLinus Torvalds } 283ea2f1590SDaniel Ritz } 2841da177e4SLinus Torvalds 2851da177e4SLinus Torvalds static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) 2861da177e4SLinus Torvalds { 2871da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 2881da177e4SLinus Torvalds u16 bridge; 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvalds yenta_set_power(socket, state); 2911da177e4SLinus Torvalds socket->io_irq = state->io_irq; 2921da177e4SLinus Torvalds bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); 2931da177e4SLinus Torvalds if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { 2941da177e4SLinus Torvalds u8 intr; 2951da177e4SLinus Torvalds bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0; 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds /* ISA interrupt control? */ 2981da177e4SLinus Torvalds intr = exca_readb(socket, I365_INTCTL); 2991da177e4SLinus Torvalds intr = (intr & ~0xf); 3001da177e4SLinus Torvalds if (!socket->cb_irq) { 3011da177e4SLinus Torvalds intr |= state->io_irq; 3021da177e4SLinus Torvalds bridge |= CB_BRIDGE_INTR; 3031da177e4SLinus Torvalds } 3041da177e4SLinus Torvalds exca_writeb(socket, I365_INTCTL, intr); 3051da177e4SLinus Torvalds } else { 3061da177e4SLinus Torvalds u8 reg; 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA); 3091da177e4SLinus Torvalds reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; 3101da177e4SLinus Torvalds reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; 3111da177e4SLinus Torvalds if (state->io_irq != socket->cb_irq) { 3121da177e4SLinus Torvalds reg |= state->io_irq; 3131da177e4SLinus Torvalds bridge |= CB_BRIDGE_INTR; 3141da177e4SLinus Torvalds } 3151da177e4SLinus Torvalds exca_writeb(socket, I365_INTCTL, reg); 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK); 3181da177e4SLinus Torvalds reg |= I365_PWR_NORESET; 3191da177e4SLinus Torvalds if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO; 3201da177e4SLinus Torvalds if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT; 3211da177e4SLinus Torvalds if (exca_readb(socket, I365_POWER) != reg) 3221da177e4SLinus Torvalds exca_writeb(socket, I365_POWER, reg); 3231da177e4SLinus Torvalds 3241da177e4SLinus Torvalds /* CSC interrupt: no ISA irq for CSC */ 3251da177e4SLinus Torvalds reg = I365_CSC_DETECT; 3261da177e4SLinus Torvalds if (state->flags & SS_IOCARD) { 3271da177e4SLinus Torvalds if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG; 3281da177e4SLinus Torvalds } else { 3291da177e4SLinus Torvalds if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1; 3301da177e4SLinus Torvalds if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2; 3311da177e4SLinus Torvalds if (state->csc_mask & SS_READY) reg |= I365_CSC_READY; 3321da177e4SLinus Torvalds } 3331da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, reg); 3341da177e4SLinus Torvalds exca_readb(socket, I365_CSC); 3351da177e4SLinus Torvalds if(sock->zoom_video) 3361da177e4SLinus Torvalds sock->zoom_video(sock, state->flags & SS_ZVCARD); 3371da177e4SLinus Torvalds } 3381da177e4SLinus Torvalds config_writew(socket, CB_BRIDGE_CONTROL, bridge); 3391da177e4SLinus Torvalds /* Socket event mask: get card insert/remove events.. */ 3401da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 3411da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); 3421da177e4SLinus Torvalds return 0; 3431da177e4SLinus Torvalds } 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) 3461da177e4SLinus Torvalds { 3471da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 3481da177e4SLinus Torvalds int map; 3491da177e4SLinus Torvalds unsigned char ioctl, addr, enable; 3501da177e4SLinus Torvalds 3511da177e4SLinus Torvalds map = io->map; 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds if (map > 1) 3541da177e4SLinus Torvalds return -EINVAL; 3551da177e4SLinus Torvalds 3561da177e4SLinus Torvalds enable = I365_ENA_IO(map); 3571da177e4SLinus Torvalds addr = exca_readb(socket, I365_ADDRWIN); 3581da177e4SLinus Torvalds 3591da177e4SLinus Torvalds /* Disable the window before changing it.. */ 3601da177e4SLinus Torvalds if (addr & enable) { 3611da177e4SLinus Torvalds addr &= ~enable; 3621da177e4SLinus Torvalds exca_writeb(socket, I365_ADDRWIN, addr); 3631da177e4SLinus Torvalds } 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds exca_writew(socket, I365_IO(map)+I365_W_START, io->start); 3661da177e4SLinus Torvalds exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop); 3671da177e4SLinus Torvalds 3681da177e4SLinus Torvalds ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); 3691da177e4SLinus Torvalds if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); 3701da177e4SLinus Torvalds if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); 3711da177e4SLinus Torvalds if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); 3721da177e4SLinus Torvalds exca_writeb(socket, I365_IOCTL, ioctl); 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds if (io->flags & MAP_ACTIVE) 3751da177e4SLinus Torvalds exca_writeb(socket, I365_ADDRWIN, addr | enable); 3761da177e4SLinus Torvalds return 0; 3771da177e4SLinus Torvalds } 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvalds static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) 3801da177e4SLinus Torvalds { 3811da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 3821da177e4SLinus Torvalds struct pci_bus_region region; 3831da177e4SLinus Torvalds int map; 3841da177e4SLinus Torvalds unsigned char addr, enable; 3851da177e4SLinus Torvalds unsigned int start, stop, card_start; 3861da177e4SLinus Torvalds unsigned short word; 3871da177e4SLinus Torvalds 3881da177e4SLinus Torvalds pcibios_resource_to_bus(socket->dev, ®ion, mem->res); 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds map = mem->map; 3911da177e4SLinus Torvalds start = region.start; 3921da177e4SLinus Torvalds stop = region.end; 3931da177e4SLinus Torvalds card_start = mem->card_start; 3941da177e4SLinus Torvalds 3951da177e4SLinus Torvalds if (map > 4 || start > stop || ((start ^ stop) >> 24) || 3961da177e4SLinus Torvalds (card_start >> 26) || mem->speed > 1000) 3971da177e4SLinus Torvalds return -EINVAL; 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds enable = I365_ENA_MEM(map); 4001da177e4SLinus Torvalds addr = exca_readb(socket, I365_ADDRWIN); 4011da177e4SLinus Torvalds if (addr & enable) { 4021da177e4SLinus Torvalds addr &= ~enable; 4031da177e4SLinus Torvalds exca_writeb(socket, I365_ADDRWIN, addr); 4041da177e4SLinus Torvalds } 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds exca_writeb(socket, CB_MEM_PAGE(map), start >> 24); 4071da177e4SLinus Torvalds 4081da177e4SLinus Torvalds word = (start >> 12) & 0x0fff; 4091da177e4SLinus Torvalds if (mem->flags & MAP_16BIT) 4101da177e4SLinus Torvalds word |= I365_MEM_16BIT; 4111da177e4SLinus Torvalds if (mem->flags & MAP_0WS) 4121da177e4SLinus Torvalds word |= I365_MEM_0WS; 4131da177e4SLinus Torvalds exca_writew(socket, I365_MEM(map) + I365_W_START, word); 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds word = (stop >> 12) & 0x0fff; 4161da177e4SLinus Torvalds switch (to_cycles(mem->speed)) { 4171da177e4SLinus Torvalds case 0: break; 4181da177e4SLinus Torvalds case 1: word |= I365_MEM_WS0; break; 4191da177e4SLinus Torvalds case 2: word |= I365_MEM_WS1; break; 4201da177e4SLinus Torvalds default: word |= I365_MEM_WS1 | I365_MEM_WS0; break; 4211da177e4SLinus Torvalds } 4221da177e4SLinus Torvalds exca_writew(socket, I365_MEM(map) + I365_W_STOP, word); 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds word = ((card_start - start) >> 12) & 0x3fff; 4251da177e4SLinus Torvalds if (mem->flags & MAP_WRPROT) 4261da177e4SLinus Torvalds word |= I365_MEM_WRPROT; 4271da177e4SLinus Torvalds if (mem->flags & MAP_ATTRIB) 4281da177e4SLinus Torvalds word |= I365_MEM_REG; 4291da177e4SLinus Torvalds exca_writew(socket, I365_MEM(map) + I365_W_OFF, word); 4301da177e4SLinus Torvalds 4311da177e4SLinus Torvalds if (mem->flags & MAP_ACTIVE) 4321da177e4SLinus Torvalds exca_writeb(socket, I365_ADDRWIN, addr | enable); 4331da177e4SLinus Torvalds return 0; 4341da177e4SLinus Torvalds } 4351da177e4SLinus Torvalds 4361da177e4SLinus Torvalds 437fa912bcbSDaniel Ritz 438fa912bcbSDaniel Ritz static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) 4391da177e4SLinus Torvalds { 440fa912bcbSDaniel Ritz unsigned int events; 441fa912bcbSDaniel Ritz struct yenta_socket *socket = (struct yenta_socket *) dev_id; 4421da177e4SLinus Torvalds u8 csc; 4431da177e4SLinus Torvalds u32 cb_event; 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds /* Clear interrupt status for the event */ 4461da177e4SLinus Torvalds cb_event = cb_readl(socket, CB_SOCKET_EVENT); 4471da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, cb_event); 4481da177e4SLinus Torvalds 4491da177e4SLinus Torvalds csc = exca_readb(socket, I365_CSC); 4501da177e4SLinus Torvalds 451e4115805SDaniel Ritz if (!(cb_event || csc)) 452e4115805SDaniel Ritz return IRQ_NONE; 453e4115805SDaniel Ritz 4541da177e4SLinus Torvalds events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ; 4551da177e4SLinus Torvalds events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0; 4561da177e4SLinus Torvalds if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { 4571da177e4SLinus Torvalds events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; 4581da177e4SLinus Torvalds } else { 4591da177e4SLinus Torvalds events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; 4601da177e4SLinus Torvalds events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; 4611da177e4SLinus Torvalds events |= (csc & I365_CSC_READY) ? SS_READY : 0; 4621da177e4SLinus Torvalds } 4631da177e4SLinus Torvalds 464fa912bcbSDaniel Ritz if (events) 4651da177e4SLinus Torvalds pcmcia_parse_events(&socket->socket, events); 466fa912bcbSDaniel Ritz 4671da177e4SLinus Torvalds return IRQ_HANDLED; 4681da177e4SLinus Torvalds } 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds static void yenta_interrupt_wrapper(unsigned long data) 4711da177e4SLinus Torvalds { 4721da177e4SLinus Torvalds struct yenta_socket *socket = (struct yenta_socket *) data; 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds yenta_interrupt(0, (void *)socket, NULL); 4751da177e4SLinus Torvalds socket->poll_timer.expires = jiffies + HZ; 4761da177e4SLinus Torvalds add_timer(&socket->poll_timer); 4771da177e4SLinus Torvalds } 4781da177e4SLinus Torvalds 4791da177e4SLinus Torvalds static void yenta_clear_maps(struct yenta_socket *socket) 4801da177e4SLinus Torvalds { 4811da177e4SLinus Torvalds int i; 4821da177e4SLinus Torvalds struct resource res = { .start = 0, .end = 0x0fff }; 4831da177e4SLinus Torvalds pccard_io_map io = { 0, 0, 0, 0, 1 }; 4841da177e4SLinus Torvalds pccard_mem_map mem = { .res = &res, }; 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds yenta_set_socket(&socket->socket, &dead_socket); 4871da177e4SLinus Torvalds for (i = 0; i < 2; i++) { 4881da177e4SLinus Torvalds io.map = i; 4891da177e4SLinus Torvalds yenta_set_io_map(&socket->socket, &io); 4901da177e4SLinus Torvalds } 4911da177e4SLinus Torvalds for (i = 0; i < 5; i++) { 4921da177e4SLinus Torvalds mem.map = i; 4931da177e4SLinus Torvalds yenta_set_mem_map(&socket->socket, &mem); 4941da177e4SLinus Torvalds } 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds 497fa912bcbSDaniel Ritz /* redoes voltage interrogation if required */ 498fa912bcbSDaniel Ritz static void yenta_interrogate(struct yenta_socket *socket) 499fa912bcbSDaniel Ritz { 500fa912bcbSDaniel Ritz u32 state; 501fa912bcbSDaniel Ritz 502fa912bcbSDaniel Ritz state = cb_readl(socket, CB_SOCKET_STATE); 503fa912bcbSDaniel Ritz if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) || 504fa912bcbSDaniel Ritz (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) || 505fa912bcbSDaniel Ritz ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD))) 506fa912bcbSDaniel Ritz cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); 507fa912bcbSDaniel Ritz } 508fa912bcbSDaniel Ritz 5091da177e4SLinus Torvalds /* Called at resume and initialization events */ 5101da177e4SLinus Torvalds static int yenta_sock_init(struct pcmcia_socket *sock) 5111da177e4SLinus Torvalds { 5121da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 5131da177e4SLinus Torvalds 5141da177e4SLinus Torvalds exca_writeb(socket, I365_GBLCTL, 0x00); 5151da177e4SLinus Torvalds exca_writeb(socket, I365_GENCTL, 0x00); 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds /* Redo card voltage interrogation */ 518fa912bcbSDaniel Ritz yenta_interrogate(socket); 5191da177e4SLinus Torvalds 5201da177e4SLinus Torvalds yenta_clear_maps(socket); 5211da177e4SLinus Torvalds 5221da177e4SLinus Torvalds if (socket->type && socket->type->sock_init) 5231da177e4SLinus Torvalds socket->type->sock_init(socket); 5241da177e4SLinus Torvalds 5251da177e4SLinus Torvalds /* Re-enable CSC interrupts */ 5261da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds return 0; 5291da177e4SLinus Torvalds } 5301da177e4SLinus Torvalds 5311da177e4SLinus Torvalds static int yenta_sock_suspend(struct pcmcia_socket *sock) 5321da177e4SLinus Torvalds { 5331da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvalds /* Disable CSC interrupts */ 5361da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, 0x0); 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds return 0; 5391da177e4SLinus Torvalds } 5401da177e4SLinus Torvalds 5411da177e4SLinus Torvalds /* 5421da177e4SLinus Torvalds * Use an adaptive allocation for the memory resource, 5431da177e4SLinus Torvalds * sometimes the memory behind pci bridges is limited: 5441da177e4SLinus Torvalds * 1/8 of the size of the io window of the parent. 545eb0a90b4SDominik Brodowski * max 4 MB, min 16 kB. We try very hard to not get below 546eb0a90b4SDominik Brodowski * the "ACC" values, though. 5471da177e4SLinus Torvalds */ 5481da177e4SLinus Torvalds #define BRIDGE_MEM_MAX 4*1024*1024 549eb0a90b4SDominik Brodowski #define BRIDGE_MEM_ACC 128*1024 5501da177e4SLinus Torvalds #define BRIDGE_MEM_MIN 16*1024 5511da177e4SLinus Torvalds 552eb0a90b4SDominik Brodowski #define BRIDGE_IO_MAX 512 553eb0a90b4SDominik Brodowski #define BRIDGE_IO_ACC 256 5541da177e4SLinus Torvalds #define BRIDGE_IO_MIN 32 5551da177e4SLinus Torvalds 5561da177e4SLinus Torvalds #ifndef PCIBIOS_MIN_CARDBUS_IO 5571da177e4SLinus Torvalds #define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO 5581da177e4SLinus Torvalds #endif 5591da177e4SLinus Torvalds 560eb0a90b4SDominik Brodowski static int yenta_search_one_res(struct resource *root, struct resource *res, 561eb0a90b4SDominik Brodowski u32 min) 562eb0a90b4SDominik Brodowski { 563eb0a90b4SDominik Brodowski u32 align, size, start, end; 564eb0a90b4SDominik Brodowski 565eb0a90b4SDominik Brodowski if (res->flags & IORESOURCE_IO) { 566eb0a90b4SDominik Brodowski align = 1024; 567eb0a90b4SDominik Brodowski size = BRIDGE_IO_MAX; 568eb0a90b4SDominik Brodowski start = PCIBIOS_MIN_CARDBUS_IO; 569eb0a90b4SDominik Brodowski end = ~0U; 570eb0a90b4SDominik Brodowski } else { 571eb0a90b4SDominik Brodowski unsigned long avail = root->end - root->start; 572eb0a90b4SDominik Brodowski int i; 573eb0a90b4SDominik Brodowski size = BRIDGE_MEM_MAX; 574eb0a90b4SDominik Brodowski if (size > avail/8) { 575eb0a90b4SDominik Brodowski size=(avail+1)/8; 576eb0a90b4SDominik Brodowski /* round size down to next power of 2 */ 577eb0a90b4SDominik Brodowski i = 0; 578eb0a90b4SDominik Brodowski while ((size /= 2) != 0) 579eb0a90b4SDominik Brodowski i++; 580eb0a90b4SDominik Brodowski size = 1 << i; 581eb0a90b4SDominik Brodowski } 582eb0a90b4SDominik Brodowski if (size < min) 583eb0a90b4SDominik Brodowski size = min; 584eb0a90b4SDominik Brodowski align = size; 585eb0a90b4SDominik Brodowski start = PCIBIOS_MIN_MEM; 586eb0a90b4SDominik Brodowski end = ~0U; 587eb0a90b4SDominik Brodowski } 588eb0a90b4SDominik Brodowski 589eb0a90b4SDominik Brodowski do { 590eb0a90b4SDominik Brodowski if (allocate_resource(root, res, size, start, end, align, 591eb0a90b4SDominik Brodowski NULL, NULL)==0) { 592eb0a90b4SDominik Brodowski return 1; 593eb0a90b4SDominik Brodowski } 594eb0a90b4SDominik Brodowski size = size/2; 595eb0a90b4SDominik Brodowski align = size; 596eb0a90b4SDominik Brodowski } while (size >= min); 597eb0a90b4SDominik Brodowski 598eb0a90b4SDominik Brodowski return 0; 599eb0a90b4SDominik Brodowski } 600eb0a90b4SDominik Brodowski 601eb0a90b4SDominik Brodowski 602eb0a90b4SDominik Brodowski static int yenta_search_res(struct yenta_socket *socket, struct resource *res, 603eb0a90b4SDominik Brodowski u32 min) 604eb0a90b4SDominik Brodowski { 605eb0a90b4SDominik Brodowski int i; 606eb0a90b4SDominik Brodowski for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) { 607eb0a90b4SDominik Brodowski struct resource * root = socket->dev->bus->resource[i]; 608eb0a90b4SDominik Brodowski if (!root) 609eb0a90b4SDominik Brodowski continue; 610eb0a90b4SDominik Brodowski 611eb0a90b4SDominik Brodowski if ((res->flags ^ root->flags) & 612eb0a90b4SDominik Brodowski (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)) 613eb0a90b4SDominik Brodowski continue; /* Wrong type */ 614eb0a90b4SDominik Brodowski 615eb0a90b4SDominik Brodowski if (yenta_search_one_res(root, res, min)) 616eb0a90b4SDominik Brodowski return 1; 617eb0a90b4SDominik Brodowski } 618eb0a90b4SDominik Brodowski return 0; 619eb0a90b4SDominik Brodowski } 620eb0a90b4SDominik Brodowski 621b3743fa4SDominik Brodowski static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) 6221da177e4SLinus Torvalds { 6231da177e4SLinus Torvalds struct resource *root, *res; 62443c34735SDominik Brodowski struct pci_bus_region region; 6251da177e4SLinus Torvalds unsigned mask; 6261da177e4SLinus Torvalds 6277925407aSIvan Kokshaysky res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; 6287925407aSIvan Kokshaysky /* Already allocated? */ 6297925407aSIvan Kokshaysky if (res->parent) 630b3743fa4SDominik Brodowski return 0; 6317925407aSIvan Kokshaysky 6321da177e4SLinus Torvalds /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ 6331da177e4SLinus Torvalds mask = ~0xfff; 6341da177e4SLinus Torvalds if (type & IORESOURCE_IO) 6351da177e4SLinus Torvalds mask = ~3; 6361da177e4SLinus Torvalds 63743c34735SDominik Brodowski res->name = socket->dev->subordinate->name; 6381da177e4SLinus Torvalds res->flags = type; 6391da177e4SLinus Torvalds 64043c34735SDominik Brodowski region.start = config_readl(socket, addr_start) & mask; 64143c34735SDominik Brodowski region.end = config_readl(socket, addr_end) | ~mask; 64243c34735SDominik Brodowski if (region.start && region.end > region.start && !override_bios) { 64343c34735SDominik Brodowski pcibios_bus_to_resource(socket->dev, res, ®ion); 644862104e5SDominik Brodowski root = pci_find_parent_resource(socket->dev, res); 645862104e5SDominik Brodowski if (root && (request_resource(root, res) == 0)) 646b3743fa4SDominik Brodowski return 0; 647862104e5SDominik Brodowski printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n", 6481da177e4SLinus Torvalds pci_name(socket->dev), nr); 6491da177e4SLinus Torvalds } 6501da177e4SLinus Torvalds 6511da177e4SLinus Torvalds if (type & IORESOURCE_IO) { 652eb0a90b4SDominik Brodowski if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) || 653eb0a90b4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_IO_ACC)) || 654b3743fa4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_IO_MIN))) 655b3743fa4SDominik Brodowski return 1; 656eb0a90b4SDominik Brodowski } else { 657eb0a90b4SDominik Brodowski if (type & IORESOURCE_PREFETCH) { 658eb0a90b4SDominik Brodowski if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || 659eb0a90b4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || 660b3743fa4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) 661b3743fa4SDominik Brodowski return 1; 662eb0a90b4SDominik Brodowski /* Approximating prefetchable by non-prefetchable */ 663eb0a90b4SDominik Brodowski res->flags = IORESOURCE_MEM; 664eb0a90b4SDominik Brodowski } 665eb0a90b4SDominik Brodowski if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || 666eb0a90b4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || 667b3743fa4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) 668b3743fa4SDominik Brodowski return 1; 669eb0a90b4SDominik Brodowski } 670eb0a90b4SDominik Brodowski 6711da177e4SLinus Torvalds printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n", 6721da177e4SLinus Torvalds pci_name(socket->dev), type); 673eb0a90b4SDominik Brodowski res->start = res->end = res->flags = 0; 674b3743fa4SDominik Brodowski return 0; 6751da177e4SLinus Torvalds } 6761da177e4SLinus Torvalds 6771da177e4SLinus Torvalds /* 6781da177e4SLinus Torvalds * Allocate the bridge mappings for the device.. 6791da177e4SLinus Torvalds */ 6801da177e4SLinus Torvalds static void yenta_allocate_resources(struct yenta_socket *socket) 6811da177e4SLinus Torvalds { 682b3743fa4SDominik Brodowski int program = 0; 683b3743fa4SDominik Brodowski program += yenta_allocate_res(socket, 0, IORESOURCE_IO, 68427879835SDominik Brodowski PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); 685b3743fa4SDominik Brodowski program += yenta_allocate_res(socket, 1, IORESOURCE_IO, 68627879835SDominik Brodowski PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); 687b3743fa4SDominik Brodowski program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH, 68827879835SDominik Brodowski PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); 689b3743fa4SDominik Brodowski program += yenta_allocate_res(socket, 3, IORESOURCE_MEM, 69027879835SDominik Brodowski PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); 691b3743fa4SDominik Brodowski if (program) 692b3743fa4SDominik Brodowski pci_setup_cardbus(socket->dev->subordinate); 6931da177e4SLinus Torvalds } 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds 6961da177e4SLinus Torvalds /* 6971da177e4SLinus Torvalds * Free the bridge mappings for the device.. 6981da177e4SLinus Torvalds */ 6991da177e4SLinus Torvalds static void yenta_free_resources(struct yenta_socket *socket) 7001da177e4SLinus Torvalds { 7011da177e4SLinus Torvalds int i; 7021da177e4SLinus Torvalds for (i=0;i<4;i++) { 7031da177e4SLinus Torvalds struct resource *res; 7041da177e4SLinus Torvalds res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; 7051da177e4SLinus Torvalds if (res->start != 0 && res->end != 0) 7061da177e4SLinus Torvalds release_resource(res); 707b3743fa4SDominik Brodowski res->start = res->end = res->flags = 0; 7081da177e4SLinus Torvalds } 7091da177e4SLinus Torvalds } 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds 7121da177e4SLinus Torvalds /* 7131da177e4SLinus Torvalds * Close it down - release our resources and go home.. 7141da177e4SLinus Torvalds */ 7151da177e4SLinus Torvalds static void yenta_close(struct pci_dev *dev) 7161da177e4SLinus Torvalds { 7171da177e4SLinus Torvalds struct yenta_socket *sock = pci_get_drvdata(dev); 7181da177e4SLinus Torvalds 719030ee39cSLinus Torvalds /* Remove the register attributes */ 720030ee39cSLinus Torvalds device_remove_file(&dev->dev, &dev_attr_yenta_registers); 721030ee39cSLinus Torvalds 7221da177e4SLinus Torvalds /* we don't want a dying socket registered */ 7231da177e4SLinus Torvalds pcmcia_unregister_socket(&sock->socket); 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds /* Disable all events so we don't die in an IRQ storm */ 7261da177e4SLinus Torvalds cb_writel(sock, CB_SOCKET_MASK, 0x0); 7271da177e4SLinus Torvalds exca_writeb(sock, I365_CSCINT, 0); 7281da177e4SLinus Torvalds 7291da177e4SLinus Torvalds if (sock->cb_irq) 7301da177e4SLinus Torvalds free_irq(sock->cb_irq, sock); 7311da177e4SLinus Torvalds else 7321da177e4SLinus Torvalds del_timer_sync(&sock->poll_timer); 7331da177e4SLinus Torvalds 7341da177e4SLinus Torvalds if (sock->base) 7351da177e4SLinus Torvalds iounmap(sock->base); 7361da177e4SLinus Torvalds yenta_free_resources(sock); 7371da177e4SLinus Torvalds 7381da177e4SLinus Torvalds pci_release_regions(dev); 7391da177e4SLinus Torvalds pci_disable_device(dev); 7401da177e4SLinus Torvalds pci_set_drvdata(dev, NULL); 7411da177e4SLinus Torvalds } 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds static struct pccard_operations yenta_socket_operations = { 7451da177e4SLinus Torvalds .init = yenta_sock_init, 7461da177e4SLinus Torvalds .suspend = yenta_sock_suspend, 7471da177e4SLinus Torvalds .get_status = yenta_get_status, 7481da177e4SLinus Torvalds .set_socket = yenta_set_socket, 7491da177e4SLinus Torvalds .set_io_map = yenta_set_io_map, 7501da177e4SLinus Torvalds .set_mem_map = yenta_set_mem_map, 7511da177e4SLinus Torvalds }; 7521da177e4SLinus Torvalds 7531da177e4SLinus Torvalds 75463e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 7551da177e4SLinus Torvalds #include "ti113x.h" 75663e7ebd0SDaniel Ritz #endif 75763e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_RICOH 7581da177e4SLinus Torvalds #include "ricoh.h" 75963e7ebd0SDaniel Ritz #endif 76063e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TOSHIBA 7611da177e4SLinus Torvalds #include "topic.h" 76263e7ebd0SDaniel Ritz #endif 76363e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_O2 7641da177e4SLinus Torvalds #include "o2micro.h" 76563e7ebd0SDaniel Ritz #endif 7661da177e4SLinus Torvalds 7671da177e4SLinus Torvalds enum { 7681da177e4SLinus Torvalds CARDBUS_TYPE_DEFAULT = -1, 7691da177e4SLinus Torvalds CARDBUS_TYPE_TI, 7701da177e4SLinus Torvalds CARDBUS_TYPE_TI113X, 7711da177e4SLinus Torvalds CARDBUS_TYPE_TI12XX, 7721da177e4SLinus Torvalds CARDBUS_TYPE_TI1250, 7731da177e4SLinus Torvalds CARDBUS_TYPE_RICOH, 774ea2f1590SDaniel Ritz CARDBUS_TYPE_TOPIC95, 7751da177e4SLinus Torvalds CARDBUS_TYPE_TOPIC97, 7761da177e4SLinus Torvalds CARDBUS_TYPE_O2MICRO, 7778c3520d4SDaniel Ritz CARDBUS_TYPE_ENE, 7781da177e4SLinus Torvalds }; 7791da177e4SLinus Torvalds 7801da177e4SLinus Torvalds /* 7811da177e4SLinus Torvalds * Different cardbus controllers have slightly different 7821da177e4SLinus Torvalds * initialization sequences etc details. List them here.. 7831da177e4SLinus Torvalds */ 7841da177e4SLinus Torvalds static struct cardbus_type cardbus_type[] = { 78563e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 7861da177e4SLinus Torvalds [CARDBUS_TYPE_TI] = { 7871da177e4SLinus Torvalds .override = ti_override, 7881da177e4SLinus Torvalds .save_state = ti_save_state, 7891da177e4SLinus Torvalds .restore_state = ti_restore_state, 7901da177e4SLinus Torvalds .sock_init = ti_init, 7911da177e4SLinus Torvalds }, 7921da177e4SLinus Torvalds [CARDBUS_TYPE_TI113X] = { 7931da177e4SLinus Torvalds .override = ti113x_override, 7941da177e4SLinus Torvalds .save_state = ti_save_state, 7951da177e4SLinus Torvalds .restore_state = ti_restore_state, 7961da177e4SLinus Torvalds .sock_init = ti_init, 7971da177e4SLinus Torvalds }, 7981da177e4SLinus Torvalds [CARDBUS_TYPE_TI12XX] = { 7991da177e4SLinus Torvalds .override = ti12xx_override, 8001da177e4SLinus Torvalds .save_state = ti_save_state, 8011da177e4SLinus Torvalds .restore_state = ti_restore_state, 8021da177e4SLinus Torvalds .sock_init = ti_init, 8031da177e4SLinus Torvalds }, 8041da177e4SLinus Torvalds [CARDBUS_TYPE_TI1250] = { 8051da177e4SLinus Torvalds .override = ti1250_override, 8061da177e4SLinus Torvalds .save_state = ti_save_state, 8071da177e4SLinus Torvalds .restore_state = ti_restore_state, 8081da177e4SLinus Torvalds .sock_init = ti_init, 8091da177e4SLinus Torvalds }, 81063e7ebd0SDaniel Ritz #endif 81163e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_RICOH 8121da177e4SLinus Torvalds [CARDBUS_TYPE_RICOH] = { 8131da177e4SLinus Torvalds .override = ricoh_override, 8141da177e4SLinus Torvalds .save_state = ricoh_save_state, 8151da177e4SLinus Torvalds .restore_state = ricoh_restore_state, 8161da177e4SLinus Torvalds }, 81763e7ebd0SDaniel Ritz #endif 81863e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TOSHIBA 819ea2f1590SDaniel Ritz [CARDBUS_TYPE_TOPIC95] = { 820ea2f1590SDaniel Ritz .override = topic95_override, 821ea2f1590SDaniel Ritz }, 8221da177e4SLinus Torvalds [CARDBUS_TYPE_TOPIC97] = { 8231da177e4SLinus Torvalds .override = topic97_override, 8241da177e4SLinus Torvalds }, 82563e7ebd0SDaniel Ritz #endif 82663e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_O2 8271da177e4SLinus Torvalds [CARDBUS_TYPE_O2MICRO] = { 8281da177e4SLinus Torvalds .override = o2micro_override, 8291da177e4SLinus Torvalds .restore_state = o2micro_restore_state, 8301da177e4SLinus Torvalds }, 83163e7ebd0SDaniel Ritz #endif 83263e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 8338c3520d4SDaniel Ritz [CARDBUS_TYPE_ENE] = { 8348c3520d4SDaniel Ritz .override = ene_override, 8358c3520d4SDaniel Ritz .save_state = ti_save_state, 8368c3520d4SDaniel Ritz .restore_state = ti_restore_state, 8378c3520d4SDaniel Ritz .sock_init = ti_init, 8388c3520d4SDaniel Ritz }, 83963e7ebd0SDaniel Ritz #endif 8401da177e4SLinus Torvalds }; 8411da177e4SLinus Torvalds 8421da177e4SLinus Torvalds 8431da177e4SLinus Torvalds /* 8441da177e4SLinus Torvalds * Only probe "regular" interrupts, don't 8451da177e4SLinus Torvalds * touch dangerous spots like the mouse irq, 8461da177e4SLinus Torvalds * because there are mice that apparently 8471da177e4SLinus Torvalds * get really confused if they get fondled 8481da177e4SLinus Torvalds * too intimately. 8491da177e4SLinus Torvalds * 8501da177e4SLinus Torvalds * Default to 11, 10, 9, 7, 6, 5, 4, 3. 8511da177e4SLinus Torvalds */ 8521da177e4SLinus Torvalds static u32 isa_interrupts = 0x0ef8; 8531da177e4SLinus Torvalds 8541da177e4SLinus Torvalds static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask) 8551da177e4SLinus Torvalds { 8561da177e4SLinus Torvalds int i; 8571da177e4SLinus Torvalds unsigned long val; 8581da177e4SLinus Torvalds u32 mask; 8591da177e4SLinus Torvalds 8601da177e4SLinus Torvalds /* 8611da177e4SLinus Torvalds * Probe for usable interrupts using the force 8621da177e4SLinus Torvalds * register to generate bogus card status events. 8631da177e4SLinus Torvalds */ 8641da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 8651da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); 8661da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, 0); 8671da177e4SLinus Torvalds val = probe_irq_on() & isa_irq_mask; 8681da177e4SLinus Torvalds for (i = 1; i < 16; i++) { 8691da177e4SLinus Torvalds if (!((val >> i) & 1)) 8701da177e4SLinus Torvalds continue; 8711da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4)); 8721da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); 8731da177e4SLinus Torvalds udelay(100); 8741da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 8751da177e4SLinus Torvalds } 8761da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, 0); 8771da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, 0); 8781da177e4SLinus Torvalds 8791da177e4SLinus Torvalds mask = probe_irq_mask(val) & 0xffff; 8801da177e4SLinus Torvalds 8811da177e4SLinus Torvalds return mask; 8821da177e4SLinus Torvalds } 8831da177e4SLinus Torvalds 8841da177e4SLinus Torvalds 88563e7ebd0SDaniel Ritz /** 88663e7ebd0SDaniel Ritz * yenta PCI irq probing. 88763e7ebd0SDaniel Ritz * currently only used in the TI/EnE initialization code 88863e7ebd0SDaniel Ritz */ 88963e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 89063e7ebd0SDaniel Ritz 8911da177e4SLinus Torvalds /* interrupt handler, only used during probing */ 8921da177e4SLinus Torvalds static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *regs) 8931da177e4SLinus Torvalds { 8941da177e4SLinus Torvalds struct yenta_socket *socket = (struct yenta_socket *) dev_id; 8951da177e4SLinus Torvalds u8 csc; 8961da177e4SLinus Torvalds u32 cb_event; 8971da177e4SLinus Torvalds 8981da177e4SLinus Torvalds /* Clear interrupt status for the event */ 8991da177e4SLinus Torvalds cb_event = cb_readl(socket, CB_SOCKET_EVENT); 9001da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 9011da177e4SLinus Torvalds csc = exca_readb(socket, I365_CSC); 9021da177e4SLinus Torvalds 9031da177e4SLinus Torvalds if (cb_event || csc) { 9041da177e4SLinus Torvalds socket->probe_status = 1; 9051da177e4SLinus Torvalds return IRQ_HANDLED; 9061da177e4SLinus Torvalds } 9071da177e4SLinus Torvalds 9081da177e4SLinus Torvalds return IRQ_NONE; 9091da177e4SLinus Torvalds } 9101da177e4SLinus Torvalds 9111da177e4SLinus Torvalds /* probes the PCI interrupt, use only on override functions */ 9121da177e4SLinus Torvalds static int yenta_probe_cb_irq(struct yenta_socket *socket) 9131da177e4SLinus Torvalds { 9141da177e4SLinus Torvalds if (!socket->cb_irq) 9151da177e4SLinus Torvalds return -1; 9161da177e4SLinus Torvalds 9171da177e4SLinus Torvalds socket->probe_status = 0; 9181da177e4SLinus Torvalds 9191da177e4SLinus Torvalds if (request_irq(socket->cb_irq, yenta_probe_handler, SA_SHIRQ, "yenta", socket)) { 9201da177e4SLinus Torvalds printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n"); 9211da177e4SLinus Torvalds return -1; 9221da177e4SLinus Torvalds } 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds /* generate interrupt, wait */ 9251da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG); 9261da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 9271da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); 9281da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); 9291da177e4SLinus Torvalds 9301da177e4SLinus Torvalds msleep(100); 9311da177e4SLinus Torvalds 9321da177e4SLinus Torvalds /* disable interrupts */ 9331da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, 0); 9341da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, 0); 9351da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 9361da177e4SLinus Torvalds exca_readb(socket, I365_CSC); 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds free_irq(socket->cb_irq, socket); 9391da177e4SLinus Torvalds 9401da177e4SLinus Torvalds return (int) socket->probe_status; 9411da177e4SLinus Torvalds } 9421da177e4SLinus Torvalds 94363e7ebd0SDaniel Ritz #endif /* CONFIG_YENTA_TI */ 9441da177e4SLinus Torvalds 9451da177e4SLinus Torvalds 9461da177e4SLinus Torvalds /* 9471da177e4SLinus Torvalds * Set static data that doesn't need re-initializing.. 9481da177e4SLinus Torvalds */ 9491da177e4SLinus Torvalds static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask) 9501da177e4SLinus Torvalds { 9511da177e4SLinus Torvalds socket->socket.pci_irq = socket->cb_irq; 952fa912bcbSDaniel Ritz if (isa_probe) 9531da177e4SLinus Torvalds socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); 954fa912bcbSDaniel Ritz else 955fa912bcbSDaniel Ritz socket->socket.irq_mask = 0; 9561da177e4SLinus Torvalds 9571da177e4SLinus Torvalds printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n", 9581da177e4SLinus Torvalds socket->socket.irq_mask, socket->cb_irq); 9591da177e4SLinus Torvalds } 9601da177e4SLinus Torvalds 9611da177e4SLinus Torvalds /* 9621da177e4SLinus Torvalds * Initialize the standard cardbus registers 9631da177e4SLinus Torvalds */ 9641da177e4SLinus Torvalds static void yenta_config_init(struct yenta_socket *socket) 9651da177e4SLinus Torvalds { 9661da177e4SLinus Torvalds u16 bridge; 9671da177e4SLinus Torvalds struct pci_dev *dev = socket->dev; 9688e5d17ebSDominik Brodowski struct pci_bus_region region; 9691da177e4SLinus Torvalds 9708e5d17ebSDominik Brodowski pcibios_resource_to_bus(socket->dev, ®ion, &dev->resource[0]); 9711da177e4SLinus Torvalds 9721da177e4SLinus Torvalds config_writel(socket, CB_LEGACY_MODE_BASE, 0); 9738e5d17ebSDominik Brodowski config_writel(socket, PCI_BASE_ADDRESS_0, region.start); 9741da177e4SLinus Torvalds config_writew(socket, PCI_COMMAND, 9751da177e4SLinus Torvalds PCI_COMMAND_IO | 9761da177e4SLinus Torvalds PCI_COMMAND_MEMORY | 9771da177e4SLinus Torvalds PCI_COMMAND_MASTER | 9781da177e4SLinus Torvalds PCI_COMMAND_WAIT); 9791da177e4SLinus Torvalds 9801da177e4SLinus Torvalds /* MAGIC NUMBERS! Fixme */ 9811da177e4SLinus Torvalds config_writeb(socket, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); 9821da177e4SLinus Torvalds config_writeb(socket, PCI_LATENCY_TIMER, 168); 9831da177e4SLinus Torvalds config_writel(socket, PCI_PRIMARY_BUS, 9841da177e4SLinus Torvalds (176 << 24) | /* sec. latency timer */ 9851da177e4SLinus Torvalds (dev->subordinate->subordinate << 16) | /* subordinate bus */ 9861da177e4SLinus Torvalds (dev->subordinate->secondary << 8) | /* secondary bus */ 9871da177e4SLinus Torvalds dev->subordinate->primary); /* primary bus */ 9881da177e4SLinus Torvalds 9891da177e4SLinus Torvalds /* 9901da177e4SLinus Torvalds * Set up the bridging state: 9911da177e4SLinus Torvalds * - enable write posting. 9921da177e4SLinus Torvalds * - memory window 0 prefetchable, window 1 non-prefetchable 9931da177e4SLinus Torvalds * - PCI interrupts enabled if a PCI interrupt exists.. 9941da177e4SLinus Torvalds */ 9951da177e4SLinus Torvalds bridge = config_readw(socket, CB_BRIDGE_CONTROL); 996a413c090SDaniel Ritz bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); 997a413c090SDaniel Ritz bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN; 9981da177e4SLinus Torvalds config_writew(socket, CB_BRIDGE_CONTROL, bridge); 9991da177e4SLinus Torvalds } 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds /* 10021da177e4SLinus Torvalds * Initialize a cardbus controller. Make sure we have a usable 10031da177e4SLinus Torvalds * interrupt, and that we can map the cardbus area. Fill in the 10041da177e4SLinus Torvalds * socket information structure.. 10051da177e4SLinus Torvalds */ 10061da177e4SLinus Torvalds static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_id *id) 10071da177e4SLinus Torvalds { 10081da177e4SLinus Torvalds struct yenta_socket *socket; 10091da177e4SLinus Torvalds int ret; 10101da177e4SLinus Torvalds 1011c7fb0b35SIvan Kokshaysky /* 1012c7fb0b35SIvan Kokshaysky * If we failed to assign proper bus numbers for this cardbus 1013c7fb0b35SIvan Kokshaysky * controller during PCI probe, its subordinate pci_bus is NULL. 1014c7fb0b35SIvan Kokshaysky * Bail out if so. 1015c7fb0b35SIvan Kokshaysky */ 1016c7fb0b35SIvan Kokshaysky if (!dev->subordinate) { 10175a23f347SLinus Torvalds printk(KERN_ERR "Yenta: no bus associated with %s! " 10185a23f347SLinus Torvalds "(try 'pci=assign-busses')\n", pci_name(dev)); 1019c7fb0b35SIvan Kokshaysky return -ENODEV; 1020c7fb0b35SIvan Kokshaysky } 1021c7fb0b35SIvan Kokshaysky 10228084b372SDominik Brodowski socket = kzalloc(sizeof(struct yenta_socket), GFP_KERNEL); 10231da177e4SLinus Torvalds if (!socket) 10241da177e4SLinus Torvalds return -ENOMEM; 10251da177e4SLinus Torvalds 10261da177e4SLinus Torvalds /* prepare pcmcia_socket */ 10271da177e4SLinus Torvalds socket->socket.ops = ¥ta_socket_operations; 10281da177e4SLinus Torvalds socket->socket.resource_ops = &pccard_nonstatic_ops; 10291da177e4SLinus Torvalds socket->socket.dev.dev = &dev->dev; 10301da177e4SLinus Torvalds socket->socket.driver_data = socket; 10311da177e4SLinus Torvalds socket->socket.owner = THIS_MODULE; 10325bc6b68aSRussell King socket->socket.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD; 10335bc6b68aSRussell King socket->socket.map_size = 0x1000; 10345bc6b68aSRussell King socket->socket.cb_dev = dev; 10351da177e4SLinus Torvalds 10361da177e4SLinus Torvalds /* prepare struct yenta_socket */ 10371da177e4SLinus Torvalds socket->dev = dev; 10381da177e4SLinus Torvalds pci_set_drvdata(dev, socket); 10391da177e4SLinus Torvalds 10401da177e4SLinus Torvalds /* 10411da177e4SLinus Torvalds * Do some basic sanity checking.. 10421da177e4SLinus Torvalds */ 10431da177e4SLinus Torvalds if (pci_enable_device(dev)) { 10441da177e4SLinus Torvalds ret = -EBUSY; 10451da177e4SLinus Torvalds goto free; 10461da177e4SLinus Torvalds } 10471da177e4SLinus Torvalds 10481da177e4SLinus Torvalds ret = pci_request_regions(dev, "yenta_socket"); 10491da177e4SLinus Torvalds if (ret) 10501da177e4SLinus Torvalds goto disable; 10511da177e4SLinus Torvalds 10521da177e4SLinus Torvalds if (!pci_resource_start(dev, 0)) { 10531da177e4SLinus Torvalds printk(KERN_ERR "No cardbus resource!\n"); 10541da177e4SLinus Torvalds ret = -ENODEV; 10551da177e4SLinus Torvalds goto release; 10561da177e4SLinus Torvalds } 10571da177e4SLinus Torvalds 10581da177e4SLinus Torvalds /* 10591da177e4SLinus Torvalds * Ok, start setup.. Map the cardbus registers, 10601da177e4SLinus Torvalds * and request the IRQ. 10611da177e4SLinus Torvalds */ 10621da177e4SLinus Torvalds socket->base = ioremap(pci_resource_start(dev, 0), 0x1000); 10631da177e4SLinus Torvalds if (!socket->base) { 10641da177e4SLinus Torvalds ret = -ENOMEM; 10651da177e4SLinus Torvalds goto release; 10661da177e4SLinus Torvalds } 10671da177e4SLinus Torvalds 10681da177e4SLinus Torvalds /* 10691da177e4SLinus Torvalds * report the subsystem vendor and device for help debugging 10701da177e4SLinus Torvalds * the irq stuff... 10711da177e4SLinus Torvalds */ 10721da177e4SLinus Torvalds printk(KERN_INFO "Yenta: CardBus bridge found at %s [%04x:%04x]\n", 10731da177e4SLinus Torvalds pci_name(dev), dev->subsystem_vendor, dev->subsystem_device); 10741da177e4SLinus Torvalds 10751da177e4SLinus Torvalds yenta_config_init(socket); 10761da177e4SLinus Torvalds 10771da177e4SLinus Torvalds /* Disable all events */ 10781da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, 0x0); 10791da177e4SLinus Torvalds 10801da177e4SLinus Torvalds /* Set up the bridge regions.. */ 10811da177e4SLinus Torvalds yenta_allocate_resources(socket); 10821da177e4SLinus Torvalds 10831da177e4SLinus Torvalds socket->cb_irq = dev->irq; 10841da177e4SLinus Torvalds 10851da177e4SLinus Torvalds /* Do we have special options for the device? */ 10861da177e4SLinus Torvalds if (id->driver_data != CARDBUS_TYPE_DEFAULT && 10871da177e4SLinus Torvalds id->driver_data < ARRAY_SIZE(cardbus_type)) { 10881da177e4SLinus Torvalds socket->type = &cardbus_type[id->driver_data]; 10891da177e4SLinus Torvalds 10901da177e4SLinus Torvalds ret = socket->type->override(socket); 10911da177e4SLinus Torvalds if (ret < 0) 10921da177e4SLinus Torvalds goto unmap; 10931da177e4SLinus Torvalds } 10941da177e4SLinus Torvalds 10951da177e4SLinus Torvalds /* We must finish initialization here */ 10961da177e4SLinus Torvalds 10971da177e4SLinus Torvalds if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, "yenta", socket)) { 10981da177e4SLinus Torvalds /* No IRQ or request_irq failed. Poll */ 10991da177e4SLinus Torvalds socket->cb_irq = 0; /* But zero is a valid IRQ number. */ 11001da177e4SLinus Torvalds init_timer(&socket->poll_timer); 11011da177e4SLinus Torvalds socket->poll_timer.function = yenta_interrupt_wrapper; 11021da177e4SLinus Torvalds socket->poll_timer.data = (unsigned long)socket; 11031da177e4SLinus Torvalds socket->poll_timer.expires = jiffies + HZ; 11041da177e4SLinus Torvalds add_timer(&socket->poll_timer); 11055bc6b68aSRussell King printk(KERN_INFO "Yenta: no PCI IRQ, CardBus support disabled for this socket.\n" 11065bc6b68aSRussell King KERN_INFO "Yenta: check your BIOS CardBus, BIOS IRQ or ACPI settings.\n"); 11075bc6b68aSRussell King } else { 11085bc6b68aSRussell King socket->socket.features |= SS_CAP_CARDBUS; 11091da177e4SLinus Torvalds } 11101da177e4SLinus Torvalds 11111da177e4SLinus Torvalds /* Figure out what the dang thing can do for the PCMCIA layer... */ 1112fa912bcbSDaniel Ritz yenta_interrogate(socket); 11131da177e4SLinus Torvalds yenta_get_socket_capabilities(socket, isa_interrupts); 11141da177e4SLinus Torvalds printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); 11151da177e4SLinus Torvalds 11161da177e4SLinus Torvalds /* Register it with the pcmcia layer.. */ 11171da177e4SLinus Torvalds ret = pcmcia_register_socket(&socket->socket); 1118030ee39cSLinus Torvalds if (ret == 0) { 1119030ee39cSLinus Torvalds /* Add the yenta register attributes */ 1120030ee39cSLinus Torvalds device_create_file(&dev->dev, &dev_attr_yenta_registers); 11211da177e4SLinus Torvalds goto out; 1122030ee39cSLinus Torvalds } 11231da177e4SLinus Torvalds 11241da177e4SLinus Torvalds unmap: 11251da177e4SLinus Torvalds iounmap(socket->base); 11261da177e4SLinus Torvalds release: 11271da177e4SLinus Torvalds pci_release_regions(dev); 11281da177e4SLinus Torvalds disable: 11291da177e4SLinus Torvalds pci_disable_device(dev); 11301da177e4SLinus Torvalds free: 11311da177e4SLinus Torvalds kfree(socket); 11321da177e4SLinus Torvalds out: 11331da177e4SLinus Torvalds return ret; 11341da177e4SLinus Torvalds } 11351da177e4SLinus Torvalds 11361da177e4SLinus Torvalds 11371da177e4SLinus Torvalds static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) 11381da177e4SLinus Torvalds { 11391da177e4SLinus Torvalds struct yenta_socket *socket = pci_get_drvdata(dev); 11401da177e4SLinus Torvalds int ret; 11411da177e4SLinus Torvalds 11421da177e4SLinus Torvalds ret = pcmcia_socket_dev_suspend(&dev->dev, state); 11431da177e4SLinus Torvalds 11441da177e4SLinus Torvalds if (socket) { 11451da177e4SLinus Torvalds if (socket->type && socket->type->save_state) 11461da177e4SLinus Torvalds socket->type->save_state(socket); 11471da177e4SLinus Torvalds 11481da177e4SLinus Torvalds /* FIXME: pci_save_state needs to have a better interface */ 11491da177e4SLinus Torvalds pci_save_state(dev); 11501da177e4SLinus Torvalds pci_read_config_dword(dev, 16*4, &socket->saved_state[0]); 11511da177e4SLinus Torvalds pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); 1152d58da590SDavid Shaohua Li pci_disable_device(dev); 11531da177e4SLinus Torvalds 11541da177e4SLinus Torvalds /* 11551da177e4SLinus Torvalds * Some laptops (IBM T22) do not like us putting the Cardbus 11561da177e4SLinus Torvalds * bridge into D3. At a guess, some other laptop will 11571da177e4SLinus Torvalds * probably require this, so leave it commented out for now. 11581da177e4SLinus Torvalds */ 11591da177e4SLinus Torvalds /* pci_set_power_state(dev, 3); */ 11601da177e4SLinus Torvalds } 11611da177e4SLinus Torvalds 11621da177e4SLinus Torvalds return ret; 11631da177e4SLinus Torvalds } 11641da177e4SLinus Torvalds 11651da177e4SLinus Torvalds 11661da177e4SLinus Torvalds static int yenta_dev_resume (struct pci_dev *dev) 11671da177e4SLinus Torvalds { 11681da177e4SLinus Torvalds struct yenta_socket *socket = pci_get_drvdata(dev); 11691da177e4SLinus Torvalds 11701da177e4SLinus Torvalds if (socket) { 11711da177e4SLinus Torvalds pci_set_power_state(dev, 0); 11721da177e4SLinus Torvalds /* FIXME: pci_restore_state needs to have a better interface */ 11731da177e4SLinus Torvalds pci_restore_state(dev); 11741da177e4SLinus Torvalds pci_write_config_dword(dev, 16*4, socket->saved_state[0]); 11751da177e4SLinus Torvalds pci_write_config_dword(dev, 17*4, socket->saved_state[1]); 1176d58da590SDavid Shaohua Li pci_enable_device(dev); 1177d58da590SDavid Shaohua Li pci_set_master(dev); 11781da177e4SLinus Torvalds 11791da177e4SLinus Torvalds if (socket->type && socket->type->restore_state) 11801da177e4SLinus Torvalds socket->type->restore_state(socket); 11811da177e4SLinus Torvalds } 11821da177e4SLinus Torvalds 11831da177e4SLinus Torvalds return pcmcia_socket_dev_resume(&dev->dev); 11841da177e4SLinus Torvalds } 11851da177e4SLinus Torvalds 11861da177e4SLinus Torvalds 11871da177e4SLinus Torvalds #define CB_ID(vend,dev,type) \ 11881da177e4SLinus Torvalds { \ 11891da177e4SLinus Torvalds .vendor = vend, \ 11901da177e4SLinus Torvalds .device = dev, \ 11911da177e4SLinus Torvalds .subvendor = PCI_ANY_ID, \ 11921da177e4SLinus Torvalds .subdevice = PCI_ANY_ID, \ 11931da177e4SLinus Torvalds .class = PCI_CLASS_BRIDGE_CARDBUS << 8, \ 11941da177e4SLinus Torvalds .class_mask = ~0, \ 11951da177e4SLinus Torvalds .driver_data = CARDBUS_TYPE_##type, \ 11961da177e4SLinus Torvalds } 11971da177e4SLinus Torvalds 11981da177e4SLinus Torvalds static struct pci_device_id yenta_table [] = { 11991da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI), 12001da177e4SLinus Torvalds 12011da177e4SLinus Torvalds /* 12021da177e4SLinus Torvalds * TBD: Check if these TI variants can use more 12031da177e4SLinus Torvalds * advanced overrides instead. (I can't get the 12041da177e4SLinus Torvalds * data sheets for these devices. --rmk) 12051da177e4SLinus Torvalds */ 120663e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 12071da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210, TI), 12081da177e4SLinus Torvalds 12091da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130, TI113X), 12101da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1131, TI113X), 12111da177e4SLinus Torvalds 12121da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211, TI12XX), 12131da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1220, TI12XX), 12141da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1221, TI12XX), 12151da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1225, TI12XX), 12161da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251A, TI12XX), 12171da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251B, TI12XX), 12181da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, TI12XX), 12191da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1450, TI12XX), 12201da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1451A, TI12XX), 12211da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510, TI12XX), 12221da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520, TI12XX), 12231da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1620, TI12XX), 12241da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX), 12251da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX), 12261da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX), 12271da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4510, TI12XX), 12281da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4520, TI12XX), 12291da177e4SLinus Torvalds 12301da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), 12311da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), 12321da177e4SLinus Torvalds 12336c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX), 12346c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX), 12356c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX), 12366c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX), 12376c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX), 12386c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX), 12396c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX), 12406c1a10dbSDaniel Ritz 1241f9cb8b71SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX), 1242f9cb8b71SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX), 1243f9cb8b71SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX), 1244f9cb8b71SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX), 12458c3520d4SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), 12468c3520d4SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), 12478c3520d4SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), 12488c3520d4SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE), 124963e7ebd0SDaniel Ritz #endif /* CONFIG_YENTA_TI */ 12501da177e4SLinus Torvalds 125163e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_RICOH 12521da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), 12531da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), 12541da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475, RICOH), 12551da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), 12561da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), 125763e7ebd0SDaniel Ritz #endif 12581da177e4SLinus Torvalds 125963e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TOSHIBA 1260ea2f1590SDaniel Ritz CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95), 12611da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), 12621da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), 126363e7ebd0SDaniel Ritz #endif 12641da177e4SLinus Torvalds 126563e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_O2 12661da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO), 126763e7ebd0SDaniel Ritz #endif 12681da177e4SLinus Torvalds 12691da177e4SLinus Torvalds /* match any cardbus bridge */ 12701da177e4SLinus Torvalds CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT), 12711da177e4SLinus Torvalds { /* all zeroes */ } 12721da177e4SLinus Torvalds }; 12731da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, yenta_table); 12741da177e4SLinus Torvalds 12751da177e4SLinus Torvalds 12761da177e4SLinus Torvalds static struct pci_driver yenta_cardbus_driver = { 12771da177e4SLinus Torvalds .name = "yenta_cardbus", 12781da177e4SLinus Torvalds .id_table = yenta_table, 12791da177e4SLinus Torvalds .probe = yenta_probe, 12801da177e4SLinus Torvalds .remove = __devexit_p(yenta_close), 12811da177e4SLinus Torvalds .suspend = yenta_dev_suspend, 12821da177e4SLinus Torvalds .resume = yenta_dev_resume, 12831da177e4SLinus Torvalds }; 12841da177e4SLinus Torvalds 12851da177e4SLinus Torvalds 12861da177e4SLinus Torvalds static int __init yenta_socket_init(void) 12871da177e4SLinus Torvalds { 12881da177e4SLinus Torvalds return pci_register_driver (¥ta_cardbus_driver); 12891da177e4SLinus Torvalds } 12901da177e4SLinus Torvalds 12911da177e4SLinus Torvalds 12921da177e4SLinus Torvalds static void __exit yenta_socket_exit (void) 12931da177e4SLinus Torvalds { 12941da177e4SLinus Torvalds pci_unregister_driver (¥ta_cardbus_driver); 12951da177e4SLinus Torvalds } 12961da177e4SLinus Torvalds 12971da177e4SLinus Torvalds 12981da177e4SLinus Torvalds module_init(yenta_socket_init); 12991da177e4SLinus Torvalds module_exit(yenta_socket_exit); 13001da177e4SLinus Torvalds 13011da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 1302