summaryrefslogtreecommitdiff
path: root/drivers/pcmcia/yenta_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/yenta_socket.c')
-rw-r--r--drivers/pcmcia/yenta_socket.c122
1 files changed, 65 insertions, 57 deletions
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 0347a29f297b..db9f952f9e3c 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -72,6 +72,7 @@ static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
{
debug("%p %04x %08x\n", socket, reg, val);
writel(val, socket->base + reg);
+ readl(socket->base + reg); /* avoid problems with PCI write posting */
}
static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
@@ -136,6 +137,7 @@ static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val
{
debug("%p %04x %02x\n", socket, reg, val);
writeb(val, socket->base + 0x800 + reg);
+ readb(socket->base + 0x800 + reg); /* PCI write posting... */
}
static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
@@ -143,6 +145,10 @@ static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
debug("%p %04x %04x\n", socket, reg, val);
writeb(val, socket->base + 0x800 + reg);
writeb(val >> 8, socket->base + 0x800 + reg + 1);
+
+ /* PCI write posting... */
+ readb(socket->base + 0x800 + reg);
+ readb(socket->base + 0x800 + reg + 1);
}
/*
@@ -553,12 +559,6 @@ static void yenta_interrogate(struct yenta_socket *socket)
static int yenta_sock_init(struct pcmcia_socket *sock)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
- u16 bridge;
-
- bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR;
- if (!socket->cb_irq)
- bridge |= CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge);
exca_writeb(socket, I365_GBLCTL, 0x00);
exca_writeb(socket, I365_GENCTL, 0x00);
@@ -667,7 +667,7 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res,
return 0;
}
-static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
+static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
{
struct resource *root, *res;
struct pci_bus_region region;
@@ -676,7 +676,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
/* Already allocated? */
if (res->parent)
- return;
+ return 0;
/* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
mask = ~0xfff;
@@ -692,7 +692,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
pcibios_bus_to_resource(socket->dev, res, &region);
root = pci_find_parent_resource(socket->dev, res);
if (root && (request_resource(root, res) == 0))
- return;
+ return 0;
printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",
pci_name(socket->dev), nr);
}
@@ -700,35 +700,27 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
if (type & IORESOURCE_IO) {
if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) ||
(yenta_search_res(socket, res, BRIDGE_IO_ACC)) ||
- (yenta_search_res(socket, res, BRIDGE_IO_MIN))) {
- config_writel(socket, addr_start, res->start);
- config_writel(socket, addr_end, res->end);
- return;
- }
+ (yenta_search_res(socket, res, BRIDGE_IO_MIN)))
+ return 1;
} else {
if (type & IORESOURCE_PREFETCH) {
if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
(yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
- (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
- config_writel(socket, addr_start, res->start);
- config_writel(socket, addr_end, res->end);
- return;
- }
+ (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+ return 1;
/* Approximating prefetchable by non-prefetchable */
res->flags = IORESOURCE_MEM;
}
if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
(yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
- (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
- config_writel(socket, addr_start, res->start);
- config_writel(socket, addr_end, res->end);
- return;
- }
+ (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+ return 1;
}
printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
pci_name(socket->dev), type);
res->start = res->end = res->flags = 0;
+ return 0;
}
/*
@@ -736,14 +728,17 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
*/
static void yenta_allocate_resources(struct yenta_socket *socket)
{
- yenta_allocate_res(socket, 0, IORESOURCE_IO,
+ int program = 0;
+ program += yenta_allocate_res(socket, 0, IORESOURCE_IO,
PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0);
- yenta_allocate_res(socket, 1, IORESOURCE_IO,
+ program += yenta_allocate_res(socket, 1, IORESOURCE_IO,
PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1);
- yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
+ program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0);
- yenta_allocate_res(socket, 3, IORESOURCE_MEM,
+ program += yenta_allocate_res(socket, 3, IORESOURCE_MEM,
PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1);
+ if (program)
+ pci_setup_cardbus(socket->dev->subordinate);
}
@@ -758,7 +753,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;
if (res->start != 0 && res->end != 0)
release_resource(res);
- res->start = res->end = 0;
+ res->start = res->end = res->flags = 0;
}
}
@@ -818,6 +813,7 @@ enum {
CARDBUS_TYPE_TOPIC95,
CARDBUS_TYPE_TOPIC97,
CARDBUS_TYPE_O2MICRO,
+ CARDBUS_TYPE_ENE,
};
/*
@@ -864,6 +860,12 @@ static struct cardbus_type cardbus_type[] = {
.override = o2micro_override,
.restore_state = o2micro_restore_state,
},
+ [CARDBUS_TYPE_ENE] = {
+ .override = ene_override,
+ .save_state = ti_save_state,
+ .restore_state = ti_restore_state,
+ .sock_init = ti_init,
+ },
};
@@ -882,16 +884,8 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
{
int i;
unsigned long val;
- u16 bridge_ctrl;
u32 mask;
- /* Set up ISA irq routing to probe the ISA irqs.. */
- bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
- if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
- bridge_ctrl |= CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
- }
-
/*
* Probe for usable interrupts using the force
* register to generate bogus card status events.
@@ -913,9 +907,6 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
mask = probe_irq_mask(val) & 0xffff;
- bridge_ctrl &= ~CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-
return mask;
}
@@ -943,18 +934,11 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *re
/* probes the PCI interrupt, use only on override functions */
static int yenta_probe_cb_irq(struct yenta_socket *socket)
{
- u16 bridge_ctrl;
-
if (!socket->cb_irq)
return -1;
socket->probe_status = 0;
- /* disable ISA interrupts */
- bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
- bridge_ctrl &= ~CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-
if (request_irq(socket->cb_irq, yenta_probe_handler, SA_SHIRQ, "yenta", socket)) {
printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n");
return -1;
@@ -965,7 +949,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
cb_writel(socket, CB_SOCKET_EVENT, -1);
cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
-
+
msleep(100);
/* disable interrupts */
@@ -1003,11 +987,12 @@ static void yenta_config_init(struct yenta_socket *socket)
{
u16 bridge;
struct pci_dev *dev = socket->dev;
+ struct pci_bus_region region;
- pci_set_power_state(socket->dev, 0);
+ pcibios_resource_to_bus(socket->dev, &region, &dev->resource[0]);
config_writel(socket, CB_LEGACY_MODE_BASE, 0);
- config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start);
+ config_writel(socket, PCI_BASE_ADDRESS_0, region.start);
config_writew(socket, PCI_COMMAND,
PCI_COMMAND_IO |
PCI_COMMAND_MEMORY |
@@ -1030,8 +1015,8 @@ static void yenta_config_init(struct yenta_socket *socket)
* - PCI interrupts enabled if a PCI interrupt exists..
*/
bridge = config_readw(socket, CB_BRIDGE_CONTROL);
- bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
- bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN | CB_BRIDGE_INTR;
+ bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
+ bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
config_writew(socket, CB_BRIDGE_CONTROL, bridge);
}
@@ -1044,7 +1029,18 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
{
struct yenta_socket *socket;
int ret;
-
+
+ /*
+ * If we failed to assign proper bus numbers for this cardbus
+ * controller during PCI probe, its subordinate pci_bus is NULL.
+ * Bail out if so.
+ */
+ if (!dev->subordinate) {
+ printk(KERN_ERR "Yenta: no bus associated with %s! "
+ "(try 'pci=assign-busses')\n", pci_name(dev));
+ return -ENODEV;
+ }
+
socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
if (!socket)
return -ENOMEM;
@@ -1253,10 +1249,22 @@ static struct pci_device_id yenta_table [] = {
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, TI12XX),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, TI12XX),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, TI1250),
- CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX),
+
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
+ CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH),