diff options
Diffstat (limited to 'drivers/pcmcia/yenta_socket.c')
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 47 |
1 files changed, 24 insertions, 23 deletions
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 0347a29f297..f0997c36c9b 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); } /* @@ -667,7 +673,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 +682,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 +698,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ pcibios_bus_to_resource(socket->dev, res, ®ion); 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 +706,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 +734,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 +759,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; } } |