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 290d250a481SDaniel Ritz /* if powering down: do it immediately */ 291d250a481SDaniel Ritz if (state->Vcc == 0) 2921da177e4SLinus Torvalds yenta_set_power(socket, state); 293d250a481SDaniel Ritz 2941da177e4SLinus Torvalds socket->io_irq = state->io_irq; 2951da177e4SLinus Torvalds bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); 2961da177e4SLinus Torvalds if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { 2971da177e4SLinus Torvalds u8 intr; 2981da177e4SLinus Torvalds bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0; 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds /* ISA interrupt control? */ 3011da177e4SLinus Torvalds intr = exca_readb(socket, I365_INTCTL); 3021da177e4SLinus Torvalds intr = (intr & ~0xf); 3031da177e4SLinus Torvalds if (!socket->cb_irq) { 3041da177e4SLinus Torvalds intr |= state->io_irq; 3051da177e4SLinus Torvalds bridge |= CB_BRIDGE_INTR; 3061da177e4SLinus Torvalds } 3071da177e4SLinus Torvalds exca_writeb(socket, I365_INTCTL, intr); 3081da177e4SLinus Torvalds } else { 3091da177e4SLinus Torvalds u8 reg; 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA); 3121da177e4SLinus Torvalds reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; 3131da177e4SLinus Torvalds reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; 3141da177e4SLinus Torvalds if (state->io_irq != socket->cb_irq) { 3151da177e4SLinus Torvalds reg |= state->io_irq; 3161da177e4SLinus Torvalds bridge |= CB_BRIDGE_INTR; 3171da177e4SLinus Torvalds } 3181da177e4SLinus Torvalds exca_writeb(socket, I365_INTCTL, reg); 3191da177e4SLinus Torvalds 3201da177e4SLinus Torvalds reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK); 3211da177e4SLinus Torvalds reg |= I365_PWR_NORESET; 3221da177e4SLinus Torvalds if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO; 3231da177e4SLinus Torvalds if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT; 3241da177e4SLinus Torvalds if (exca_readb(socket, I365_POWER) != reg) 3251da177e4SLinus Torvalds exca_writeb(socket, I365_POWER, reg); 3261da177e4SLinus Torvalds 3271da177e4SLinus Torvalds /* CSC interrupt: no ISA irq for CSC */ 3281da177e4SLinus Torvalds reg = I365_CSC_DETECT; 3291da177e4SLinus Torvalds if (state->flags & SS_IOCARD) { 3301da177e4SLinus Torvalds if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG; 3311da177e4SLinus Torvalds } else { 3321da177e4SLinus Torvalds if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1; 3331da177e4SLinus Torvalds if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2; 3341da177e4SLinus Torvalds if (state->csc_mask & SS_READY) reg |= I365_CSC_READY; 3351da177e4SLinus Torvalds } 3361da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, reg); 3371da177e4SLinus Torvalds exca_readb(socket, I365_CSC); 3381da177e4SLinus Torvalds if(sock->zoom_video) 3391da177e4SLinus Torvalds sock->zoom_video(sock, state->flags & SS_ZVCARD); 3401da177e4SLinus Torvalds } 3411da177e4SLinus Torvalds config_writew(socket, CB_BRIDGE_CONTROL, bridge); 3421da177e4SLinus Torvalds /* Socket event mask: get card insert/remove events.. */ 3431da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 3441da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); 345d250a481SDaniel Ritz 346d250a481SDaniel Ritz /* if powering up: do it as the last step when the socket is configured */ 347d250a481SDaniel Ritz if (state->Vcc != 0) 348d250a481SDaniel Ritz yenta_set_power(socket, state); 3491da177e4SLinus Torvalds return 0; 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) 3531da177e4SLinus Torvalds { 3541da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 3551da177e4SLinus Torvalds int map; 3561da177e4SLinus Torvalds unsigned char ioctl, addr, enable; 3571da177e4SLinus Torvalds 3581da177e4SLinus Torvalds map = io->map; 3591da177e4SLinus Torvalds 3601da177e4SLinus Torvalds if (map > 1) 3611da177e4SLinus Torvalds return -EINVAL; 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds enable = I365_ENA_IO(map); 3641da177e4SLinus Torvalds addr = exca_readb(socket, I365_ADDRWIN); 3651da177e4SLinus Torvalds 3661da177e4SLinus Torvalds /* Disable the window before changing it.. */ 3671da177e4SLinus Torvalds if (addr & enable) { 3681da177e4SLinus Torvalds addr &= ~enable; 3691da177e4SLinus Torvalds exca_writeb(socket, I365_ADDRWIN, addr); 3701da177e4SLinus Torvalds } 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds exca_writew(socket, I365_IO(map)+I365_W_START, io->start); 3731da177e4SLinus Torvalds exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop); 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); 3761da177e4SLinus Torvalds if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); 3771da177e4SLinus Torvalds if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); 3781da177e4SLinus Torvalds if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); 3791da177e4SLinus Torvalds exca_writeb(socket, I365_IOCTL, ioctl); 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds if (io->flags & MAP_ACTIVE) 3821da177e4SLinus Torvalds exca_writeb(socket, I365_ADDRWIN, addr | enable); 3831da177e4SLinus Torvalds return 0; 3841da177e4SLinus Torvalds } 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) 3871da177e4SLinus Torvalds { 3881da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 3891da177e4SLinus Torvalds struct pci_bus_region region; 3901da177e4SLinus Torvalds int map; 3911da177e4SLinus Torvalds unsigned char addr, enable; 3921da177e4SLinus Torvalds unsigned int start, stop, card_start; 3931da177e4SLinus Torvalds unsigned short word; 3941da177e4SLinus Torvalds 3951da177e4SLinus Torvalds pcibios_resource_to_bus(socket->dev, ®ion, mem->res); 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds map = mem->map; 3981da177e4SLinus Torvalds start = region.start; 3991da177e4SLinus Torvalds stop = region.end; 4001da177e4SLinus Torvalds card_start = mem->card_start; 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds if (map > 4 || start > stop || ((start ^ stop) >> 24) || 4031da177e4SLinus Torvalds (card_start >> 26) || mem->speed > 1000) 4041da177e4SLinus Torvalds return -EINVAL; 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds enable = I365_ENA_MEM(map); 4071da177e4SLinus Torvalds addr = exca_readb(socket, I365_ADDRWIN); 4081da177e4SLinus Torvalds if (addr & enable) { 4091da177e4SLinus Torvalds addr &= ~enable; 4101da177e4SLinus Torvalds exca_writeb(socket, I365_ADDRWIN, addr); 4111da177e4SLinus Torvalds } 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds exca_writeb(socket, CB_MEM_PAGE(map), start >> 24); 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds word = (start >> 12) & 0x0fff; 4161da177e4SLinus Torvalds if (mem->flags & MAP_16BIT) 4171da177e4SLinus Torvalds word |= I365_MEM_16BIT; 4181da177e4SLinus Torvalds if (mem->flags & MAP_0WS) 4191da177e4SLinus Torvalds word |= I365_MEM_0WS; 4201da177e4SLinus Torvalds exca_writew(socket, I365_MEM(map) + I365_W_START, word); 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds word = (stop >> 12) & 0x0fff; 4231da177e4SLinus Torvalds switch (to_cycles(mem->speed)) { 4241da177e4SLinus Torvalds case 0: break; 4251da177e4SLinus Torvalds case 1: word |= I365_MEM_WS0; break; 4261da177e4SLinus Torvalds case 2: word |= I365_MEM_WS1; break; 4271da177e4SLinus Torvalds default: word |= I365_MEM_WS1 | I365_MEM_WS0; break; 4281da177e4SLinus Torvalds } 4291da177e4SLinus Torvalds exca_writew(socket, I365_MEM(map) + I365_W_STOP, word); 4301da177e4SLinus Torvalds 4311da177e4SLinus Torvalds word = ((card_start - start) >> 12) & 0x3fff; 4321da177e4SLinus Torvalds if (mem->flags & MAP_WRPROT) 4331da177e4SLinus Torvalds word |= I365_MEM_WRPROT; 4341da177e4SLinus Torvalds if (mem->flags & MAP_ATTRIB) 4351da177e4SLinus Torvalds word |= I365_MEM_REG; 4361da177e4SLinus Torvalds exca_writew(socket, I365_MEM(map) + I365_W_OFF, word); 4371da177e4SLinus Torvalds 4381da177e4SLinus Torvalds if (mem->flags & MAP_ACTIVE) 4391da177e4SLinus Torvalds exca_writeb(socket, I365_ADDRWIN, addr | enable); 4401da177e4SLinus Torvalds return 0; 4411da177e4SLinus Torvalds } 4421da177e4SLinus Torvalds 4431da177e4SLinus Torvalds 444fa912bcbSDaniel Ritz 445fa912bcbSDaniel Ritz static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) 4461da177e4SLinus Torvalds { 447fa912bcbSDaniel Ritz unsigned int events; 448fa912bcbSDaniel Ritz struct yenta_socket *socket = (struct yenta_socket *) dev_id; 4491da177e4SLinus Torvalds u8 csc; 4501da177e4SLinus Torvalds u32 cb_event; 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds /* Clear interrupt status for the event */ 4531da177e4SLinus Torvalds cb_event = cb_readl(socket, CB_SOCKET_EVENT); 4541da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, cb_event); 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds csc = exca_readb(socket, I365_CSC); 4571da177e4SLinus Torvalds 458e4115805SDaniel Ritz if (!(cb_event || csc)) 459e4115805SDaniel Ritz return IRQ_NONE; 460e4115805SDaniel Ritz 4611da177e4SLinus Torvalds events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ; 4621da177e4SLinus Torvalds events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0; 4631da177e4SLinus Torvalds if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { 4641da177e4SLinus Torvalds events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; 4651da177e4SLinus Torvalds } else { 4661da177e4SLinus Torvalds events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; 4671da177e4SLinus Torvalds events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; 4681da177e4SLinus Torvalds events |= (csc & I365_CSC_READY) ? SS_READY : 0; 4691da177e4SLinus Torvalds } 4701da177e4SLinus Torvalds 471fa912bcbSDaniel Ritz if (events) 4721da177e4SLinus Torvalds pcmcia_parse_events(&socket->socket, events); 473fa912bcbSDaniel Ritz 4741da177e4SLinus Torvalds return IRQ_HANDLED; 4751da177e4SLinus Torvalds } 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds static void yenta_interrupt_wrapper(unsigned long data) 4781da177e4SLinus Torvalds { 4791da177e4SLinus Torvalds struct yenta_socket *socket = (struct yenta_socket *) data; 4801da177e4SLinus Torvalds 4811da177e4SLinus Torvalds yenta_interrupt(0, (void *)socket, NULL); 4821da177e4SLinus Torvalds socket->poll_timer.expires = jiffies + HZ; 4831da177e4SLinus Torvalds add_timer(&socket->poll_timer); 4841da177e4SLinus Torvalds } 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds static void yenta_clear_maps(struct yenta_socket *socket) 4871da177e4SLinus Torvalds { 4881da177e4SLinus Torvalds int i; 4891da177e4SLinus Torvalds struct resource res = { .start = 0, .end = 0x0fff }; 4901da177e4SLinus Torvalds pccard_io_map io = { 0, 0, 0, 0, 1 }; 4911da177e4SLinus Torvalds pccard_mem_map mem = { .res = &res, }; 4921da177e4SLinus Torvalds 4931da177e4SLinus Torvalds yenta_set_socket(&socket->socket, &dead_socket); 4941da177e4SLinus Torvalds for (i = 0; i < 2; i++) { 4951da177e4SLinus Torvalds io.map = i; 4961da177e4SLinus Torvalds yenta_set_io_map(&socket->socket, &io); 4971da177e4SLinus Torvalds } 4981da177e4SLinus Torvalds for (i = 0; i < 5; i++) { 4991da177e4SLinus Torvalds mem.map = i; 5001da177e4SLinus Torvalds yenta_set_mem_map(&socket->socket, &mem); 5011da177e4SLinus Torvalds } 5021da177e4SLinus Torvalds } 5031da177e4SLinus Torvalds 504fa912bcbSDaniel Ritz /* redoes voltage interrogation if required */ 505fa912bcbSDaniel Ritz static void yenta_interrogate(struct yenta_socket *socket) 506fa912bcbSDaniel Ritz { 507fa912bcbSDaniel Ritz u32 state; 508fa912bcbSDaniel Ritz 509fa912bcbSDaniel Ritz state = cb_readl(socket, CB_SOCKET_STATE); 510fa912bcbSDaniel Ritz if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) || 511fa912bcbSDaniel Ritz (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) || 512fa912bcbSDaniel Ritz ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD))) 513fa912bcbSDaniel Ritz cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); 514fa912bcbSDaniel Ritz } 515fa912bcbSDaniel Ritz 5161da177e4SLinus Torvalds /* Called at resume and initialization events */ 5171da177e4SLinus Torvalds static int yenta_sock_init(struct pcmcia_socket *sock) 5181da177e4SLinus Torvalds { 5191da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds exca_writeb(socket, I365_GBLCTL, 0x00); 5221da177e4SLinus Torvalds exca_writeb(socket, I365_GENCTL, 0x00); 5231da177e4SLinus Torvalds 5241da177e4SLinus Torvalds /* Redo card voltage interrogation */ 525fa912bcbSDaniel Ritz yenta_interrogate(socket); 5261da177e4SLinus Torvalds 5271da177e4SLinus Torvalds yenta_clear_maps(socket); 5281da177e4SLinus Torvalds 5291da177e4SLinus Torvalds if (socket->type && socket->type->sock_init) 5301da177e4SLinus Torvalds socket->type->sock_init(socket); 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds /* Re-enable CSC interrupts */ 5331da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvalds return 0; 5361da177e4SLinus Torvalds } 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds static int yenta_sock_suspend(struct pcmcia_socket *sock) 5391da177e4SLinus Torvalds { 5401da177e4SLinus Torvalds struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 5411da177e4SLinus Torvalds 5421da177e4SLinus Torvalds /* Disable CSC interrupts */ 5431da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, 0x0); 5441da177e4SLinus Torvalds 5451da177e4SLinus Torvalds return 0; 5461da177e4SLinus Torvalds } 5471da177e4SLinus Torvalds 5481da177e4SLinus Torvalds /* 5491da177e4SLinus Torvalds * Use an adaptive allocation for the memory resource, 5501da177e4SLinus Torvalds * sometimes the memory behind pci bridges is limited: 5511da177e4SLinus Torvalds * 1/8 of the size of the io window of the parent. 552eb0a90b4SDominik Brodowski * max 4 MB, min 16 kB. We try very hard to not get below 553eb0a90b4SDominik Brodowski * the "ACC" values, though. 5541da177e4SLinus Torvalds */ 5551da177e4SLinus Torvalds #define BRIDGE_MEM_MAX 4*1024*1024 556eb0a90b4SDominik Brodowski #define BRIDGE_MEM_ACC 128*1024 5571da177e4SLinus Torvalds #define BRIDGE_MEM_MIN 16*1024 5581da177e4SLinus Torvalds 559eb0a90b4SDominik Brodowski #define BRIDGE_IO_MAX 512 560eb0a90b4SDominik Brodowski #define BRIDGE_IO_ACC 256 5611da177e4SLinus Torvalds #define BRIDGE_IO_MIN 32 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds #ifndef PCIBIOS_MIN_CARDBUS_IO 5641da177e4SLinus Torvalds #define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO 5651da177e4SLinus Torvalds #endif 5661da177e4SLinus Torvalds 567eb0a90b4SDominik Brodowski static int yenta_search_one_res(struct resource *root, struct resource *res, 568eb0a90b4SDominik Brodowski u32 min) 569eb0a90b4SDominik Brodowski { 570eb0a90b4SDominik Brodowski u32 align, size, start, end; 571eb0a90b4SDominik Brodowski 572eb0a90b4SDominik Brodowski if (res->flags & IORESOURCE_IO) { 573eb0a90b4SDominik Brodowski align = 1024; 574eb0a90b4SDominik Brodowski size = BRIDGE_IO_MAX; 575eb0a90b4SDominik Brodowski start = PCIBIOS_MIN_CARDBUS_IO; 576eb0a90b4SDominik Brodowski end = ~0U; 577eb0a90b4SDominik Brodowski } else { 578eb0a90b4SDominik Brodowski unsigned long avail = root->end - root->start; 579eb0a90b4SDominik Brodowski int i; 580eb0a90b4SDominik Brodowski size = BRIDGE_MEM_MAX; 581eb0a90b4SDominik Brodowski if (size > avail/8) { 582eb0a90b4SDominik Brodowski size=(avail+1)/8; 583eb0a90b4SDominik Brodowski /* round size down to next power of 2 */ 584eb0a90b4SDominik Brodowski i = 0; 585eb0a90b4SDominik Brodowski while ((size /= 2) != 0) 586eb0a90b4SDominik Brodowski i++; 587eb0a90b4SDominik Brodowski size = 1 << i; 588eb0a90b4SDominik Brodowski } 589eb0a90b4SDominik Brodowski if (size < min) 590eb0a90b4SDominik Brodowski size = min; 591eb0a90b4SDominik Brodowski align = size; 592eb0a90b4SDominik Brodowski start = PCIBIOS_MIN_MEM; 593eb0a90b4SDominik Brodowski end = ~0U; 594eb0a90b4SDominik Brodowski } 595eb0a90b4SDominik Brodowski 596eb0a90b4SDominik Brodowski do { 597eb0a90b4SDominik Brodowski if (allocate_resource(root, res, size, start, end, align, 598eb0a90b4SDominik Brodowski NULL, NULL)==0) { 599eb0a90b4SDominik Brodowski return 1; 600eb0a90b4SDominik Brodowski } 601eb0a90b4SDominik Brodowski size = size/2; 602eb0a90b4SDominik Brodowski align = size; 603eb0a90b4SDominik Brodowski } while (size >= min); 604eb0a90b4SDominik Brodowski 605eb0a90b4SDominik Brodowski return 0; 606eb0a90b4SDominik Brodowski } 607eb0a90b4SDominik Brodowski 608eb0a90b4SDominik Brodowski 609eb0a90b4SDominik Brodowski static int yenta_search_res(struct yenta_socket *socket, struct resource *res, 610eb0a90b4SDominik Brodowski u32 min) 611eb0a90b4SDominik Brodowski { 612eb0a90b4SDominik Brodowski int i; 613eb0a90b4SDominik Brodowski for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) { 614eb0a90b4SDominik Brodowski struct resource * root = socket->dev->bus->resource[i]; 615eb0a90b4SDominik Brodowski if (!root) 616eb0a90b4SDominik Brodowski continue; 617eb0a90b4SDominik Brodowski 618eb0a90b4SDominik Brodowski if ((res->flags ^ root->flags) & 619eb0a90b4SDominik Brodowski (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)) 620eb0a90b4SDominik Brodowski continue; /* Wrong type */ 621eb0a90b4SDominik Brodowski 622eb0a90b4SDominik Brodowski if (yenta_search_one_res(root, res, min)) 623eb0a90b4SDominik Brodowski return 1; 624eb0a90b4SDominik Brodowski } 625eb0a90b4SDominik Brodowski return 0; 626eb0a90b4SDominik Brodowski } 627eb0a90b4SDominik Brodowski 628b3743fa4SDominik Brodowski static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) 6291da177e4SLinus Torvalds { 6301da177e4SLinus Torvalds struct resource *root, *res; 63143c34735SDominik Brodowski struct pci_bus_region region; 6321da177e4SLinus Torvalds unsigned mask; 6331da177e4SLinus Torvalds 6347925407aSIvan Kokshaysky res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; 6357925407aSIvan Kokshaysky /* Already allocated? */ 6367925407aSIvan Kokshaysky if (res->parent) 637b3743fa4SDominik Brodowski return 0; 6387925407aSIvan Kokshaysky 6391da177e4SLinus Torvalds /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ 6401da177e4SLinus Torvalds mask = ~0xfff; 6411da177e4SLinus Torvalds if (type & IORESOURCE_IO) 6421da177e4SLinus Torvalds mask = ~3; 6431da177e4SLinus Torvalds 64443c34735SDominik Brodowski res->name = socket->dev->subordinate->name; 6451da177e4SLinus Torvalds res->flags = type; 6461da177e4SLinus Torvalds 64743c34735SDominik Brodowski region.start = config_readl(socket, addr_start) & mask; 64843c34735SDominik Brodowski region.end = config_readl(socket, addr_end) | ~mask; 64943c34735SDominik Brodowski if (region.start && region.end > region.start && !override_bios) { 65043c34735SDominik Brodowski pcibios_bus_to_resource(socket->dev, res, ®ion); 651862104e5SDominik Brodowski root = pci_find_parent_resource(socket->dev, res); 652862104e5SDominik Brodowski if (root && (request_resource(root, res) == 0)) 653b3743fa4SDominik Brodowski return 0; 654862104e5SDominik Brodowski printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n", 6551da177e4SLinus Torvalds pci_name(socket->dev), nr); 6561da177e4SLinus Torvalds } 6571da177e4SLinus Torvalds 6581da177e4SLinus Torvalds if (type & IORESOURCE_IO) { 659eb0a90b4SDominik Brodowski if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) || 660eb0a90b4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_IO_ACC)) || 661b3743fa4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_IO_MIN))) 662b3743fa4SDominik Brodowski return 1; 663eb0a90b4SDominik Brodowski } else { 664eb0a90b4SDominik Brodowski if (type & IORESOURCE_PREFETCH) { 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 /* Approximating prefetchable by non-prefetchable */ 670eb0a90b4SDominik Brodowski res->flags = IORESOURCE_MEM; 671eb0a90b4SDominik Brodowski } 672eb0a90b4SDominik Brodowski if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || 673eb0a90b4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || 674b3743fa4SDominik Brodowski (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) 675b3743fa4SDominik Brodowski return 1; 676eb0a90b4SDominik Brodowski } 677eb0a90b4SDominik Brodowski 6781da177e4SLinus Torvalds printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n", 6791da177e4SLinus Torvalds pci_name(socket->dev), type); 680eb0a90b4SDominik Brodowski res->start = res->end = res->flags = 0; 681b3743fa4SDominik Brodowski return 0; 6821da177e4SLinus Torvalds } 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds /* 6851da177e4SLinus Torvalds * Allocate the bridge mappings for the device.. 6861da177e4SLinus Torvalds */ 6871da177e4SLinus Torvalds static void yenta_allocate_resources(struct yenta_socket *socket) 6881da177e4SLinus Torvalds { 689b3743fa4SDominik Brodowski int program = 0; 690b3743fa4SDominik Brodowski program += yenta_allocate_res(socket, 0, IORESOURCE_IO, 69127879835SDominik Brodowski PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); 692b3743fa4SDominik Brodowski program += yenta_allocate_res(socket, 1, IORESOURCE_IO, 69327879835SDominik Brodowski PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); 694b3743fa4SDominik Brodowski program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH, 69527879835SDominik Brodowski PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); 696b3743fa4SDominik Brodowski program += yenta_allocate_res(socket, 3, IORESOURCE_MEM, 69727879835SDominik Brodowski PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); 698b3743fa4SDominik Brodowski if (program) 699b3743fa4SDominik Brodowski pci_setup_cardbus(socket->dev->subordinate); 7001da177e4SLinus Torvalds } 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvalds 7031da177e4SLinus Torvalds /* 7041da177e4SLinus Torvalds * Free the bridge mappings for the device.. 7051da177e4SLinus Torvalds */ 7061da177e4SLinus Torvalds static void yenta_free_resources(struct yenta_socket *socket) 7071da177e4SLinus Torvalds { 7081da177e4SLinus Torvalds int i; 7091da177e4SLinus Torvalds for (i=0;i<4;i++) { 7101da177e4SLinus Torvalds struct resource *res; 7111da177e4SLinus Torvalds res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; 7121da177e4SLinus Torvalds if (res->start != 0 && res->end != 0) 7131da177e4SLinus Torvalds release_resource(res); 714b3743fa4SDominik Brodowski res->start = res->end = res->flags = 0; 7151da177e4SLinus Torvalds } 7161da177e4SLinus Torvalds } 7171da177e4SLinus Torvalds 7181da177e4SLinus Torvalds 7191da177e4SLinus Torvalds /* 7201da177e4SLinus Torvalds * Close it down - release our resources and go home.. 7211da177e4SLinus Torvalds */ 7221da177e4SLinus Torvalds static void yenta_close(struct pci_dev *dev) 7231da177e4SLinus Torvalds { 7241da177e4SLinus Torvalds struct yenta_socket *sock = pci_get_drvdata(dev); 7251da177e4SLinus Torvalds 726030ee39cSLinus Torvalds /* Remove the register attributes */ 727030ee39cSLinus Torvalds device_remove_file(&dev->dev, &dev_attr_yenta_registers); 728030ee39cSLinus Torvalds 7291da177e4SLinus Torvalds /* we don't want a dying socket registered */ 7301da177e4SLinus Torvalds pcmcia_unregister_socket(&sock->socket); 7311da177e4SLinus Torvalds 7321da177e4SLinus Torvalds /* Disable all events so we don't die in an IRQ storm */ 7331da177e4SLinus Torvalds cb_writel(sock, CB_SOCKET_MASK, 0x0); 7341da177e4SLinus Torvalds exca_writeb(sock, I365_CSCINT, 0); 7351da177e4SLinus Torvalds 7361da177e4SLinus Torvalds if (sock->cb_irq) 7371da177e4SLinus Torvalds free_irq(sock->cb_irq, sock); 7381da177e4SLinus Torvalds else 7391da177e4SLinus Torvalds del_timer_sync(&sock->poll_timer); 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds if (sock->base) 7421da177e4SLinus Torvalds iounmap(sock->base); 7431da177e4SLinus Torvalds yenta_free_resources(sock); 7441da177e4SLinus Torvalds 7451da177e4SLinus Torvalds pci_release_regions(dev); 7461da177e4SLinus Torvalds pci_disable_device(dev); 7471da177e4SLinus Torvalds pci_set_drvdata(dev, NULL); 7481da177e4SLinus Torvalds } 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds 7511da177e4SLinus Torvalds static struct pccard_operations yenta_socket_operations = { 7521da177e4SLinus Torvalds .init = yenta_sock_init, 7531da177e4SLinus Torvalds .suspend = yenta_sock_suspend, 7541da177e4SLinus Torvalds .get_status = yenta_get_status, 7551da177e4SLinus Torvalds .set_socket = yenta_set_socket, 7561da177e4SLinus Torvalds .set_io_map = yenta_set_io_map, 7571da177e4SLinus Torvalds .set_mem_map = yenta_set_mem_map, 7581da177e4SLinus Torvalds }; 7591da177e4SLinus Torvalds 7601da177e4SLinus Torvalds 76163e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 7621da177e4SLinus Torvalds #include "ti113x.h" 76363e7ebd0SDaniel Ritz #endif 76463e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_RICOH 7651da177e4SLinus Torvalds #include "ricoh.h" 76663e7ebd0SDaniel Ritz #endif 76763e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TOSHIBA 7681da177e4SLinus Torvalds #include "topic.h" 76963e7ebd0SDaniel Ritz #endif 77063e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_O2 7711da177e4SLinus Torvalds #include "o2micro.h" 77263e7ebd0SDaniel Ritz #endif 7731da177e4SLinus Torvalds 7741da177e4SLinus Torvalds enum { 7751da177e4SLinus Torvalds CARDBUS_TYPE_DEFAULT = -1, 7761da177e4SLinus Torvalds CARDBUS_TYPE_TI, 7771da177e4SLinus Torvalds CARDBUS_TYPE_TI113X, 7781da177e4SLinus Torvalds CARDBUS_TYPE_TI12XX, 7791da177e4SLinus Torvalds CARDBUS_TYPE_TI1250, 7801da177e4SLinus Torvalds CARDBUS_TYPE_RICOH, 781ea2f1590SDaniel Ritz CARDBUS_TYPE_TOPIC95, 7821da177e4SLinus Torvalds CARDBUS_TYPE_TOPIC97, 7831da177e4SLinus Torvalds CARDBUS_TYPE_O2MICRO, 7848c3520d4SDaniel Ritz CARDBUS_TYPE_ENE, 7851da177e4SLinus Torvalds }; 7861da177e4SLinus Torvalds 7871da177e4SLinus Torvalds /* 7881da177e4SLinus Torvalds * Different cardbus controllers have slightly different 7891da177e4SLinus Torvalds * initialization sequences etc details. List them here.. 7901da177e4SLinus Torvalds */ 7911da177e4SLinus Torvalds static struct cardbus_type cardbus_type[] = { 79263e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 7931da177e4SLinus Torvalds [CARDBUS_TYPE_TI] = { 7941da177e4SLinus Torvalds .override = ti_override, 7951da177e4SLinus Torvalds .save_state = ti_save_state, 7961da177e4SLinus Torvalds .restore_state = ti_restore_state, 7971da177e4SLinus Torvalds .sock_init = ti_init, 7981da177e4SLinus Torvalds }, 7991da177e4SLinus Torvalds [CARDBUS_TYPE_TI113X] = { 8001da177e4SLinus Torvalds .override = ti113x_override, 8011da177e4SLinus Torvalds .save_state = ti_save_state, 8021da177e4SLinus Torvalds .restore_state = ti_restore_state, 8031da177e4SLinus Torvalds .sock_init = ti_init, 8041da177e4SLinus Torvalds }, 8051da177e4SLinus Torvalds [CARDBUS_TYPE_TI12XX] = { 8061da177e4SLinus Torvalds .override = ti12xx_override, 8071da177e4SLinus Torvalds .save_state = ti_save_state, 8081da177e4SLinus Torvalds .restore_state = ti_restore_state, 8091da177e4SLinus Torvalds .sock_init = ti_init, 8101da177e4SLinus Torvalds }, 8111da177e4SLinus Torvalds [CARDBUS_TYPE_TI1250] = { 8121da177e4SLinus Torvalds .override = ti1250_override, 8131da177e4SLinus Torvalds .save_state = ti_save_state, 8141da177e4SLinus Torvalds .restore_state = ti_restore_state, 8151da177e4SLinus Torvalds .sock_init = ti_init, 8161da177e4SLinus Torvalds }, 81763e7ebd0SDaniel Ritz #endif 81863e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_RICOH 8191da177e4SLinus Torvalds [CARDBUS_TYPE_RICOH] = { 8201da177e4SLinus Torvalds .override = ricoh_override, 8211da177e4SLinus Torvalds .save_state = ricoh_save_state, 8221da177e4SLinus Torvalds .restore_state = ricoh_restore_state, 8231da177e4SLinus Torvalds }, 82463e7ebd0SDaniel Ritz #endif 82563e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TOSHIBA 826ea2f1590SDaniel Ritz [CARDBUS_TYPE_TOPIC95] = { 827ea2f1590SDaniel Ritz .override = topic95_override, 828ea2f1590SDaniel Ritz }, 8291da177e4SLinus Torvalds [CARDBUS_TYPE_TOPIC97] = { 8301da177e4SLinus Torvalds .override = topic97_override, 8311da177e4SLinus Torvalds }, 83263e7ebd0SDaniel Ritz #endif 83363e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_O2 8341da177e4SLinus Torvalds [CARDBUS_TYPE_O2MICRO] = { 8351da177e4SLinus Torvalds .override = o2micro_override, 8361da177e4SLinus Torvalds .restore_state = o2micro_restore_state, 8371da177e4SLinus Torvalds }, 83863e7ebd0SDaniel Ritz #endif 83963e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 8408c3520d4SDaniel Ritz [CARDBUS_TYPE_ENE] = { 8418c3520d4SDaniel Ritz .override = ene_override, 8428c3520d4SDaniel Ritz .save_state = ti_save_state, 8438c3520d4SDaniel Ritz .restore_state = ti_restore_state, 8448c3520d4SDaniel Ritz .sock_init = ti_init, 8458c3520d4SDaniel Ritz }, 84663e7ebd0SDaniel Ritz #endif 8471da177e4SLinus Torvalds }; 8481da177e4SLinus Torvalds 8491da177e4SLinus Torvalds 8501da177e4SLinus Torvalds /* 8511da177e4SLinus Torvalds * Only probe "regular" interrupts, don't 8521da177e4SLinus Torvalds * touch dangerous spots like the mouse irq, 8531da177e4SLinus Torvalds * because there are mice that apparently 8541da177e4SLinus Torvalds * get really confused if they get fondled 8551da177e4SLinus Torvalds * too intimately. 8561da177e4SLinus Torvalds * 8571da177e4SLinus Torvalds * Default to 11, 10, 9, 7, 6, 5, 4, 3. 8581da177e4SLinus Torvalds */ 8591da177e4SLinus Torvalds static u32 isa_interrupts = 0x0ef8; 8601da177e4SLinus Torvalds 8611da177e4SLinus Torvalds static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask) 8621da177e4SLinus Torvalds { 8631da177e4SLinus Torvalds int i; 8641da177e4SLinus Torvalds unsigned long val; 8651da177e4SLinus Torvalds u32 mask; 8661da177e4SLinus Torvalds 8671da177e4SLinus Torvalds /* 8681da177e4SLinus Torvalds * Probe for usable interrupts using the force 8691da177e4SLinus Torvalds * register to generate bogus card status events. 8701da177e4SLinus Torvalds */ 8711da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 8721da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); 8731da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, 0); 8741da177e4SLinus Torvalds val = probe_irq_on() & isa_irq_mask; 8751da177e4SLinus Torvalds for (i = 1; i < 16; i++) { 8761da177e4SLinus Torvalds if (!((val >> i) & 1)) 8771da177e4SLinus Torvalds continue; 8781da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4)); 8791da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); 8801da177e4SLinus Torvalds udelay(100); 8811da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 8821da177e4SLinus Torvalds } 8831da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, 0); 8841da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, 0); 8851da177e4SLinus Torvalds 8861da177e4SLinus Torvalds mask = probe_irq_mask(val) & 0xffff; 8871da177e4SLinus Torvalds 8881da177e4SLinus Torvalds return mask; 8891da177e4SLinus Torvalds } 8901da177e4SLinus Torvalds 8911da177e4SLinus Torvalds 89263e7ebd0SDaniel Ritz /** 89363e7ebd0SDaniel Ritz * yenta PCI irq probing. 89463e7ebd0SDaniel Ritz * currently only used in the TI/EnE initialization code 89563e7ebd0SDaniel Ritz */ 89663e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 89763e7ebd0SDaniel Ritz 8981da177e4SLinus Torvalds /* interrupt handler, only used during probing */ 8991da177e4SLinus Torvalds static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *regs) 9001da177e4SLinus Torvalds { 9011da177e4SLinus Torvalds struct yenta_socket *socket = (struct yenta_socket *) dev_id; 9021da177e4SLinus Torvalds u8 csc; 9031da177e4SLinus Torvalds u32 cb_event; 9041da177e4SLinus Torvalds 9051da177e4SLinus Torvalds /* Clear interrupt status for the event */ 9061da177e4SLinus Torvalds cb_event = cb_readl(socket, CB_SOCKET_EVENT); 9071da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 9081da177e4SLinus Torvalds csc = exca_readb(socket, I365_CSC); 9091da177e4SLinus Torvalds 9101da177e4SLinus Torvalds if (cb_event || csc) { 9111da177e4SLinus Torvalds socket->probe_status = 1; 9121da177e4SLinus Torvalds return IRQ_HANDLED; 9131da177e4SLinus Torvalds } 9141da177e4SLinus Torvalds 9151da177e4SLinus Torvalds return IRQ_NONE; 9161da177e4SLinus Torvalds } 9171da177e4SLinus Torvalds 9181da177e4SLinus Torvalds /* probes the PCI interrupt, use only on override functions */ 9191da177e4SLinus Torvalds static int yenta_probe_cb_irq(struct yenta_socket *socket) 9201da177e4SLinus Torvalds { 9211da177e4SLinus Torvalds if (!socket->cb_irq) 9221da177e4SLinus Torvalds return -1; 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds socket->probe_status = 0; 9251da177e4SLinus Torvalds 9261da177e4SLinus Torvalds if (request_irq(socket->cb_irq, yenta_probe_handler, SA_SHIRQ, "yenta", socket)) { 9271da177e4SLinus Torvalds printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n"); 9281da177e4SLinus Torvalds return -1; 9291da177e4SLinus Torvalds } 9301da177e4SLinus Torvalds 9311da177e4SLinus Torvalds /* generate interrupt, wait */ 9321da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG); 9331da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 9341da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); 9351da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); 9361da177e4SLinus Torvalds 9371da177e4SLinus Torvalds msleep(100); 9381da177e4SLinus Torvalds 9391da177e4SLinus Torvalds /* disable interrupts */ 9401da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, 0); 9411da177e4SLinus Torvalds exca_writeb(socket, I365_CSCINT, 0); 9421da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_EVENT, -1); 9431da177e4SLinus Torvalds exca_readb(socket, I365_CSC); 9441da177e4SLinus Torvalds 9451da177e4SLinus Torvalds free_irq(socket->cb_irq, socket); 9461da177e4SLinus Torvalds 9471da177e4SLinus Torvalds return (int) socket->probe_status; 9481da177e4SLinus Torvalds } 9491da177e4SLinus Torvalds 95063e7ebd0SDaniel Ritz #endif /* CONFIG_YENTA_TI */ 9511da177e4SLinus Torvalds 9521da177e4SLinus Torvalds 9531da177e4SLinus Torvalds /* 9541da177e4SLinus Torvalds * Set static data that doesn't need re-initializing.. 9551da177e4SLinus Torvalds */ 9561da177e4SLinus Torvalds static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask) 9571da177e4SLinus Torvalds { 9581da177e4SLinus Torvalds socket->socket.pci_irq = socket->cb_irq; 959fa912bcbSDaniel Ritz if (isa_probe) 9601da177e4SLinus Torvalds socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); 961fa912bcbSDaniel Ritz else 962fa912bcbSDaniel Ritz socket->socket.irq_mask = 0; 9631da177e4SLinus Torvalds 9641da177e4SLinus Torvalds printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n", 9651da177e4SLinus Torvalds socket->socket.irq_mask, socket->cb_irq); 9661da177e4SLinus Torvalds } 9671da177e4SLinus Torvalds 9681da177e4SLinus Torvalds /* 9691da177e4SLinus Torvalds * Initialize the standard cardbus registers 9701da177e4SLinus Torvalds */ 9711da177e4SLinus Torvalds static void yenta_config_init(struct yenta_socket *socket) 9721da177e4SLinus Torvalds { 9731da177e4SLinus Torvalds u16 bridge; 9741da177e4SLinus Torvalds struct pci_dev *dev = socket->dev; 9758e5d17ebSDominik Brodowski struct pci_bus_region region; 9761da177e4SLinus Torvalds 9778e5d17ebSDominik Brodowski pcibios_resource_to_bus(socket->dev, ®ion, &dev->resource[0]); 9781da177e4SLinus Torvalds 9791da177e4SLinus Torvalds config_writel(socket, CB_LEGACY_MODE_BASE, 0); 9808e5d17ebSDominik Brodowski config_writel(socket, PCI_BASE_ADDRESS_0, region.start); 9811da177e4SLinus Torvalds config_writew(socket, PCI_COMMAND, 9821da177e4SLinus Torvalds PCI_COMMAND_IO | 9831da177e4SLinus Torvalds PCI_COMMAND_MEMORY | 9841da177e4SLinus Torvalds PCI_COMMAND_MASTER | 9851da177e4SLinus Torvalds PCI_COMMAND_WAIT); 9861da177e4SLinus Torvalds 9871da177e4SLinus Torvalds /* MAGIC NUMBERS! Fixme */ 9881da177e4SLinus Torvalds config_writeb(socket, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); 9891da177e4SLinus Torvalds config_writeb(socket, PCI_LATENCY_TIMER, 168); 9901da177e4SLinus Torvalds config_writel(socket, PCI_PRIMARY_BUS, 9911da177e4SLinus Torvalds (176 << 24) | /* sec. latency timer */ 9921da177e4SLinus Torvalds (dev->subordinate->subordinate << 16) | /* subordinate bus */ 9931da177e4SLinus Torvalds (dev->subordinate->secondary << 8) | /* secondary bus */ 9941da177e4SLinus Torvalds dev->subordinate->primary); /* primary bus */ 9951da177e4SLinus Torvalds 9961da177e4SLinus Torvalds /* 9971da177e4SLinus Torvalds * Set up the bridging state: 9981da177e4SLinus Torvalds * - enable write posting. 9991da177e4SLinus Torvalds * - memory window 0 prefetchable, window 1 non-prefetchable 10001da177e4SLinus Torvalds * - PCI interrupts enabled if a PCI interrupt exists.. 10011da177e4SLinus Torvalds */ 10021da177e4SLinus Torvalds bridge = config_readw(socket, CB_BRIDGE_CONTROL); 1003a413c090SDaniel Ritz bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); 1004a413c090SDaniel Ritz bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN; 10051da177e4SLinus Torvalds config_writew(socket, CB_BRIDGE_CONTROL, bridge); 10061da177e4SLinus Torvalds } 10071da177e4SLinus Torvalds 10081da177e4SLinus Torvalds /* 10091da177e4SLinus Torvalds * Initialize a cardbus controller. Make sure we have a usable 10101da177e4SLinus Torvalds * interrupt, and that we can map the cardbus area. Fill in the 10111da177e4SLinus Torvalds * socket information structure.. 10121da177e4SLinus Torvalds */ 10131da177e4SLinus Torvalds static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_id *id) 10141da177e4SLinus Torvalds { 10151da177e4SLinus Torvalds struct yenta_socket *socket; 10161da177e4SLinus Torvalds int ret; 10171da177e4SLinus Torvalds 1018c7fb0b35SIvan Kokshaysky /* 1019c7fb0b35SIvan Kokshaysky * If we failed to assign proper bus numbers for this cardbus 1020c7fb0b35SIvan Kokshaysky * controller during PCI probe, its subordinate pci_bus is NULL. 1021c7fb0b35SIvan Kokshaysky * Bail out if so. 1022c7fb0b35SIvan Kokshaysky */ 1023c7fb0b35SIvan Kokshaysky if (!dev->subordinate) { 10245a23f347SLinus Torvalds printk(KERN_ERR "Yenta: no bus associated with %s! " 10255a23f347SLinus Torvalds "(try 'pci=assign-busses')\n", pci_name(dev)); 1026c7fb0b35SIvan Kokshaysky return -ENODEV; 1027c7fb0b35SIvan Kokshaysky } 1028c7fb0b35SIvan Kokshaysky 10298084b372SDominik Brodowski socket = kzalloc(sizeof(struct yenta_socket), GFP_KERNEL); 10301da177e4SLinus Torvalds if (!socket) 10311da177e4SLinus Torvalds return -ENOMEM; 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds /* prepare pcmcia_socket */ 10341da177e4SLinus Torvalds socket->socket.ops = ¥ta_socket_operations; 10351da177e4SLinus Torvalds socket->socket.resource_ops = &pccard_nonstatic_ops; 10361da177e4SLinus Torvalds socket->socket.dev.dev = &dev->dev; 10371da177e4SLinus Torvalds socket->socket.driver_data = socket; 10381da177e4SLinus Torvalds socket->socket.owner = THIS_MODULE; 10395bc6b68aSRussell King socket->socket.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD; 10405bc6b68aSRussell King socket->socket.map_size = 0x1000; 10415bc6b68aSRussell King socket->socket.cb_dev = dev; 10421da177e4SLinus Torvalds 10431da177e4SLinus Torvalds /* prepare struct yenta_socket */ 10441da177e4SLinus Torvalds socket->dev = dev; 10451da177e4SLinus Torvalds pci_set_drvdata(dev, socket); 10461da177e4SLinus Torvalds 10471da177e4SLinus Torvalds /* 10481da177e4SLinus Torvalds * Do some basic sanity checking.. 10491da177e4SLinus Torvalds */ 10501da177e4SLinus Torvalds if (pci_enable_device(dev)) { 10511da177e4SLinus Torvalds ret = -EBUSY; 10521da177e4SLinus Torvalds goto free; 10531da177e4SLinus Torvalds } 10541da177e4SLinus Torvalds 10551da177e4SLinus Torvalds ret = pci_request_regions(dev, "yenta_socket"); 10561da177e4SLinus Torvalds if (ret) 10571da177e4SLinus Torvalds goto disable; 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds if (!pci_resource_start(dev, 0)) { 10601da177e4SLinus Torvalds printk(KERN_ERR "No cardbus resource!\n"); 10611da177e4SLinus Torvalds ret = -ENODEV; 10621da177e4SLinus Torvalds goto release; 10631da177e4SLinus Torvalds } 10641da177e4SLinus Torvalds 10651da177e4SLinus Torvalds /* 10661da177e4SLinus Torvalds * Ok, start setup.. Map the cardbus registers, 10671da177e4SLinus Torvalds * and request the IRQ. 10681da177e4SLinus Torvalds */ 10691da177e4SLinus Torvalds socket->base = ioremap(pci_resource_start(dev, 0), 0x1000); 10701da177e4SLinus Torvalds if (!socket->base) { 10711da177e4SLinus Torvalds ret = -ENOMEM; 10721da177e4SLinus Torvalds goto release; 10731da177e4SLinus Torvalds } 10741da177e4SLinus Torvalds 10751da177e4SLinus Torvalds /* 10761da177e4SLinus Torvalds * report the subsystem vendor and device for help debugging 10771da177e4SLinus Torvalds * the irq stuff... 10781da177e4SLinus Torvalds */ 10791da177e4SLinus Torvalds printk(KERN_INFO "Yenta: CardBus bridge found at %s [%04x:%04x]\n", 10801da177e4SLinus Torvalds pci_name(dev), dev->subsystem_vendor, dev->subsystem_device); 10811da177e4SLinus Torvalds 10821da177e4SLinus Torvalds yenta_config_init(socket); 10831da177e4SLinus Torvalds 10841da177e4SLinus Torvalds /* Disable all events */ 10851da177e4SLinus Torvalds cb_writel(socket, CB_SOCKET_MASK, 0x0); 10861da177e4SLinus Torvalds 10871da177e4SLinus Torvalds /* Set up the bridge regions.. */ 10881da177e4SLinus Torvalds yenta_allocate_resources(socket); 10891da177e4SLinus Torvalds 10901da177e4SLinus Torvalds socket->cb_irq = dev->irq; 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds /* Do we have special options for the device? */ 10931da177e4SLinus Torvalds if (id->driver_data != CARDBUS_TYPE_DEFAULT && 10941da177e4SLinus Torvalds id->driver_data < ARRAY_SIZE(cardbus_type)) { 10951da177e4SLinus Torvalds socket->type = &cardbus_type[id->driver_data]; 10961da177e4SLinus Torvalds 10971da177e4SLinus Torvalds ret = socket->type->override(socket); 10981da177e4SLinus Torvalds if (ret < 0) 10991da177e4SLinus Torvalds goto unmap; 11001da177e4SLinus Torvalds } 11011da177e4SLinus Torvalds 11021da177e4SLinus Torvalds /* We must finish initialization here */ 11031da177e4SLinus Torvalds 11041da177e4SLinus Torvalds if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, "yenta", socket)) { 11051da177e4SLinus Torvalds /* No IRQ or request_irq failed. Poll */ 11061da177e4SLinus Torvalds socket->cb_irq = 0; /* But zero is a valid IRQ number. */ 11071da177e4SLinus Torvalds init_timer(&socket->poll_timer); 11081da177e4SLinus Torvalds socket->poll_timer.function = yenta_interrupt_wrapper; 11091da177e4SLinus Torvalds socket->poll_timer.data = (unsigned long)socket; 11101da177e4SLinus Torvalds socket->poll_timer.expires = jiffies + HZ; 11111da177e4SLinus Torvalds add_timer(&socket->poll_timer); 11125bc6b68aSRussell King printk(KERN_INFO "Yenta: no PCI IRQ, CardBus support disabled for this socket.\n" 11135bc6b68aSRussell King KERN_INFO "Yenta: check your BIOS CardBus, BIOS IRQ or ACPI settings.\n"); 11145bc6b68aSRussell King } else { 11155bc6b68aSRussell King socket->socket.features |= SS_CAP_CARDBUS; 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds 11181da177e4SLinus Torvalds /* Figure out what the dang thing can do for the PCMCIA layer... */ 1119fa912bcbSDaniel Ritz yenta_interrogate(socket); 11201da177e4SLinus Torvalds yenta_get_socket_capabilities(socket, isa_interrupts); 11211da177e4SLinus Torvalds printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); 11221da177e4SLinus Torvalds 11231da177e4SLinus Torvalds /* Register it with the pcmcia layer.. */ 11241da177e4SLinus Torvalds ret = pcmcia_register_socket(&socket->socket); 1125030ee39cSLinus Torvalds if (ret == 0) { 1126030ee39cSLinus Torvalds /* Add the yenta register attributes */ 1127030ee39cSLinus Torvalds device_create_file(&dev->dev, &dev_attr_yenta_registers); 11281da177e4SLinus Torvalds goto out; 1129030ee39cSLinus Torvalds } 11301da177e4SLinus Torvalds 11311da177e4SLinus Torvalds unmap: 11321da177e4SLinus Torvalds iounmap(socket->base); 11331da177e4SLinus Torvalds release: 11341da177e4SLinus Torvalds pci_release_regions(dev); 11351da177e4SLinus Torvalds disable: 11361da177e4SLinus Torvalds pci_disable_device(dev); 11371da177e4SLinus Torvalds free: 11381da177e4SLinus Torvalds kfree(socket); 11391da177e4SLinus Torvalds out: 11401da177e4SLinus Torvalds return ret; 11411da177e4SLinus Torvalds } 11421da177e4SLinus Torvalds 11431da177e4SLinus Torvalds 11441da177e4SLinus Torvalds static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) 11451da177e4SLinus Torvalds { 11461da177e4SLinus Torvalds struct yenta_socket *socket = pci_get_drvdata(dev); 11471da177e4SLinus Torvalds int ret; 11481da177e4SLinus Torvalds 11491da177e4SLinus Torvalds ret = pcmcia_socket_dev_suspend(&dev->dev, state); 11501da177e4SLinus Torvalds 11511da177e4SLinus Torvalds if (socket) { 11521da177e4SLinus Torvalds if (socket->type && socket->type->save_state) 11531da177e4SLinus Torvalds socket->type->save_state(socket); 11541da177e4SLinus Torvalds 11551da177e4SLinus Torvalds /* FIXME: pci_save_state needs to have a better interface */ 11561da177e4SLinus Torvalds pci_save_state(dev); 11571da177e4SLinus Torvalds pci_read_config_dword(dev, 16*4, &socket->saved_state[0]); 11581da177e4SLinus Torvalds pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); 1159d58da590SDavid Shaohua Li pci_disable_device(dev); 11601da177e4SLinus Torvalds 11611da177e4SLinus Torvalds /* 11621da177e4SLinus Torvalds * Some laptops (IBM T22) do not like us putting the Cardbus 11631da177e4SLinus Torvalds * bridge into D3. At a guess, some other laptop will 11641da177e4SLinus Torvalds * probably require this, so leave it commented out for now. 11651da177e4SLinus Torvalds */ 11661da177e4SLinus Torvalds /* pci_set_power_state(dev, 3); */ 11671da177e4SLinus Torvalds } 11681da177e4SLinus Torvalds 11691da177e4SLinus Torvalds return ret; 11701da177e4SLinus Torvalds } 11711da177e4SLinus Torvalds 11721da177e4SLinus Torvalds 11731da177e4SLinus Torvalds static int yenta_dev_resume (struct pci_dev *dev) 11741da177e4SLinus Torvalds { 11751da177e4SLinus Torvalds struct yenta_socket *socket = pci_get_drvdata(dev); 11761da177e4SLinus Torvalds 11771da177e4SLinus Torvalds if (socket) { 11781da177e4SLinus Torvalds pci_set_power_state(dev, 0); 11791da177e4SLinus Torvalds /* FIXME: pci_restore_state needs to have a better interface */ 11801da177e4SLinus Torvalds pci_restore_state(dev); 11811da177e4SLinus Torvalds pci_write_config_dword(dev, 16*4, socket->saved_state[0]); 11821da177e4SLinus Torvalds pci_write_config_dword(dev, 17*4, socket->saved_state[1]); 1183d58da590SDavid Shaohua Li pci_enable_device(dev); 1184d58da590SDavid Shaohua Li pci_set_master(dev); 11851da177e4SLinus Torvalds 11861da177e4SLinus Torvalds if (socket->type && socket->type->restore_state) 11871da177e4SLinus Torvalds socket->type->restore_state(socket); 11881da177e4SLinus Torvalds } 11891da177e4SLinus Torvalds 11901da177e4SLinus Torvalds return pcmcia_socket_dev_resume(&dev->dev); 11911da177e4SLinus Torvalds } 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds 11941da177e4SLinus Torvalds #define CB_ID(vend,dev,type) \ 11951da177e4SLinus Torvalds { \ 11961da177e4SLinus Torvalds .vendor = vend, \ 11971da177e4SLinus Torvalds .device = dev, \ 11981da177e4SLinus Torvalds .subvendor = PCI_ANY_ID, \ 11991da177e4SLinus Torvalds .subdevice = PCI_ANY_ID, \ 12001da177e4SLinus Torvalds .class = PCI_CLASS_BRIDGE_CARDBUS << 8, \ 12011da177e4SLinus Torvalds .class_mask = ~0, \ 12021da177e4SLinus Torvalds .driver_data = CARDBUS_TYPE_##type, \ 12031da177e4SLinus Torvalds } 12041da177e4SLinus Torvalds 12051da177e4SLinus Torvalds static struct pci_device_id yenta_table [] = { 12061da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI), 12071da177e4SLinus Torvalds 12081da177e4SLinus Torvalds /* 12091da177e4SLinus Torvalds * TBD: Check if these TI variants can use more 12101da177e4SLinus Torvalds * advanced overrides instead. (I can't get the 12111da177e4SLinus Torvalds * data sheets for these devices. --rmk) 12121da177e4SLinus Torvalds */ 121363e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TI 12141da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210, TI), 12151da177e4SLinus Torvalds 12161da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130, TI113X), 12171da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1131, TI113X), 12181da177e4SLinus Torvalds 12191da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211, TI12XX), 12201da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1220, TI12XX), 12211da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1221, TI12XX), 12221da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1225, TI12XX), 12231da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251A, TI12XX), 12241da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251B, TI12XX), 12251da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, TI12XX), 12261da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1450, TI12XX), 12271da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1451A, TI12XX), 12281da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510, TI12XX), 12291da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520, TI12XX), 12301da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1620, TI12XX), 12311da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX), 12321da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX), 12331da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX), 12341da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4510, TI12XX), 12351da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4520, TI12XX), 12361da177e4SLinus Torvalds 12371da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), 12381da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), 12391da177e4SLinus Torvalds 12406c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX), 12416c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX), 12426c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX), 12436c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX), 12446c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX), 12456c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX), 12466c1a10dbSDaniel Ritz CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX), 12476c1a10dbSDaniel Ritz 1248f9cb8b71SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX), 1249f9cb8b71SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX), 1250f9cb8b71SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX), 1251f9cb8b71SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX), 12528c3520d4SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), 12538c3520d4SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), 12548c3520d4SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), 12558c3520d4SDaniel Ritz CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE), 125663e7ebd0SDaniel Ritz #endif /* CONFIG_YENTA_TI */ 12571da177e4SLinus Torvalds 125863e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_RICOH 12591da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), 12601da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), 12611da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475, RICOH), 12621da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), 12631da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), 126463e7ebd0SDaniel Ritz #endif 12651da177e4SLinus Torvalds 126663e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_TOSHIBA 1267ea2f1590SDaniel Ritz CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95), 12681da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), 12691da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), 127063e7ebd0SDaniel Ritz #endif 12711da177e4SLinus Torvalds 127263e7ebd0SDaniel Ritz #ifdef CONFIG_YENTA_O2 12731da177e4SLinus Torvalds CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO), 127463e7ebd0SDaniel Ritz #endif 12751da177e4SLinus Torvalds 12761da177e4SLinus Torvalds /* match any cardbus bridge */ 12771da177e4SLinus Torvalds CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT), 12781da177e4SLinus Torvalds { /* all zeroes */ } 12791da177e4SLinus Torvalds }; 12801da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, yenta_table); 12811da177e4SLinus Torvalds 12821da177e4SLinus Torvalds 12831da177e4SLinus Torvalds static struct pci_driver yenta_cardbus_driver = { 12841da177e4SLinus Torvalds .name = "yenta_cardbus", 12851da177e4SLinus Torvalds .id_table = yenta_table, 12861da177e4SLinus Torvalds .probe = yenta_probe, 12871da177e4SLinus Torvalds .remove = __devexit_p(yenta_close), 12881da177e4SLinus Torvalds .suspend = yenta_dev_suspend, 12891da177e4SLinus Torvalds .resume = yenta_dev_resume, 12901da177e4SLinus Torvalds }; 12911da177e4SLinus Torvalds 12921da177e4SLinus Torvalds 12931da177e4SLinus Torvalds static int __init yenta_socket_init(void) 12941da177e4SLinus Torvalds { 12951da177e4SLinus Torvalds return pci_register_driver (¥ta_cardbus_driver); 12961da177e4SLinus Torvalds } 12971da177e4SLinus Torvalds 12981da177e4SLinus Torvalds 12991da177e4SLinus Torvalds static void __exit yenta_socket_exit (void) 13001da177e4SLinus Torvalds { 13011da177e4SLinus Torvalds pci_unregister_driver (¥ta_cardbus_driver); 13021da177e4SLinus Torvalds } 13031da177e4SLinus Torvalds 13041da177e4SLinus Torvalds 13051da177e4SLinus Torvalds module_init(yenta_socket_init); 13061da177e4SLinus Torvalds module_exit(yenta_socket_exit); 13071da177e4SLinus Torvalds 13081da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 1309