162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Regular cardbus driver ("yenta_socket") 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * (C) Copyright 1999, 2000 Linus Torvalds 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Changelog: 862306a36Sopenharmony_ci * Aug 2002: Manfred Spraul <manfred@colorfullife.com> 962306a36Sopenharmony_ci * Dynamically adjust the size of the bridge resource 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * May 2003: Dominik Brodowski <linux@brodo.de> 1262306a36Sopenharmony_ci * Merge pci_socket.c and yenta.c into one file 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci#include <linux/init.h> 1562306a36Sopenharmony_ci#include <linux/pci.h> 1662306a36Sopenharmony_ci#include <linux/workqueue.h> 1762306a36Sopenharmony_ci#include <linux/interrupt.h> 1862306a36Sopenharmony_ci#include <linux/delay.h> 1962306a36Sopenharmony_ci#include <linux/module.h> 2062306a36Sopenharmony_ci#include <linux/io.h> 2162306a36Sopenharmony_ci#include <linux/slab.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <pcmcia/ss.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "yenta_socket.h" 2662306a36Sopenharmony_ci#include "i82365.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic bool disable_clkrun; 2962306a36Sopenharmony_cimodule_param(disable_clkrun, bool, 0444); 3062306a36Sopenharmony_ciMODULE_PARM_DESC(disable_clkrun, 3162306a36Sopenharmony_ci "If PC card doesn't function properly, please try this option (TI and Ricoh bridges only)"); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic bool isa_probe = 1; 3462306a36Sopenharmony_cimodule_param(isa_probe, bool, 0444); 3562306a36Sopenharmony_ciMODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing"); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic bool pwr_irqs_off; 3862306a36Sopenharmony_cimodule_param(pwr_irqs_off, bool, 0644); 3962306a36Sopenharmony_ciMODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!"); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic char o2_speedup[] = "default"; 4262306a36Sopenharmony_cimodule_param_string(o2_speedup, o2_speedup, sizeof(o2_speedup), 0444); 4362306a36Sopenharmony_ciMODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' " 4462306a36Sopenharmony_ci "or 'default' (uses recommended behaviour for the detected bridge)"); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* 4762306a36Sopenharmony_ci * Only probe "regular" interrupts, don't 4862306a36Sopenharmony_ci * touch dangerous spots like the mouse irq, 4962306a36Sopenharmony_ci * because there are mice that apparently 5062306a36Sopenharmony_ci * get really confused if they get fondled 5162306a36Sopenharmony_ci * too intimately. 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * Default to 11, 10, 9, 7, 6, 5, 4, 3. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_cistatic u32 isa_interrupts = 0x0ef8; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define debug(x, s, args...) dev_dbg(&s->dev->dev, x, ##args) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* Don't ask.. */ 6162306a36Sopenharmony_ci#define to_cycles(ns) ((ns)/120) 6262306a36Sopenharmony_ci#define to_ns(cycles) ((cycles)*120) 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* 6562306a36Sopenharmony_ci * yenta PCI irq probing. 6662306a36Sopenharmony_ci * currently only used in the TI/EnE initialization code 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_ci#ifdef CONFIG_YENTA_TI 6962306a36Sopenharmony_cistatic int yenta_probe_cb_irq(struct yenta_socket *socket); 7062306a36Sopenharmony_cistatic unsigned int yenta_probe_irq(struct yenta_socket *socket, 7162306a36Sopenharmony_ci u32 isa_irq_mask); 7262306a36Sopenharmony_ci#endif 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic unsigned int override_bios; 7662306a36Sopenharmony_cimodule_param(override_bios, uint, 0000); 7762306a36Sopenharmony_ciMODULE_PARM_DESC(override_bios, "yenta ignore bios resource allocation"); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* 8062306a36Sopenharmony_ci * Generate easy-to-use ways of reading a cardbus sockets 8162306a36Sopenharmony_ci * regular memory space ("cb_xxx"), configuration space 8262306a36Sopenharmony_ci * ("config_xxx") and compatibility space ("exca_xxxx") 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_cistatic inline u32 cb_readl(struct yenta_socket *socket, unsigned reg) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci u32 val = readl(socket->base + reg); 8762306a36Sopenharmony_ci debug("%04x %08x\n", socket, reg, val); 8862306a36Sopenharmony_ci return val; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci debug("%04x %08x\n", socket, reg, val); 9462306a36Sopenharmony_ci writel(val, socket->base + reg); 9562306a36Sopenharmony_ci readl(socket->base + reg); /* avoid problems with PCI write posting */ 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic inline u8 config_readb(struct yenta_socket *socket, unsigned offset) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci u8 val; 10162306a36Sopenharmony_ci pci_read_config_byte(socket->dev, offset, &val); 10262306a36Sopenharmony_ci debug("%04x %02x\n", socket, offset, val); 10362306a36Sopenharmony_ci return val; 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic inline u16 config_readw(struct yenta_socket *socket, unsigned offset) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci u16 val; 10962306a36Sopenharmony_ci pci_read_config_word(socket->dev, offset, &val); 11062306a36Sopenharmony_ci debug("%04x %04x\n", socket, offset, val); 11162306a36Sopenharmony_ci return val; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic inline u32 config_readl(struct yenta_socket *socket, unsigned offset) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci u32 val; 11762306a36Sopenharmony_ci pci_read_config_dword(socket->dev, offset, &val); 11862306a36Sopenharmony_ci debug("%04x %08x\n", socket, offset, val); 11962306a36Sopenharmony_ci return val; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci debug("%04x %02x\n", socket, offset, val); 12562306a36Sopenharmony_ci pci_write_config_byte(socket->dev, offset, val); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci debug("%04x %04x\n", socket, offset, val); 13162306a36Sopenharmony_ci pci_write_config_word(socket->dev, offset, val); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci debug("%04x %08x\n", socket, offset, val); 13762306a36Sopenharmony_ci pci_write_config_dword(socket->dev, offset, val); 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic inline u8 exca_readb(struct yenta_socket *socket, unsigned reg) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci u8 val = readb(socket->base + 0x800 + reg); 14362306a36Sopenharmony_ci debug("%04x %02x\n", socket, reg, val); 14462306a36Sopenharmony_ci return val; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci/* 14862306a36Sopenharmony_cistatic inline u8 exca_readw(struct yenta_socket *socket, unsigned reg) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci u16 val; 15162306a36Sopenharmony_ci val = readb(socket->base + 0x800 + reg); 15262306a36Sopenharmony_ci val |= readb(socket->base + 0x800 + reg + 1) << 8; 15362306a36Sopenharmony_ci debug("%04x %04x\n", socket, reg, val); 15462306a36Sopenharmony_ci return val; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci*/ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci debug("%04x %02x\n", socket, reg, val); 16162306a36Sopenharmony_ci writeb(val, socket->base + 0x800 + reg); 16262306a36Sopenharmony_ci readb(socket->base + 0x800 + reg); /* PCI write posting... */ 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci debug("%04x %04x\n", socket, reg, val); 16862306a36Sopenharmony_ci writeb(val, socket->base + 0x800 + reg); 16962306a36Sopenharmony_ci writeb(val >> 8, socket->base + 0x800 + reg + 1); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci /* PCI write posting... */ 17262306a36Sopenharmony_ci readb(socket->base + 0x800 + reg); 17362306a36Sopenharmony_ci readb(socket->base + 0x800 + reg + 1); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic ssize_t show_yenta_registers(struct device *yentadev, struct device_attribute *attr, char *buf) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci struct yenta_socket *socket = dev_get_drvdata(yentadev); 17962306a36Sopenharmony_ci int offset = 0, i; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci offset = sysfs_emit(buf, "CB registers:"); 18262306a36Sopenharmony_ci for (i = 0; i < 0x24; i += 4) { 18362306a36Sopenharmony_ci unsigned val; 18462306a36Sopenharmony_ci if (!(i & 15)) 18562306a36Sopenharmony_ci offset += sysfs_emit_at(buf, offset, "\n%02x:", i); 18662306a36Sopenharmony_ci val = cb_readl(socket, i); 18762306a36Sopenharmony_ci offset += sysfs_emit_at(buf, offset, " %08x", val); 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci offset += sysfs_emit_at(buf, offset, "\n\nExCA registers:"); 19162306a36Sopenharmony_ci for (i = 0; i < 0x45; i++) { 19262306a36Sopenharmony_ci unsigned char val; 19362306a36Sopenharmony_ci if (!(i & 7)) { 19462306a36Sopenharmony_ci if (i & 8) { 19562306a36Sopenharmony_ci memcpy(buf + offset, " -", 2); 19662306a36Sopenharmony_ci offset += 2; 19762306a36Sopenharmony_ci } else 19862306a36Sopenharmony_ci offset += sysfs_emit_at(buf, offset, "\n%02x:", i); 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci val = exca_readb(socket, i); 20162306a36Sopenharmony_ci offset += sysfs_emit_at(buf, offset, " %02x", val); 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci sysfs_emit_at(buf, offset, "\n"); 20462306a36Sopenharmony_ci return offset; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cistatic DEVICE_ATTR(yenta_registers, S_IRUSR, show_yenta_registers, NULL); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/* 21062306a36Sopenharmony_ci * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend 21162306a36Sopenharmony_ci * on what kind of card is inserted.. 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_cistatic int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 21662306a36Sopenharmony_ci unsigned int val; 21762306a36Sopenharmony_ci u32 state = cb_readl(socket, CB_SOCKET_STATE); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci val = (state & CB_3VCARD) ? SS_3VCARD : 0; 22062306a36Sopenharmony_ci val |= (state & CB_XVCARD) ? SS_XVCARD : 0; 22162306a36Sopenharmony_ci val |= (state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING; 22262306a36Sopenharmony_ci val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? SS_PENDING : 0; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci if (state & CB_CBCARD) { 22662306a36Sopenharmony_ci val |= SS_CARDBUS; 22762306a36Sopenharmony_ci val |= (state & CB_CARDSTS) ? SS_STSCHG : 0; 22862306a36Sopenharmony_ci val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; 22962306a36Sopenharmony_ci val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; 23062306a36Sopenharmony_ci } else if (state & CB_16BITCARD) { 23162306a36Sopenharmony_ci u8 status = exca_readb(socket, I365_STATUS); 23262306a36Sopenharmony_ci val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0; 23362306a36Sopenharmony_ci if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { 23462306a36Sopenharmony_ci val |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; 23562306a36Sopenharmony_ci } else { 23662306a36Sopenharmony_ci val |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; 23762306a36Sopenharmony_ci val |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; 24062306a36Sopenharmony_ci val |= (status & I365_CS_READY) ? SS_READY : 0; 24162306a36Sopenharmony_ci val |= (status & I365_CS_POWERON) ? SS_POWERON : 0; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci *value = val; 24562306a36Sopenharmony_ci return 0; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci /* some birdges require to use the ExCA registers to power 16bit cards */ 25162306a36Sopenharmony_ci if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) && 25262306a36Sopenharmony_ci (socket->flags & YENTA_16BIT_POWER_EXCA)) { 25362306a36Sopenharmony_ci u8 reg, old; 25462306a36Sopenharmony_ci reg = old = exca_readb(socket, I365_POWER); 25562306a36Sopenharmony_ci reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* i82365SL-DF style */ 25862306a36Sopenharmony_ci if (socket->flags & YENTA_16BIT_POWER_DF) { 25962306a36Sopenharmony_ci switch (state->Vcc) { 26062306a36Sopenharmony_ci case 33: 26162306a36Sopenharmony_ci reg |= I365_VCC_3V; 26262306a36Sopenharmony_ci break; 26362306a36Sopenharmony_ci case 50: 26462306a36Sopenharmony_ci reg |= I365_VCC_5V; 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci default: 26762306a36Sopenharmony_ci reg = 0; 26862306a36Sopenharmony_ci break; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci switch (state->Vpp) { 27162306a36Sopenharmony_ci case 33: 27262306a36Sopenharmony_ci case 50: 27362306a36Sopenharmony_ci reg |= I365_VPP1_5V; 27462306a36Sopenharmony_ci break; 27562306a36Sopenharmony_ci case 120: 27662306a36Sopenharmony_ci reg |= I365_VPP1_12V; 27762306a36Sopenharmony_ci break; 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci } else { 28062306a36Sopenharmony_ci /* i82365SL-B style */ 28162306a36Sopenharmony_ci switch (state->Vcc) { 28262306a36Sopenharmony_ci case 50: 28362306a36Sopenharmony_ci reg |= I365_VCC_5V; 28462306a36Sopenharmony_ci break; 28562306a36Sopenharmony_ci default: 28662306a36Sopenharmony_ci reg = 0; 28762306a36Sopenharmony_ci break; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci switch (state->Vpp) { 29062306a36Sopenharmony_ci case 50: 29162306a36Sopenharmony_ci reg |= I365_VPP1_5V | I365_VPP2_5V; 29262306a36Sopenharmony_ci break; 29362306a36Sopenharmony_ci case 120: 29462306a36Sopenharmony_ci reg |= I365_VPP1_12V | I365_VPP2_12V; 29562306a36Sopenharmony_ci break; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci if (reg != old) 30062306a36Sopenharmony_ci exca_writeb(socket, I365_POWER, reg); 30162306a36Sopenharmony_ci } else { 30262306a36Sopenharmony_ci u32 reg = 0; /* CB_SC_STPCLK? */ 30362306a36Sopenharmony_ci switch (state->Vcc) { 30462306a36Sopenharmony_ci case 33: 30562306a36Sopenharmony_ci reg = CB_SC_VCC_3V; 30662306a36Sopenharmony_ci break; 30762306a36Sopenharmony_ci case 50: 30862306a36Sopenharmony_ci reg = CB_SC_VCC_5V; 30962306a36Sopenharmony_ci break; 31062306a36Sopenharmony_ci default: 31162306a36Sopenharmony_ci reg = 0; 31262306a36Sopenharmony_ci break; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci switch (state->Vpp) { 31562306a36Sopenharmony_ci case 33: 31662306a36Sopenharmony_ci reg |= CB_SC_VPP_3V; 31762306a36Sopenharmony_ci break; 31862306a36Sopenharmony_ci case 50: 31962306a36Sopenharmony_ci reg |= CB_SC_VPP_5V; 32062306a36Sopenharmony_ci break; 32162306a36Sopenharmony_ci case 120: 32262306a36Sopenharmony_ci reg |= CB_SC_VPP_12V; 32362306a36Sopenharmony_ci break; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) 32662306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_CONTROL, reg); 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 33362306a36Sopenharmony_ci u16 bridge; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* if powering down: do it immediately */ 33662306a36Sopenharmony_ci if (state->Vcc == 0) 33762306a36Sopenharmony_ci yenta_set_power(socket, state); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci socket->io_irq = state->io_irq; 34062306a36Sopenharmony_ci bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); 34162306a36Sopenharmony_ci if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { 34262306a36Sopenharmony_ci u8 intr; 34362306a36Sopenharmony_ci bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* ISA interrupt control? */ 34662306a36Sopenharmony_ci intr = exca_readb(socket, I365_INTCTL); 34762306a36Sopenharmony_ci intr = (intr & ~0xf); 34862306a36Sopenharmony_ci if (!socket->dev->irq) { 34962306a36Sopenharmony_ci intr |= socket->cb_irq ? socket->cb_irq : state->io_irq; 35062306a36Sopenharmony_ci bridge |= CB_BRIDGE_INTR; 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci exca_writeb(socket, I365_INTCTL, intr); 35362306a36Sopenharmony_ci } else { 35462306a36Sopenharmony_ci u8 reg; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA); 35762306a36Sopenharmony_ci reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; 35862306a36Sopenharmony_ci reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; 35962306a36Sopenharmony_ci if (state->io_irq != socket->dev->irq) { 36062306a36Sopenharmony_ci reg |= state->io_irq; 36162306a36Sopenharmony_ci bridge |= CB_BRIDGE_INTR; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci exca_writeb(socket, I365_INTCTL, reg); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK); 36662306a36Sopenharmony_ci reg |= I365_PWR_NORESET; 36762306a36Sopenharmony_ci if (state->flags & SS_PWR_AUTO) 36862306a36Sopenharmony_ci reg |= I365_PWR_AUTO; 36962306a36Sopenharmony_ci if (state->flags & SS_OUTPUT_ENA) 37062306a36Sopenharmony_ci reg |= I365_PWR_OUT; 37162306a36Sopenharmony_ci if (exca_readb(socket, I365_POWER) != reg) 37262306a36Sopenharmony_ci exca_writeb(socket, I365_POWER, reg); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* CSC interrupt: no ISA irq for CSC */ 37562306a36Sopenharmony_ci reg = exca_readb(socket, I365_CSCINT); 37662306a36Sopenharmony_ci reg &= I365_CSC_IRQ_MASK; 37762306a36Sopenharmony_ci reg |= I365_CSC_DETECT; 37862306a36Sopenharmony_ci if (state->flags & SS_IOCARD) { 37962306a36Sopenharmony_ci if (state->csc_mask & SS_STSCHG) 38062306a36Sopenharmony_ci reg |= I365_CSC_STSCHG; 38162306a36Sopenharmony_ci } else { 38262306a36Sopenharmony_ci if (state->csc_mask & SS_BATDEAD) 38362306a36Sopenharmony_ci reg |= I365_CSC_BVD1; 38462306a36Sopenharmony_ci if (state->csc_mask & SS_BATWARN) 38562306a36Sopenharmony_ci reg |= I365_CSC_BVD2; 38662306a36Sopenharmony_ci if (state->csc_mask & SS_READY) 38762306a36Sopenharmony_ci reg |= I365_CSC_READY; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci exca_writeb(socket, I365_CSCINT, reg); 39062306a36Sopenharmony_ci exca_readb(socket, I365_CSC); 39162306a36Sopenharmony_ci if (sock->zoom_video) 39262306a36Sopenharmony_ci sock->zoom_video(sock, state->flags & SS_ZVCARD); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci config_writew(socket, CB_BRIDGE_CONTROL, bridge); 39562306a36Sopenharmony_ci /* Socket event mask: get card insert/remove events.. */ 39662306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_EVENT, -1); 39762306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* if powering up: do it as the last step when the socket is configured */ 40062306a36Sopenharmony_ci if (state->Vcc != 0) 40162306a36Sopenharmony_ci yenta_set_power(socket, state); 40262306a36Sopenharmony_ci return 0; 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 40862306a36Sopenharmony_ci int map; 40962306a36Sopenharmony_ci unsigned char ioctl, addr, enable; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci map = io->map; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (map > 1) 41462306a36Sopenharmony_ci return -EINVAL; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci enable = I365_ENA_IO(map); 41762306a36Sopenharmony_ci addr = exca_readb(socket, I365_ADDRWIN); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci /* Disable the window before changing it.. */ 42062306a36Sopenharmony_ci if (addr & enable) { 42162306a36Sopenharmony_ci addr &= ~enable; 42262306a36Sopenharmony_ci exca_writeb(socket, I365_ADDRWIN, addr); 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci exca_writew(socket, I365_IO(map)+I365_W_START, io->start); 42662306a36Sopenharmony_ci exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); 42962306a36Sopenharmony_ci if (io->flags & MAP_0WS) 43062306a36Sopenharmony_ci ioctl |= I365_IOCTL_0WS(map); 43162306a36Sopenharmony_ci if (io->flags & MAP_16BIT) 43262306a36Sopenharmony_ci ioctl |= I365_IOCTL_16BIT(map); 43362306a36Sopenharmony_ci if (io->flags & MAP_AUTOSZ) 43462306a36Sopenharmony_ci ioctl |= I365_IOCTL_IOCS16(map); 43562306a36Sopenharmony_ci exca_writeb(socket, I365_IOCTL, ioctl); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (io->flags & MAP_ACTIVE) 43862306a36Sopenharmony_ci exca_writeb(socket, I365_ADDRWIN, addr | enable); 43962306a36Sopenharmony_ci return 0; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 44562306a36Sopenharmony_ci struct pci_bus_region region; 44662306a36Sopenharmony_ci int map; 44762306a36Sopenharmony_ci unsigned char addr, enable; 44862306a36Sopenharmony_ci unsigned int start, stop, card_start; 44962306a36Sopenharmony_ci unsigned short word; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci pcibios_resource_to_bus(socket->dev->bus, ®ion, mem->res); 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci map = mem->map; 45462306a36Sopenharmony_ci start = region.start; 45562306a36Sopenharmony_ci stop = region.end; 45662306a36Sopenharmony_ci card_start = mem->card_start; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci if (map > 4 || start > stop || ((start ^ stop) >> 24) || 45962306a36Sopenharmony_ci (card_start >> 26) || mem->speed > 1000) 46062306a36Sopenharmony_ci return -EINVAL; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci enable = I365_ENA_MEM(map); 46362306a36Sopenharmony_ci addr = exca_readb(socket, I365_ADDRWIN); 46462306a36Sopenharmony_ci if (addr & enable) { 46562306a36Sopenharmony_ci addr &= ~enable; 46662306a36Sopenharmony_ci exca_writeb(socket, I365_ADDRWIN, addr); 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci exca_writeb(socket, CB_MEM_PAGE(map), start >> 24); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci word = (start >> 12) & 0x0fff; 47262306a36Sopenharmony_ci if (mem->flags & MAP_16BIT) 47362306a36Sopenharmony_ci word |= I365_MEM_16BIT; 47462306a36Sopenharmony_ci if (mem->flags & MAP_0WS) 47562306a36Sopenharmony_ci word |= I365_MEM_0WS; 47662306a36Sopenharmony_ci exca_writew(socket, I365_MEM(map) + I365_W_START, word); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci word = (stop >> 12) & 0x0fff; 47962306a36Sopenharmony_ci switch (to_cycles(mem->speed)) { 48062306a36Sopenharmony_ci case 0: 48162306a36Sopenharmony_ci break; 48262306a36Sopenharmony_ci case 1: 48362306a36Sopenharmony_ci word |= I365_MEM_WS0; 48462306a36Sopenharmony_ci break; 48562306a36Sopenharmony_ci case 2: 48662306a36Sopenharmony_ci word |= I365_MEM_WS1; 48762306a36Sopenharmony_ci break; 48862306a36Sopenharmony_ci default: 48962306a36Sopenharmony_ci word |= I365_MEM_WS1 | I365_MEM_WS0; 49062306a36Sopenharmony_ci break; 49162306a36Sopenharmony_ci } 49262306a36Sopenharmony_ci exca_writew(socket, I365_MEM(map) + I365_W_STOP, word); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci word = ((card_start - start) >> 12) & 0x3fff; 49562306a36Sopenharmony_ci if (mem->flags & MAP_WRPROT) 49662306a36Sopenharmony_ci word |= I365_MEM_WRPROT; 49762306a36Sopenharmony_ci if (mem->flags & MAP_ATTRIB) 49862306a36Sopenharmony_ci word |= I365_MEM_REG; 49962306a36Sopenharmony_ci exca_writew(socket, I365_MEM(map) + I365_W_OFF, word); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (mem->flags & MAP_ACTIVE) 50262306a36Sopenharmony_ci exca_writeb(socket, I365_ADDRWIN, addr | enable); 50362306a36Sopenharmony_ci return 0; 50462306a36Sopenharmony_ci} 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_cistatic irqreturn_t yenta_interrupt(int irq, void *dev_id) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci unsigned int events; 51162306a36Sopenharmony_ci struct yenta_socket *socket = (struct yenta_socket *) dev_id; 51262306a36Sopenharmony_ci u8 csc; 51362306a36Sopenharmony_ci u32 cb_event; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci /* Clear interrupt status for the event */ 51662306a36Sopenharmony_ci cb_event = cb_readl(socket, CB_SOCKET_EVENT); 51762306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_EVENT, cb_event); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci csc = exca_readb(socket, I365_CSC); 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (!(cb_event || csc)) 52262306a36Sopenharmony_ci return IRQ_NONE; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ; 52562306a36Sopenharmony_ci events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0; 52662306a36Sopenharmony_ci if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { 52762306a36Sopenharmony_ci events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; 52862306a36Sopenharmony_ci } else { 52962306a36Sopenharmony_ci events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; 53062306a36Sopenharmony_ci events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; 53162306a36Sopenharmony_ci events |= (csc & I365_CSC_READY) ? SS_READY : 0; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (events) 53562306a36Sopenharmony_ci pcmcia_parse_events(&socket->socket, events); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci return IRQ_HANDLED; 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_cistatic void yenta_interrupt_wrapper(struct timer_list *t) 54162306a36Sopenharmony_ci{ 54262306a36Sopenharmony_ci struct yenta_socket *socket = from_timer(socket, t, poll_timer); 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci yenta_interrupt(0, (void *)socket); 54562306a36Sopenharmony_ci socket->poll_timer.expires = jiffies + HZ; 54662306a36Sopenharmony_ci add_timer(&socket->poll_timer); 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cistatic void yenta_clear_maps(struct yenta_socket *socket) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci int i; 55262306a36Sopenharmony_ci struct resource res = { .start = 0, .end = 0x0fff }; 55362306a36Sopenharmony_ci pccard_io_map io = { 0, 0, 0, 0, 1 }; 55462306a36Sopenharmony_ci pccard_mem_map mem = { .res = &res, }; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci yenta_set_socket(&socket->socket, &dead_socket); 55762306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 55862306a36Sopenharmony_ci io.map = i; 55962306a36Sopenharmony_ci yenta_set_io_map(&socket->socket, &io); 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci for (i = 0; i < 5; i++) { 56262306a36Sopenharmony_ci mem.map = i; 56362306a36Sopenharmony_ci yenta_set_mem_map(&socket->socket, &mem); 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci} 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci/* redoes voltage interrogation if required */ 56862306a36Sopenharmony_cistatic void yenta_interrogate(struct yenta_socket *socket) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci u32 state; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci state = cb_readl(socket, CB_SOCKET_STATE); 57362306a36Sopenharmony_ci if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) || 57462306a36Sopenharmony_ci (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) || 57562306a36Sopenharmony_ci ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD))) 57662306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); 57762306a36Sopenharmony_ci} 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci/* Called at resume and initialization events */ 58062306a36Sopenharmony_cistatic int yenta_sock_init(struct pcmcia_socket *sock) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci exca_writeb(socket, I365_GBLCTL, 0x00); 58562306a36Sopenharmony_ci exca_writeb(socket, I365_GENCTL, 0x00); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci /* Redo card voltage interrogation */ 58862306a36Sopenharmony_ci yenta_interrogate(socket); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci yenta_clear_maps(socket); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci if (socket->type && socket->type->sock_init) 59362306a36Sopenharmony_ci socket->type->sock_init(socket); 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci /* Re-enable CSC interrupts */ 59662306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci return 0; 59962306a36Sopenharmony_ci} 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_cistatic int yenta_sock_suspend(struct pcmcia_socket *sock) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci /* Disable CSC interrupts */ 60662306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_MASK, 0x0); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci return 0; 60962306a36Sopenharmony_ci} 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci/* 61262306a36Sopenharmony_ci * Use an adaptive allocation for the memory resource, 61362306a36Sopenharmony_ci * sometimes the memory behind pci bridges is limited: 61462306a36Sopenharmony_ci * 1/8 of the size of the io window of the parent. 61562306a36Sopenharmony_ci * max 4 MB, min 16 kB. We try very hard to not get below 61662306a36Sopenharmony_ci * the "ACC" values, though. 61762306a36Sopenharmony_ci */ 61862306a36Sopenharmony_ci#define BRIDGE_MEM_MAX (4*1024*1024) 61962306a36Sopenharmony_ci#define BRIDGE_MEM_ACC (128*1024) 62062306a36Sopenharmony_ci#define BRIDGE_MEM_MIN (16*1024) 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci#define BRIDGE_IO_MAX 512 62362306a36Sopenharmony_ci#define BRIDGE_IO_ACC 256 62462306a36Sopenharmony_ci#define BRIDGE_IO_MIN 32 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci#ifndef PCIBIOS_MIN_CARDBUS_IO 62762306a36Sopenharmony_ci#define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO 62862306a36Sopenharmony_ci#endif 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic int yenta_search_one_res(struct resource *root, struct resource *res, 63162306a36Sopenharmony_ci u32 min) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci u32 align, size, start, end; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci if (res->flags & IORESOURCE_IO) { 63662306a36Sopenharmony_ci align = 1024; 63762306a36Sopenharmony_ci size = BRIDGE_IO_MAX; 63862306a36Sopenharmony_ci start = PCIBIOS_MIN_CARDBUS_IO; 63962306a36Sopenharmony_ci end = ~0U; 64062306a36Sopenharmony_ci } else { 64162306a36Sopenharmony_ci unsigned long avail = root->end - root->start; 64262306a36Sopenharmony_ci int i; 64362306a36Sopenharmony_ci size = BRIDGE_MEM_MAX; 64462306a36Sopenharmony_ci if (size > avail/8) { 64562306a36Sopenharmony_ci size = (avail+1)/8; 64662306a36Sopenharmony_ci /* round size down to next power of 2 */ 64762306a36Sopenharmony_ci i = 0; 64862306a36Sopenharmony_ci while ((size /= 2) != 0) 64962306a36Sopenharmony_ci i++; 65062306a36Sopenharmony_ci size = 1 << i; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci if (size < min) 65362306a36Sopenharmony_ci size = min; 65462306a36Sopenharmony_ci align = size; 65562306a36Sopenharmony_ci start = PCIBIOS_MIN_MEM; 65662306a36Sopenharmony_ci end = ~0U; 65762306a36Sopenharmony_ci } 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci do { 66062306a36Sopenharmony_ci if (allocate_resource(root, res, size, start, end, align, 66162306a36Sopenharmony_ci NULL, NULL) == 0) { 66262306a36Sopenharmony_ci return 1; 66362306a36Sopenharmony_ci } 66462306a36Sopenharmony_ci size = size/2; 66562306a36Sopenharmony_ci align = size; 66662306a36Sopenharmony_ci } while (size >= min); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci return 0; 66962306a36Sopenharmony_ci} 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_cistatic int yenta_search_res(struct yenta_socket *socket, struct resource *res, 67362306a36Sopenharmony_ci u32 min) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci struct resource *root; 67662306a36Sopenharmony_ci int i; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci pci_bus_for_each_resource(socket->dev->bus, root, i) { 67962306a36Sopenharmony_ci if (!root) 68062306a36Sopenharmony_ci continue; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci if ((res->flags ^ root->flags) & 68362306a36Sopenharmony_ci (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)) 68462306a36Sopenharmony_ci continue; /* Wrong type */ 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci if (yenta_search_one_res(root, res, min)) 68762306a36Sopenharmony_ci return 1; 68862306a36Sopenharmony_ci } 68962306a36Sopenharmony_ci return 0; 69062306a36Sopenharmony_ci} 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci struct pci_dev *dev = socket->dev; 69562306a36Sopenharmony_ci struct resource *res; 69662306a36Sopenharmony_ci struct pci_bus_region region; 69762306a36Sopenharmony_ci unsigned mask; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci res = &dev->resource[nr]; 70062306a36Sopenharmony_ci /* Already allocated? */ 70162306a36Sopenharmony_ci if (res->parent) 70262306a36Sopenharmony_ci return 0; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ 70562306a36Sopenharmony_ci mask = ~0xfff; 70662306a36Sopenharmony_ci if (type & IORESOURCE_IO) 70762306a36Sopenharmony_ci mask = ~3; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci res->name = dev->subordinate->name; 71062306a36Sopenharmony_ci res->flags = type; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci region.start = config_readl(socket, addr_start) & mask; 71362306a36Sopenharmony_ci region.end = config_readl(socket, addr_end) | ~mask; 71462306a36Sopenharmony_ci if (region.start && region.end > region.start && !override_bios) { 71562306a36Sopenharmony_ci pcibios_bus_to_resource(dev->bus, res, ®ion); 71662306a36Sopenharmony_ci if (pci_claim_resource(dev, nr) == 0) 71762306a36Sopenharmony_ci return 0; 71862306a36Sopenharmony_ci dev_info(&dev->dev, 71962306a36Sopenharmony_ci "Preassigned resource %d busy or not available, reconfiguring...\n", 72062306a36Sopenharmony_ci nr); 72162306a36Sopenharmony_ci } 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci if (type & IORESOURCE_IO) { 72462306a36Sopenharmony_ci if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) || 72562306a36Sopenharmony_ci (yenta_search_res(socket, res, BRIDGE_IO_ACC)) || 72662306a36Sopenharmony_ci (yenta_search_res(socket, res, BRIDGE_IO_MIN))) 72762306a36Sopenharmony_ci return 1; 72862306a36Sopenharmony_ci } else { 72962306a36Sopenharmony_ci if (type & IORESOURCE_PREFETCH) { 73062306a36Sopenharmony_ci if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || 73162306a36Sopenharmony_ci (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || 73262306a36Sopenharmony_ci (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) 73362306a36Sopenharmony_ci return 1; 73462306a36Sopenharmony_ci /* Approximating prefetchable by non-prefetchable */ 73562306a36Sopenharmony_ci res->flags = IORESOURCE_MEM; 73662306a36Sopenharmony_ci } 73762306a36Sopenharmony_ci if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || 73862306a36Sopenharmony_ci (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || 73962306a36Sopenharmony_ci (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) 74062306a36Sopenharmony_ci return 1; 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci dev_info(&dev->dev, 74462306a36Sopenharmony_ci "no resource of type %x available, trying to continue...\n", 74562306a36Sopenharmony_ci type); 74662306a36Sopenharmony_ci res->start = res->end = res->flags = 0; 74762306a36Sopenharmony_ci return 0; 74862306a36Sopenharmony_ci} 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_cistatic void yenta_free_res(struct yenta_socket *socket, int nr) 75162306a36Sopenharmony_ci{ 75262306a36Sopenharmony_ci struct pci_dev *dev = socket->dev; 75362306a36Sopenharmony_ci struct resource *res; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci res = &dev->resource[nr]; 75662306a36Sopenharmony_ci if (res->start != 0 && res->end != 0) 75762306a36Sopenharmony_ci release_resource(res); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci res->start = res->end = res->flags = 0; 76062306a36Sopenharmony_ci} 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci/* 76362306a36Sopenharmony_ci * Allocate the bridge mappings for the device.. 76462306a36Sopenharmony_ci */ 76562306a36Sopenharmony_cistatic void yenta_allocate_resources(struct yenta_socket *socket) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci int program = 0; 76862306a36Sopenharmony_ci program += yenta_allocate_res(socket, PCI_CB_BRIDGE_IO_0_WINDOW, 76962306a36Sopenharmony_ci IORESOURCE_IO, 77062306a36Sopenharmony_ci PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); 77162306a36Sopenharmony_ci program += yenta_allocate_res(socket, PCI_CB_BRIDGE_IO_1_WINDOW, 77262306a36Sopenharmony_ci IORESOURCE_IO, 77362306a36Sopenharmony_ci PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); 77462306a36Sopenharmony_ci program += yenta_allocate_res(socket, PCI_CB_BRIDGE_MEM_0_WINDOW, 77562306a36Sopenharmony_ci IORESOURCE_MEM | IORESOURCE_PREFETCH, 77662306a36Sopenharmony_ci PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); 77762306a36Sopenharmony_ci program += yenta_allocate_res(socket, PCI_CB_BRIDGE_MEM_1_WINDOW, 77862306a36Sopenharmony_ci IORESOURCE_MEM, 77962306a36Sopenharmony_ci PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); 78062306a36Sopenharmony_ci if (program) 78162306a36Sopenharmony_ci pci_setup_cardbus(socket->dev->subordinate); 78262306a36Sopenharmony_ci} 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci/* 78662306a36Sopenharmony_ci * Free the bridge mappings for the device.. 78762306a36Sopenharmony_ci */ 78862306a36Sopenharmony_cistatic void yenta_free_resources(struct yenta_socket *socket) 78962306a36Sopenharmony_ci{ 79062306a36Sopenharmony_ci yenta_free_res(socket, PCI_CB_BRIDGE_IO_0_WINDOW); 79162306a36Sopenharmony_ci yenta_free_res(socket, PCI_CB_BRIDGE_IO_1_WINDOW); 79262306a36Sopenharmony_ci yenta_free_res(socket, PCI_CB_BRIDGE_MEM_0_WINDOW); 79362306a36Sopenharmony_ci yenta_free_res(socket, PCI_CB_BRIDGE_MEM_1_WINDOW); 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci/* 79862306a36Sopenharmony_ci * Close it down - release our resources and go home.. 79962306a36Sopenharmony_ci */ 80062306a36Sopenharmony_cistatic void yenta_close(struct pci_dev *dev) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci struct yenta_socket *sock = pci_get_drvdata(dev); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci /* Remove the register attributes */ 80562306a36Sopenharmony_ci device_remove_file(&dev->dev, &dev_attr_yenta_registers); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci /* we don't want a dying socket registered */ 80862306a36Sopenharmony_ci pcmcia_unregister_socket(&sock->socket); 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci /* Disable all events so we don't die in an IRQ storm */ 81162306a36Sopenharmony_ci cb_writel(sock, CB_SOCKET_MASK, 0x0); 81262306a36Sopenharmony_ci exca_writeb(sock, I365_CSCINT, 0); 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci if (sock->cb_irq) 81562306a36Sopenharmony_ci free_irq(sock->cb_irq, sock); 81662306a36Sopenharmony_ci else 81762306a36Sopenharmony_ci timer_shutdown_sync(&sock->poll_timer); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci iounmap(sock->base); 82062306a36Sopenharmony_ci yenta_free_resources(sock); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci pci_release_regions(dev); 82362306a36Sopenharmony_ci pci_disable_device(dev); 82462306a36Sopenharmony_ci pci_set_drvdata(dev, NULL); 82562306a36Sopenharmony_ci kfree(sock); 82662306a36Sopenharmony_ci} 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_cistatic struct pccard_operations yenta_socket_operations = { 83062306a36Sopenharmony_ci .init = yenta_sock_init, 83162306a36Sopenharmony_ci .suspend = yenta_sock_suspend, 83262306a36Sopenharmony_ci .get_status = yenta_get_status, 83362306a36Sopenharmony_ci .set_socket = yenta_set_socket, 83462306a36Sopenharmony_ci .set_io_map = yenta_set_io_map, 83562306a36Sopenharmony_ci .set_mem_map = yenta_set_mem_map, 83662306a36Sopenharmony_ci}; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci#ifdef CONFIG_YENTA_TI 84062306a36Sopenharmony_ci#include "ti113x.h" 84162306a36Sopenharmony_ci#endif 84262306a36Sopenharmony_ci#ifdef CONFIG_YENTA_RICOH 84362306a36Sopenharmony_ci#include "ricoh.h" 84462306a36Sopenharmony_ci#endif 84562306a36Sopenharmony_ci#ifdef CONFIG_YENTA_TOSHIBA 84662306a36Sopenharmony_ci#include "topic.h" 84762306a36Sopenharmony_ci#endif 84862306a36Sopenharmony_ci#ifdef CONFIG_YENTA_O2 84962306a36Sopenharmony_ci#include "o2micro.h" 85062306a36Sopenharmony_ci#endif 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_cienum { 85362306a36Sopenharmony_ci CARDBUS_TYPE_DEFAULT = -1, 85462306a36Sopenharmony_ci CARDBUS_TYPE_TI, 85562306a36Sopenharmony_ci CARDBUS_TYPE_TI113X, 85662306a36Sopenharmony_ci CARDBUS_TYPE_TI12XX, 85762306a36Sopenharmony_ci CARDBUS_TYPE_TI1250, 85862306a36Sopenharmony_ci CARDBUS_TYPE_RICOH, 85962306a36Sopenharmony_ci CARDBUS_TYPE_TOPIC95, 86062306a36Sopenharmony_ci CARDBUS_TYPE_TOPIC97, 86162306a36Sopenharmony_ci CARDBUS_TYPE_O2MICRO, 86262306a36Sopenharmony_ci CARDBUS_TYPE_ENE, 86362306a36Sopenharmony_ci}; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci/* 86662306a36Sopenharmony_ci * Different cardbus controllers have slightly different 86762306a36Sopenharmony_ci * initialization sequences etc details. List them here.. 86862306a36Sopenharmony_ci */ 86962306a36Sopenharmony_cistatic struct cardbus_type cardbus_type[] = { 87062306a36Sopenharmony_ci#ifdef CONFIG_YENTA_TI 87162306a36Sopenharmony_ci [CARDBUS_TYPE_TI] = { 87262306a36Sopenharmony_ci .override = ti_override, 87362306a36Sopenharmony_ci .save_state = ti_save_state, 87462306a36Sopenharmony_ci .restore_state = ti_restore_state, 87562306a36Sopenharmony_ci .sock_init = ti_init, 87662306a36Sopenharmony_ci }, 87762306a36Sopenharmony_ci [CARDBUS_TYPE_TI113X] = { 87862306a36Sopenharmony_ci .override = ti113x_override, 87962306a36Sopenharmony_ci .save_state = ti_save_state, 88062306a36Sopenharmony_ci .restore_state = ti_restore_state, 88162306a36Sopenharmony_ci .sock_init = ti_init, 88262306a36Sopenharmony_ci }, 88362306a36Sopenharmony_ci [CARDBUS_TYPE_TI12XX] = { 88462306a36Sopenharmony_ci .override = ti12xx_override, 88562306a36Sopenharmony_ci .save_state = ti_save_state, 88662306a36Sopenharmony_ci .restore_state = ti_restore_state, 88762306a36Sopenharmony_ci .sock_init = ti_init, 88862306a36Sopenharmony_ci }, 88962306a36Sopenharmony_ci [CARDBUS_TYPE_TI1250] = { 89062306a36Sopenharmony_ci .override = ti1250_override, 89162306a36Sopenharmony_ci .save_state = ti_save_state, 89262306a36Sopenharmony_ci .restore_state = ti_restore_state, 89362306a36Sopenharmony_ci .sock_init = ti_init, 89462306a36Sopenharmony_ci }, 89562306a36Sopenharmony_ci [CARDBUS_TYPE_ENE] = { 89662306a36Sopenharmony_ci .override = ene_override, 89762306a36Sopenharmony_ci .save_state = ti_save_state, 89862306a36Sopenharmony_ci .restore_state = ti_restore_state, 89962306a36Sopenharmony_ci .sock_init = ti_init, 90062306a36Sopenharmony_ci }, 90162306a36Sopenharmony_ci#endif 90262306a36Sopenharmony_ci#ifdef CONFIG_YENTA_RICOH 90362306a36Sopenharmony_ci [CARDBUS_TYPE_RICOH] = { 90462306a36Sopenharmony_ci .override = ricoh_override, 90562306a36Sopenharmony_ci .save_state = ricoh_save_state, 90662306a36Sopenharmony_ci .restore_state = ricoh_restore_state, 90762306a36Sopenharmony_ci }, 90862306a36Sopenharmony_ci#endif 90962306a36Sopenharmony_ci#ifdef CONFIG_YENTA_TOSHIBA 91062306a36Sopenharmony_ci [CARDBUS_TYPE_TOPIC95] = { 91162306a36Sopenharmony_ci .override = topic95_override, 91262306a36Sopenharmony_ci }, 91362306a36Sopenharmony_ci [CARDBUS_TYPE_TOPIC97] = { 91462306a36Sopenharmony_ci .override = topic97_override, 91562306a36Sopenharmony_ci }, 91662306a36Sopenharmony_ci#endif 91762306a36Sopenharmony_ci#ifdef CONFIG_YENTA_O2 91862306a36Sopenharmony_ci [CARDBUS_TYPE_O2MICRO] = { 91962306a36Sopenharmony_ci .override = o2micro_override, 92062306a36Sopenharmony_ci .restore_state = o2micro_restore_state, 92162306a36Sopenharmony_ci }, 92262306a36Sopenharmony_ci#endif 92362306a36Sopenharmony_ci}; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_cistatic unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask) 92762306a36Sopenharmony_ci{ 92862306a36Sopenharmony_ci int i; 92962306a36Sopenharmony_ci unsigned long val; 93062306a36Sopenharmony_ci u32 mask; 93162306a36Sopenharmony_ci u8 reg; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci /* 93462306a36Sopenharmony_ci * Probe for usable interrupts using the force 93562306a36Sopenharmony_ci * register to generate bogus card status events. 93662306a36Sopenharmony_ci */ 93762306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_EVENT, -1); 93862306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); 93962306a36Sopenharmony_ci reg = exca_readb(socket, I365_CSCINT); 94062306a36Sopenharmony_ci exca_writeb(socket, I365_CSCINT, 0); 94162306a36Sopenharmony_ci val = probe_irq_on() & isa_irq_mask; 94262306a36Sopenharmony_ci for (i = 1; i < 16; i++) { 94362306a36Sopenharmony_ci if (!((val >> i) & 1)) 94462306a36Sopenharmony_ci continue; 94562306a36Sopenharmony_ci exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4)); 94662306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); 94762306a36Sopenharmony_ci udelay(100); 94862306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_EVENT, -1); 94962306a36Sopenharmony_ci } 95062306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_MASK, 0); 95162306a36Sopenharmony_ci exca_writeb(socket, I365_CSCINT, reg); 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci mask = probe_irq_mask(val) & 0xffff; 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci return mask; 95662306a36Sopenharmony_ci} 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci/* 96062306a36Sopenharmony_ci * yenta PCI irq probing. 96162306a36Sopenharmony_ci * currently only used in the TI/EnE initialization code 96262306a36Sopenharmony_ci */ 96362306a36Sopenharmony_ci#ifdef CONFIG_YENTA_TI 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci/* interrupt handler, only used during probing */ 96662306a36Sopenharmony_cistatic irqreturn_t yenta_probe_handler(int irq, void *dev_id) 96762306a36Sopenharmony_ci{ 96862306a36Sopenharmony_ci struct yenta_socket *socket = (struct yenta_socket *) dev_id; 96962306a36Sopenharmony_ci u8 csc; 97062306a36Sopenharmony_ci u32 cb_event; 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci /* Clear interrupt status for the event */ 97362306a36Sopenharmony_ci cb_event = cb_readl(socket, CB_SOCKET_EVENT); 97462306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_EVENT, -1); 97562306a36Sopenharmony_ci csc = exca_readb(socket, I365_CSC); 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci if (cb_event || csc) { 97862306a36Sopenharmony_ci socket->probe_status = 1; 97962306a36Sopenharmony_ci return IRQ_HANDLED; 98062306a36Sopenharmony_ci } 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci return IRQ_NONE; 98362306a36Sopenharmony_ci} 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci/* probes the PCI interrupt, use only on override functions */ 98662306a36Sopenharmony_cistatic int yenta_probe_cb_irq(struct yenta_socket *socket) 98762306a36Sopenharmony_ci{ 98862306a36Sopenharmony_ci u8 reg = 0; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci if (!socket->cb_irq) 99162306a36Sopenharmony_ci return -1; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci socket->probe_status = 0; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci if (request_irq(socket->cb_irq, yenta_probe_handler, IRQF_SHARED, "yenta", socket)) { 99662306a36Sopenharmony_ci dev_warn(&socket->dev->dev, 99762306a36Sopenharmony_ci "request_irq() in yenta_probe_cb_irq() failed!\n"); 99862306a36Sopenharmony_ci return -1; 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci /* generate interrupt, wait */ 100262306a36Sopenharmony_ci if (!socket->dev->irq) 100362306a36Sopenharmony_ci reg = exca_readb(socket, I365_CSCINT); 100462306a36Sopenharmony_ci exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG); 100562306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_EVENT, -1); 100662306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); 100762306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci msleep(100); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci /* disable interrupts */ 101262306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_MASK, 0); 101362306a36Sopenharmony_ci exca_writeb(socket, I365_CSCINT, reg); 101462306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_EVENT, -1); 101562306a36Sopenharmony_ci exca_readb(socket, I365_CSC); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci free_irq(socket->cb_irq, socket); 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci return (int) socket->probe_status; 102062306a36Sopenharmony_ci} 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci#endif /* CONFIG_YENTA_TI */ 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci/* 102662306a36Sopenharmony_ci * Set static data that doesn't need re-initializing.. 102762306a36Sopenharmony_ci */ 102862306a36Sopenharmony_cistatic void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask) 102962306a36Sopenharmony_ci{ 103062306a36Sopenharmony_ci socket->socket.pci_irq = socket->cb_irq; 103162306a36Sopenharmony_ci if (isa_probe) 103262306a36Sopenharmony_ci socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask); 103362306a36Sopenharmony_ci else 103462306a36Sopenharmony_ci socket->socket.irq_mask = 0; 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci dev_info(&socket->dev->dev, "ISA IRQ mask 0x%04x, PCI irq %d\n", 103762306a36Sopenharmony_ci socket->socket.irq_mask, socket->cb_irq); 103862306a36Sopenharmony_ci} 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci/* 104162306a36Sopenharmony_ci * Initialize the standard cardbus registers 104262306a36Sopenharmony_ci */ 104362306a36Sopenharmony_cistatic void yenta_config_init(struct yenta_socket *socket) 104462306a36Sopenharmony_ci{ 104562306a36Sopenharmony_ci u16 bridge; 104662306a36Sopenharmony_ci struct pci_dev *dev = socket->dev; 104762306a36Sopenharmony_ci struct pci_bus_region region; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci pcibios_resource_to_bus(socket->dev->bus, ®ion, &dev->resource[0]); 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci config_writel(socket, CB_LEGACY_MODE_BASE, 0); 105262306a36Sopenharmony_ci config_writel(socket, PCI_BASE_ADDRESS_0, region.start); 105362306a36Sopenharmony_ci config_writew(socket, PCI_COMMAND, 105462306a36Sopenharmony_ci PCI_COMMAND_IO | 105562306a36Sopenharmony_ci PCI_COMMAND_MEMORY | 105662306a36Sopenharmony_ci PCI_COMMAND_MASTER | 105762306a36Sopenharmony_ci PCI_COMMAND_WAIT); 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci /* MAGIC NUMBERS! Fixme */ 106062306a36Sopenharmony_ci config_writeb(socket, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); 106162306a36Sopenharmony_ci config_writeb(socket, PCI_LATENCY_TIMER, 168); 106262306a36Sopenharmony_ci config_writel(socket, PCI_PRIMARY_BUS, 106362306a36Sopenharmony_ci (176 << 24) | /* sec. latency timer */ 106462306a36Sopenharmony_ci ((unsigned int)dev->subordinate->busn_res.end << 16) | /* subordinate bus */ 106562306a36Sopenharmony_ci ((unsigned int)dev->subordinate->busn_res.start << 8) | /* secondary bus */ 106662306a36Sopenharmony_ci dev->subordinate->primary); /* primary bus */ 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci /* 106962306a36Sopenharmony_ci * Set up the bridging state: 107062306a36Sopenharmony_ci * - enable write posting. 107162306a36Sopenharmony_ci * - memory window 0 prefetchable, window 1 non-prefetchable 107262306a36Sopenharmony_ci * - PCI interrupts enabled if a PCI interrupt exists.. 107362306a36Sopenharmony_ci */ 107462306a36Sopenharmony_ci bridge = config_readw(socket, CB_BRIDGE_CONTROL); 107562306a36Sopenharmony_ci bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); 107662306a36Sopenharmony_ci bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN; 107762306a36Sopenharmony_ci config_writew(socket, CB_BRIDGE_CONTROL, bridge); 107862306a36Sopenharmony_ci} 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci/** 108162306a36Sopenharmony_ci * yenta_fixup_parent_bridge - Fix subordinate bus# of the parent bridge 108262306a36Sopenharmony_ci * @cardbus_bridge: The PCI bus which the CardBus bridge bridges to 108362306a36Sopenharmony_ci * 108462306a36Sopenharmony_ci * Checks if devices on the bus which the CardBus bridge bridges to would be 108562306a36Sopenharmony_ci * invisible during PCI scans because of a misconfigured subordinate number 108662306a36Sopenharmony_ci * of the parent brige - some BIOSes seem to be too lazy to set it right. 108762306a36Sopenharmony_ci * Does the fixup carefully by checking how far it can go without conflicts. 108862306a36Sopenharmony_ci * See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information. 108962306a36Sopenharmony_ci */ 109062306a36Sopenharmony_cistatic void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) 109162306a36Sopenharmony_ci{ 109262306a36Sopenharmony_ci struct pci_bus *sibling; 109362306a36Sopenharmony_ci unsigned char upper_limit; 109462306a36Sopenharmony_ci /* 109562306a36Sopenharmony_ci * We only check and fix the parent bridge: All systems which need 109662306a36Sopenharmony_ci * this fixup that have been reviewed are laptops and the only bridge 109762306a36Sopenharmony_ci * which needed fixing was the parent bridge of the CardBus bridge: 109862306a36Sopenharmony_ci */ 109962306a36Sopenharmony_ci struct pci_bus *bridge_to_fix = cardbus_bridge->parent; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* Check bus numbers are already set up correctly: */ 110262306a36Sopenharmony_ci if (bridge_to_fix->busn_res.end >= cardbus_bridge->busn_res.end) 110362306a36Sopenharmony_ci return; /* The subordinate number is ok, nothing to do */ 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci if (!bridge_to_fix->parent) 110662306a36Sopenharmony_ci return; /* Root bridges are ok */ 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci /* stay within the limits of the bus range of the parent: */ 110962306a36Sopenharmony_ci upper_limit = bridge_to_fix->parent->busn_res.end; 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci /* check the bus ranges of all sibling bridges to prevent overlap */ 111262306a36Sopenharmony_ci list_for_each_entry(sibling, &bridge_to_fix->parent->children, 111362306a36Sopenharmony_ci node) { 111462306a36Sopenharmony_ci /* 111562306a36Sopenharmony_ci * If the sibling has a higher secondary bus number 111662306a36Sopenharmony_ci * and it's secondary is equal or smaller than our 111762306a36Sopenharmony_ci * current upper limit, set the new upper limit to 111862306a36Sopenharmony_ci * the bus number below the sibling's range: 111962306a36Sopenharmony_ci */ 112062306a36Sopenharmony_ci if (sibling->busn_res.start > bridge_to_fix->busn_res.end 112162306a36Sopenharmony_ci && sibling->busn_res.start <= upper_limit) 112262306a36Sopenharmony_ci upper_limit = sibling->busn_res.start - 1; 112362306a36Sopenharmony_ci } 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci /* Show that the wanted subordinate number is not possible: */ 112662306a36Sopenharmony_ci if (cardbus_bridge->busn_res.end > upper_limit) 112762306a36Sopenharmony_ci dev_warn(&cardbus_bridge->dev, 112862306a36Sopenharmony_ci "Upper limit for fixing this bridge's parent bridge: #%02x\n", 112962306a36Sopenharmony_ci upper_limit); 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci /* If we have room to increase the bridge's subordinate number, */ 113262306a36Sopenharmony_ci if (bridge_to_fix->busn_res.end < upper_limit) { 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci /* use the highest number of the hidden bus, within limits */ 113562306a36Sopenharmony_ci unsigned char subordinate_to_assign = 113662306a36Sopenharmony_ci min_t(int, cardbus_bridge->busn_res.end, upper_limit); 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci dev_info(&bridge_to_fix->dev, 113962306a36Sopenharmony_ci "Raising subordinate bus# of parent bus (#%02x) from #%02x to #%02x\n", 114062306a36Sopenharmony_ci bridge_to_fix->number, 114162306a36Sopenharmony_ci (int)bridge_to_fix->busn_res.end, 114262306a36Sopenharmony_ci subordinate_to_assign); 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci /* Save the new subordinate in the bus struct of the bridge */ 114562306a36Sopenharmony_ci bridge_to_fix->busn_res.end = subordinate_to_assign; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci /* and update the PCI config space with the new subordinate */ 114862306a36Sopenharmony_ci pci_write_config_byte(bridge_to_fix->self, 114962306a36Sopenharmony_ci PCI_SUBORDINATE_BUS, bridge_to_fix->busn_res.end); 115062306a36Sopenharmony_ci } 115162306a36Sopenharmony_ci} 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci/* 115462306a36Sopenharmony_ci * Initialize a cardbus controller. Make sure we have a usable 115562306a36Sopenharmony_ci * interrupt, and that we can map the cardbus area. Fill in the 115662306a36Sopenharmony_ci * socket information structure.. 115762306a36Sopenharmony_ci */ 115862306a36Sopenharmony_cistatic int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id) 115962306a36Sopenharmony_ci{ 116062306a36Sopenharmony_ci struct yenta_socket *socket; 116162306a36Sopenharmony_ci int ret; 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci /* 116462306a36Sopenharmony_ci * If we failed to assign proper bus numbers for this cardbus 116562306a36Sopenharmony_ci * controller during PCI probe, its subordinate pci_bus is NULL. 116662306a36Sopenharmony_ci * Bail out if so. 116762306a36Sopenharmony_ci */ 116862306a36Sopenharmony_ci if (!dev->subordinate) { 116962306a36Sopenharmony_ci dev_err(&dev->dev, "no bus associated! (try 'pci=assign-busses')\n"); 117062306a36Sopenharmony_ci return -ENODEV; 117162306a36Sopenharmony_ci } 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci socket = kzalloc(sizeof(struct yenta_socket), GFP_KERNEL); 117462306a36Sopenharmony_ci if (!socket) 117562306a36Sopenharmony_ci return -ENOMEM; 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci /* prepare pcmcia_socket */ 117862306a36Sopenharmony_ci socket->socket.ops = ¥ta_socket_operations; 117962306a36Sopenharmony_ci socket->socket.resource_ops = &pccard_nonstatic_ops; 118062306a36Sopenharmony_ci socket->socket.dev.parent = &dev->dev; 118162306a36Sopenharmony_ci socket->socket.driver_data = socket; 118262306a36Sopenharmony_ci socket->socket.owner = THIS_MODULE; 118362306a36Sopenharmony_ci socket->socket.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD; 118462306a36Sopenharmony_ci socket->socket.map_size = 0x1000; 118562306a36Sopenharmony_ci socket->socket.cb_dev = dev; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci /* prepare struct yenta_socket */ 118862306a36Sopenharmony_ci socket->dev = dev; 118962306a36Sopenharmony_ci pci_set_drvdata(dev, socket); 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci /* 119262306a36Sopenharmony_ci * Do some basic sanity checking.. 119362306a36Sopenharmony_ci */ 119462306a36Sopenharmony_ci if (pci_enable_device(dev)) { 119562306a36Sopenharmony_ci ret = -EBUSY; 119662306a36Sopenharmony_ci goto free; 119762306a36Sopenharmony_ci } 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci ret = pci_request_regions(dev, "yenta_socket"); 120062306a36Sopenharmony_ci if (ret) 120162306a36Sopenharmony_ci goto disable; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci if (!pci_resource_start(dev, 0)) { 120462306a36Sopenharmony_ci dev_err(&dev->dev, "No cardbus resource!\n"); 120562306a36Sopenharmony_ci ret = -ENODEV; 120662306a36Sopenharmony_ci goto release; 120762306a36Sopenharmony_ci } 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci /* 121062306a36Sopenharmony_ci * Ok, start setup.. Map the cardbus registers, 121162306a36Sopenharmony_ci * and request the IRQ. 121262306a36Sopenharmony_ci */ 121362306a36Sopenharmony_ci socket->base = ioremap(pci_resource_start(dev, 0), 0x1000); 121462306a36Sopenharmony_ci if (!socket->base) { 121562306a36Sopenharmony_ci ret = -ENOMEM; 121662306a36Sopenharmony_ci goto release; 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci /* 122062306a36Sopenharmony_ci * report the subsystem vendor and device for help debugging 122162306a36Sopenharmony_ci * the irq stuff... 122262306a36Sopenharmony_ci */ 122362306a36Sopenharmony_ci dev_info(&dev->dev, "CardBus bridge found [%04x:%04x]\n", 122462306a36Sopenharmony_ci dev->subsystem_vendor, dev->subsystem_device); 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci yenta_config_init(socket); 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci /* Disable all events */ 122962306a36Sopenharmony_ci cb_writel(socket, CB_SOCKET_MASK, 0x0); 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci /* Set up the bridge regions.. */ 123262306a36Sopenharmony_ci yenta_allocate_resources(socket); 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci socket->cb_irq = dev->irq; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci /* Do we have special options for the device? */ 123762306a36Sopenharmony_ci if (id->driver_data != CARDBUS_TYPE_DEFAULT && 123862306a36Sopenharmony_ci id->driver_data < ARRAY_SIZE(cardbus_type)) { 123962306a36Sopenharmony_ci socket->type = &cardbus_type[id->driver_data]; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci ret = socket->type->override(socket); 124262306a36Sopenharmony_ci if (ret < 0) 124362306a36Sopenharmony_ci goto unmap; 124462306a36Sopenharmony_ci } 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci /* We must finish initialization here */ 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, IRQF_SHARED, "yenta", socket)) { 124962306a36Sopenharmony_ci /* No IRQ or request_irq failed. Poll */ 125062306a36Sopenharmony_ci socket->cb_irq = 0; /* But zero is a valid IRQ number. */ 125162306a36Sopenharmony_ci timer_setup(&socket->poll_timer, yenta_interrupt_wrapper, 0); 125262306a36Sopenharmony_ci mod_timer(&socket->poll_timer, jiffies + HZ); 125362306a36Sopenharmony_ci dev_info(&dev->dev, 125462306a36Sopenharmony_ci "no PCI IRQ, CardBus support disabled for this socket.\n"); 125562306a36Sopenharmony_ci dev_info(&dev->dev, 125662306a36Sopenharmony_ci "check your BIOS CardBus, BIOS IRQ or ACPI settings.\n"); 125762306a36Sopenharmony_ci } else { 125862306a36Sopenharmony_ci socket->socket.features |= SS_CAP_CARDBUS; 125962306a36Sopenharmony_ci } 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci /* Figure out what the dang thing can do for the PCMCIA layer... */ 126262306a36Sopenharmony_ci yenta_interrogate(socket); 126362306a36Sopenharmony_ci yenta_get_socket_capabilities(socket, isa_interrupts); 126462306a36Sopenharmony_ci dev_info(&dev->dev, "Socket status: %08x\n", 126562306a36Sopenharmony_ci cb_readl(socket, CB_SOCKET_STATE)); 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci yenta_fixup_parent_bridge(dev->subordinate); 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci /* Register it with the pcmcia layer.. */ 127062306a36Sopenharmony_ci ret = pcmcia_register_socket(&socket->socket); 127162306a36Sopenharmony_ci if (ret) 127262306a36Sopenharmony_ci goto free_irq; 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci /* Add the yenta register attributes */ 127562306a36Sopenharmony_ci ret = device_create_file(&dev->dev, &dev_attr_yenta_registers); 127662306a36Sopenharmony_ci if (ret) 127762306a36Sopenharmony_ci goto unregister_socket; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci return ret; 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci /* error path... */ 128262306a36Sopenharmony_ci unregister_socket: 128362306a36Sopenharmony_ci pcmcia_unregister_socket(&socket->socket); 128462306a36Sopenharmony_ci free_irq: 128562306a36Sopenharmony_ci if (socket->cb_irq) 128662306a36Sopenharmony_ci free_irq(socket->cb_irq, socket); 128762306a36Sopenharmony_ci else 128862306a36Sopenharmony_ci timer_shutdown_sync(&socket->poll_timer); 128962306a36Sopenharmony_ci unmap: 129062306a36Sopenharmony_ci iounmap(socket->base); 129162306a36Sopenharmony_ci yenta_free_resources(socket); 129262306a36Sopenharmony_ci release: 129362306a36Sopenharmony_ci pci_release_regions(dev); 129462306a36Sopenharmony_ci disable: 129562306a36Sopenharmony_ci pci_disable_device(dev); 129662306a36Sopenharmony_ci free: 129762306a36Sopenharmony_ci pci_set_drvdata(dev, NULL); 129862306a36Sopenharmony_ci kfree(socket); 129962306a36Sopenharmony_ci return ret; 130062306a36Sopenharmony_ci} 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 130362306a36Sopenharmony_cistatic int yenta_dev_suspend_noirq(struct device *dev) 130462306a36Sopenharmony_ci{ 130562306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev); 130662306a36Sopenharmony_ci struct yenta_socket *socket = pci_get_drvdata(pdev); 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci if (!socket) 130962306a36Sopenharmony_ci return 0; 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci if (socket->type && socket->type->save_state) 131262306a36Sopenharmony_ci socket->type->save_state(socket); 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci pci_save_state(pdev); 131562306a36Sopenharmony_ci pci_read_config_dword(pdev, 16*4, &socket->saved_state[0]); 131662306a36Sopenharmony_ci pci_read_config_dword(pdev, 17*4, &socket->saved_state[1]); 131762306a36Sopenharmony_ci pci_disable_device(pdev); 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci return 0; 132062306a36Sopenharmony_ci} 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_cistatic int yenta_dev_resume_noirq(struct device *dev) 132362306a36Sopenharmony_ci{ 132462306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev); 132562306a36Sopenharmony_ci struct yenta_socket *socket = pci_get_drvdata(pdev); 132662306a36Sopenharmony_ci int ret; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci if (!socket) 132962306a36Sopenharmony_ci return 0; 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci pci_write_config_dword(pdev, 16*4, socket->saved_state[0]); 133262306a36Sopenharmony_ci pci_write_config_dword(pdev, 17*4, socket->saved_state[1]); 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci ret = pci_enable_device(pdev); 133562306a36Sopenharmony_ci if (ret) 133662306a36Sopenharmony_ci return ret; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci pci_set_master(pdev); 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci if (socket->type && socket->type->restore_state) 134162306a36Sopenharmony_ci socket->type->restore_state(socket); 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci return 0; 134462306a36Sopenharmony_ci} 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_cistatic const struct dev_pm_ops yenta_pm_ops = { 134762306a36Sopenharmony_ci SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(yenta_dev_suspend_noirq, yenta_dev_resume_noirq) 134862306a36Sopenharmony_ci}; 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci#define YENTA_PM_OPS (¥ta_pm_ops) 135162306a36Sopenharmony_ci#else 135262306a36Sopenharmony_ci#define YENTA_PM_OPS NULL 135362306a36Sopenharmony_ci#endif 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci#define CB_ID(vend, dev, type) \ 135662306a36Sopenharmony_ci { \ 135762306a36Sopenharmony_ci .vendor = vend, \ 135862306a36Sopenharmony_ci .device = dev, \ 135962306a36Sopenharmony_ci .subvendor = PCI_ANY_ID, \ 136062306a36Sopenharmony_ci .subdevice = PCI_ANY_ID, \ 136162306a36Sopenharmony_ci .class = PCI_CLASS_BRIDGE_CARDBUS << 8, \ 136262306a36Sopenharmony_ci .class_mask = ~0, \ 136362306a36Sopenharmony_ci .driver_data = CARDBUS_TYPE_##type, \ 136462306a36Sopenharmony_ci } 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_cistatic const struct pci_device_id yenta_table[] = { 136762306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI), 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci /* 137062306a36Sopenharmony_ci * TBD: Check if these TI variants can use more 137162306a36Sopenharmony_ci * advanced overrides instead. (I can't get the 137262306a36Sopenharmony_ci * data sheets for these devices. --rmk) 137362306a36Sopenharmony_ci */ 137462306a36Sopenharmony_ci#ifdef CONFIG_YENTA_TI 137562306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210, TI), 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130, TI113X), 137862306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1131, TI113X), 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211, TI12XX), 138162306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1220, TI12XX), 138262306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1221, TI12XX), 138362306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1225, TI12XX), 138462306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251A, TI12XX), 138562306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251B, TI12XX), 138662306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, TI12XX), 138762306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1450, TI12XX), 138862306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1451A, TI12XX), 138962306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510, TI12XX), 139062306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520, TI12XX), 139162306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1620, TI12XX), 139262306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX), 139362306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX), 139462306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX), 139562306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4510, TI12XX), 139662306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4520, TI12XX), 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), 139962306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX), 140262306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX), 140362306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12, TI12XX), 140462306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX), 140562306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX), 140662306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX), 140762306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX), 140862306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX), 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, ENE), 141162306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, ENE), 141262306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, ENE), 141362306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, ENE), 141462306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), 141562306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), 141662306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), 141762306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE), 141862306a36Sopenharmony_ci#endif /* CONFIG_YENTA_TI */ 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci#ifdef CONFIG_YENTA_RICOH 142162306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), 142262306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), 142362306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475, RICOH), 142462306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), 142562306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), 142662306a36Sopenharmony_ci#endif 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci#ifdef CONFIG_YENTA_TOSHIBA 142962306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95), 143062306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), 143162306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), 143262306a36Sopenharmony_ci#endif 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci#ifdef CONFIG_YENTA_O2 143562306a36Sopenharmony_ci CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO), 143662306a36Sopenharmony_ci#endif 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci /* match any cardbus bridge */ 143962306a36Sopenharmony_ci CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT), 144062306a36Sopenharmony_ci { /* all zeroes */ } 144162306a36Sopenharmony_ci}; 144262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, yenta_table); 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_cistatic struct pci_driver yenta_cardbus_driver = { 144662306a36Sopenharmony_ci .name = "yenta_cardbus", 144762306a36Sopenharmony_ci .id_table = yenta_table, 144862306a36Sopenharmony_ci .probe = yenta_probe, 144962306a36Sopenharmony_ci .remove = yenta_close, 145062306a36Sopenharmony_ci .driver.pm = YENTA_PM_OPS, 145162306a36Sopenharmony_ci}; 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_cimodule_pci_driver(yenta_cardbus_driver); 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1456