diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/au1000_generic.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/cistpl.c | 51 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 6 | ||||
-rw-r--r-- | drivers/pcmcia/o2micro.h | 34 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 3 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_base.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_mainstone.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_sharpsl.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/sa1100_generic.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/sa1100_jornada720.c | 19 | ||||
-rw-r--r-- | drivers/pcmcia/sa1111_generic.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/sa11xx_base.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 169 |
13 files changed, 183 insertions, 112 deletions
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index 0a5c95807cf2..470ef756252e 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -388,6 +388,7 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i); memset(skt, 0, sizeof(*skt)); + skt->socket.resource_ops = &pccard_static_ops; skt->socket.ops = &au1x00_pcmcia_operations; skt->socket.owner = ops->owner; skt->socket.dev.dev = dev; diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index dd7651ff5b43..3afb682255a0 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -88,31 +88,38 @@ EXPORT_SYMBOL(release_cis_mem); static void __iomem * set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags) { - pccard_mem_map *mem = &s->cis_mem; - int ret; + pccard_mem_map *mem = &s->cis_mem; + int ret; + + if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) { + mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s); + if (mem->res == NULL) { + printk(KERN_NOTICE "cs: unable to map card memory!\n"); + return NULL; + } + s->cis_virt = NULL; + } - if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) { - mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s); - if (mem->res == NULL) { - printk(KERN_NOTICE "cs: unable to map card memory!\n"); - return NULL; + if (!(s->features & SS_CAP_STATIC_MAP) && (!s->cis_virt)) + s->cis_virt = ioremap(mem->res->start, s->map_size); + + mem->card_start = card_offset; + mem->flags = flags; + + ret = s->ops->set_mem_map(s, mem); + if (ret) { + iounmap(s->cis_virt); + s->cis_virt = NULL; + return NULL; } - s->cis_virt = ioremap(mem->res->start, s->map_size); - } - mem->card_start = card_offset; - mem->flags = flags; - ret = s->ops->set_mem_map(s, mem); - if (ret) { - iounmap(s->cis_virt); - return NULL; - } - if (s->features & SS_CAP_STATIC_MAP) { - if (s->cis_virt) - iounmap(s->cis_virt); - s->cis_virt = ioremap(mem->static_start, s->map_size); - } - return s->cis_virt; + if (s->features & SS_CAP_STATIC_MAP) { + if (s->cis_virt) + iounmap(s->cis_virt); + s->cis_virt = ioremap(mem->static_start, s->map_size); + } + + return s->cis_virt; } /*====================================================================== diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 3e3c6f12bbe6..43da2e92d50f 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -206,8 +206,8 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv) u32 hash; if (!p_drv->attach || !p_drv->event || !p_drv->detach) - printk(KERN_DEBUG "pcmcia: %s does misses a callback function", - p_drv->drv.name); + printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback " + "function\n", p_drv->drv.name); while (did && did->match_flags) { for (i=0; i<4; i++) { @@ -589,8 +589,8 @@ static void pcmcia_delayed_add_pseudo_device(void *data) static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) { if (!s->pcmcia_state.device_add_pending) { - schedule_work(&s->device_add); s->pcmcia_state.device_add_pending = 1; + schedule_work(&s->device_add); } return; } diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h index b1f6e3d9ee06..a234ce1967a3 100644 --- a/drivers/pcmcia/o2micro.h +++ b/drivers/pcmcia/o2micro.h @@ -120,11 +120,16 @@ #define O2_MODE_E_LED_OUT 0x08 #define O2_MODE_E_SKTA_ACTV 0x10 +#define O2_RESERVED1 0x94 +#define O2_RESERVED2 0xD4 +#define O2_RES_READ_PREFETCH 0x02 +#define O2_RES_WRITE_BURST 0x08 + static int o2micro_override(struct yenta_socket *socket) { /* - * 'reserved' register at 0x94/D4. chaning it to 0xCA (8 bit) enables - * read prefetching which for example makes the RME Hammerfall DSP + * 'reserved' register at 0x94/D4. allows setting read prefetch and write + * bursting. read prefetching for example makes the RME Hammerfall DSP * working. for some bridges it is at 0x94, for others at 0xD4. it's * ok to write to both registers on all O2 bridges. * from Eric Still, 02Micro. @@ -132,20 +137,35 @@ static int o2micro_override(struct yenta_socket *socket) u8 a, b; if (PCI_FUNC(socket->dev->devfn) == 0) { - a = config_readb(socket, 0x94); - b = config_readb(socket, 0xD4); + a = config_readb(socket, O2_RESERVED1); + b = config_readb(socket, O2_RESERVED2); printk(KERN_INFO "Yenta O2: res at 0x94/0xD4: %02x/%02x\n", a, b); switch (socket->dev->device) { + /* + * older bridges have problems with both read prefetch and write + * bursting depending on the combination of the chipset, bridge + * and the cardbus card. so disable them to be on the safe side. + */ + case PCI_DEVICE_ID_O2_6729: + case PCI_DEVICE_ID_O2_6730: + case PCI_DEVICE_ID_O2_6812: case PCI_DEVICE_ID_O2_6832: - printk(KERN_INFO "Yenta O2: old bridge, not enabling read prefetch / write burst\n"); + case PCI_DEVICE_ID_O2_6836: + printk(KERN_INFO "Yenta O2: old bridge, disabling read prefetch/write burst\n"); + config_writeb(socket, O2_RESERVED1, + a & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST)); + config_writeb(socket, O2_RESERVED2, + b & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST)); break; default: printk(KERN_INFO "Yenta O2: enabling read prefetch/write burst\n"); - config_writeb(socket, 0x94, a | 0x0a); - config_writeb(socket, 0xD4, b | 0x0a); + config_writeb(socket, O2_RESERVED1, + a | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST); + config_writeb(socket, O2_RESERVED2, + b | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST); } } diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 184f4f88b2a0..599b116d9747 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -41,6 +41,7 @@ module_param(io_speed, int, 0444); #ifdef CONFIG_PCMCIA_PROBE +#include <asm/irq.h> /* mask of IRQs already reserved by other cards, we should avoid using them */ static u8 pcmcia_used_irq[NR_IRQS]; #endif @@ -800,7 +801,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) } else { int try; u32 mask = s->irq_mask; - void *data = NULL; + void *data = &p_dev->dev.driver; /* something unique to this device */ for (try = 0; try < 64; try++) { irq = try % 32; diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 3e23cd461fb1..325c992f7d8f 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -246,7 +246,7 @@ static void __exit pxa2xx_pcmcia_exit(void) driver_unregister(&pxa2xx_pcmcia_driver); } -module_init(pxa2xx_pcmcia_init); +fs_initcall(pxa2xx_pcmcia_init); module_exit(pxa2xx_pcmcia_exit); MODULE_AUTHOR("Stefan Eletzhofer <stefan.eletzhofer@inquant.de> and Ian Molton <spyro@f2s.com>"); diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index 5309734e1687..bbe69b07ce50 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c @@ -196,7 +196,7 @@ static void __exit mst_pcmcia_exit(void) platform_device_unregister(mst_pcmcia_device); } -module_init(mst_pcmcia_init); +fs_initcall(mst_pcmcia_init); module_exit(mst_pcmcia_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index 42efe218867a..7bac2f7d8b3f 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -257,7 +257,7 @@ static void __exit sharpsl_pcmcia_exit(void) platform_device_unregister(sharpsl_pcmcia_device); } -module_init(sharpsl_pcmcia_init); +fs_initcall(sharpsl_pcmcia_init); module_exit(sharpsl_pcmcia_exit); MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support"); diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index e98bb3d80e7c..d4ed508b38be 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -126,5 +126,5 @@ MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>"); MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11x0 Socket Controller"); MODULE_LICENSE("Dual MPL/GPL"); -module_init(sa11x0_pcmcia_init); +fs_initcall(sa11x0_pcmcia_init); module_exit(sa11x0_pcmcia_exit); diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c index 0a387106acb0..7a87298bae99 100644 --- a/drivers/pcmcia/sa1100_jornada720.c +++ b/drivers/pcmcia/sa1100_jornada720.c @@ -30,20 +30,9 @@ static int jornada720_pcmcia_hw_init(struct soc_pcmcia_socket *skt) */ GRER |= 0x00000002; /* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */ - PA_DDR = 0; - PA_DWR = 0; - PA_SDR = 0; - PA_SSR = 0; - - PB_DDR = 0; - PB_DWR = 0x01; - PB_SDR = 0; - PB_SSR = 0; - - PC_DDR = 0x88; - PC_DWR = 0x20; - PC_SDR = 0; - PC_SSR = 0; + sa1111_set_io_dir(SA1111_DEV(skt->dev), GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); + sa1111_set_io(SA1111_DEV(skt->dev), GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); + sa1111_set_sleep_io(SA1111_DEV(skt->dev), GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); return sa1111_pcmcia_hw_init(skt); } @@ -95,7 +84,7 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__, unsigned long flags; local_irq_save(flags); - PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set; + sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); local_irq_restore(flags); } diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index b441f43a6a55..bb90a1448a53 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -189,7 +189,7 @@ static void __exit sa1111_drv_pcmcia_exit(void) sa1111_driver_unregister(&pcmcia_driver); } -module_init(sa1111_drv_pcmcia_init); +fs_initcall(sa1111_drv_pcmcia_init); module_exit(sa1111_drv_pcmcia_exit); MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver"); diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index db04ffb6f68c..59c5d968e9f6 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c @@ -189,7 +189,7 @@ static int __init sa11xx_pcmcia_init(void) { return 0; } -module_init(sa11xx_pcmcia_init); +fs_initcall(sa11xx_pcmcia_init); static void __exit sa11xx_pcmcia_exit(void) {} diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 0e7aa8176692..62fd705203fb 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -527,64 +527,29 @@ static int yenta_sock_suspend(struct pcmcia_socket *sock) * Use an adaptive allocation for the memory resource, * sometimes the memory behind pci bridges is limited: * 1/8 of the size of the io window of the parent. - * max 4 MB, min 16 kB. + * max 4 MB, min 16 kB. We try very hard to not get below + * the "ACC" values, though. */ #define BRIDGE_MEM_MAX 4*1024*1024 +#define BRIDGE_MEM_ACC 128*1024 #define BRIDGE_MEM_MIN 16*1024 -#define BRIDGE_IO_MAX 256 +#define BRIDGE_IO_MAX 512 +#define BRIDGE_IO_ACC 256 #define BRIDGE_IO_MIN 32 #ifndef PCIBIOS_MIN_CARDBUS_IO #define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO #endif -static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type) +static int yenta_search_one_res(struct resource *root, struct resource *res, + u32 min) { - struct pci_bus *bus; - struct resource *root, *res; - u32 start, end; - u32 align, size, min; - unsigned offset; - unsigned mask; - - res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; - /* Already allocated? */ - if (res->parent) - return 0; - - /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ - mask = ~0xfff; - if (type & IORESOURCE_IO) - mask = ~3; - - offset = 0x1c + 8*nr; - bus = socket->dev->subordinate; - res->name = bus->name; - res->flags = type; - res->start = 0; - res->end = 0; - root = pci_find_parent_resource(socket->dev, res); + u32 align, size, start, end; - if (!root) - return; - - start = config_readl(socket, offset) & mask; - end = config_readl(socket, offset+4) | ~mask; - if (start && end > start && !override_bios) { - res->start = start; - res->end = end; - if (request_resource(root, res) == 0) - return; - printk(KERN_INFO "yenta %s: Preassigned resource %d busy, reconfiguring...\n", - pci_name(socket->dev), nr); - res->start = res->end = 0; - } - - if (type & IORESOURCE_IO) { + if (res->flags & IORESOURCE_IO) { align = 1024; size = BRIDGE_IO_MAX; - min = BRIDGE_IO_MIN; start = PCIBIOS_MIN_CARDBUS_IO; end = ~0U; } else { @@ -599,26 +564,107 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ i++; size = 1 << i; } - if (size < BRIDGE_MEM_MIN) - size = BRIDGE_MEM_MIN; - min = BRIDGE_MEM_MIN; + if (size < min) + size = min; align = size; start = PCIBIOS_MIN_MEM; end = ~0U; } - + do { - if (allocate_resource(root, res, size, start, end, align, NULL, NULL)==0) { - config_writel(socket, offset, res->start); - config_writel(socket, offset+4, res->end); - return; + if (allocate_resource(root, res, size, start, end, align, + NULL, NULL)==0) { + return 1; } size = size/2; align = size; } while (size >= min); + + return 0; +} + + +static int yenta_search_res(struct yenta_socket *socket, struct resource *res, + u32 min) +{ + int i; + for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) { + struct resource * root = socket->dev->bus->resource[i]; + if (!root) + continue; + + if ((res->flags ^ root->flags) & + (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)) + continue; /* Wrong type */ + + if (yenta_search_one_res(root, res, min)) + return 1; + } + return 0; +} + +static void 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; + unsigned mask; + + res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; + /* Already allocated? */ + if (res->parent) + return; + + /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ + mask = ~0xfff; + if (type & IORESOURCE_IO) + mask = ~3; + + res->name = socket->dev->subordinate->name; + res->flags = type; + + region.start = config_readl(socket, addr_start) & mask; + region.end = config_readl(socket, addr_end) | ~mask; + if (region.start && region.end > region.start && !override_bios) { + pcibios_bus_to_resource(socket->dev, res, ®ion); + root = pci_find_parent_resource(socket->dev, res); + if (root && (request_resource(root, res) == 0)) + return; + printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n", + pci_name(socket->dev), nr); + } + + 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; + } + } 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; + } + /* 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; + } + } + printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n", - pci_name(socket->dev), type); - res->start = res->end = 0; + pci_name(socket->dev), type); + res->start = res->end = res->flags = 0; } /* @@ -626,10 +672,14 @@ 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_MEM|IORESOURCE_PREFETCH); - yenta_allocate_res(socket, 1, IORESOURCE_MEM); - yenta_allocate_res(socket, 2, IORESOURCE_IO); - yenta_allocate_res(socket, 3, IORESOURCE_IO); /* PCI isn't clever enough to use this one yet */ + yenta_allocate_res(socket, 0, IORESOURCE_IO, + PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); + 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, + PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); + yenta_allocate_res(socket, 3, IORESOURCE_MEM, + PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); } @@ -1055,6 +1105,7 @@ static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) pci_save_state(dev); pci_read_config_dword(dev, 16*4, &socket->saved_state[0]); pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); + pci_disable_device(dev); /* * Some laptops (IBM T22) do not like us putting the Cardbus @@ -1078,6 +1129,8 @@ static int yenta_dev_resume (struct pci_dev *dev) pci_restore_state(dev); pci_write_config_dword(dev, 16*4, socket->saved_state[0]); pci_write_config_dword(dev, 17*4, socket->saved_state[1]); + pci_enable_device(dev); + pci_set_master(dev); if (socket->type && socket->type->restore_state) socket->type->restore_state(socket); |