From d0e3db40e2a1352aa2a2f425a7d4631bddc03d51 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 11 Mar 2009 15:46:14 +0900 Subject: sh: add init member to pci_channel data This patch adds an init callback to struct pci_channel and makes sure it is initialized properly. Code is added to call this init function from pcibios_init(). Return values are adjusted and a warning is is printed if init fails. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 0d6ac7a1db49..29ec16e69afa 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -28,18 +28,31 @@ static int __init pcibios_init(void) struct pci_bus *bus; int busno; + /* init channels */ + busno = 0; + for (p = board_pci_channels; p->init; p++) { + if (p->init(p) == 0) + p->enabled = 1; + else + pr_err("Unable to init pci channel %d\n", busno); + busno++; + } + #ifdef CONFIG_PCI_AUTO /* assign resources */ busno = 0; - for (p = board_pci_channels; p->pci_ops != NULL; p++) - busno = pciauto_assign_resources(busno, p) + 1; + for (p = board_pci_channels; p->init; p++) + if (p->enabled) + busno = pciauto_assign_resources(busno, p) + 1; #endif /* scan the buses */ busno = 0; - for (p = board_pci_channels; p->pci_ops != NULL; p++) { - bus = pci_scan_bus(busno, p->pci_ops, p); - busno = bus->subordinate + 1; + for (p = board_pci_channels; p->init; p++) { + if (p->enabled) { + bus = pci_scan_bus(busno, p->pci_ops, p); + busno = bus->subordinate + 1; + } } pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq); -- cgit v1.2.3 From ef339f241b08a16af58897e6288ba200e0c7a8c7 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 19 Feb 2008 21:35:22 +0900 Subject: sh: pci memory range checking code This patch changes the code to use __is_pci_memory() instead of is_pci_memaddr(). __is_pci_memory() loops through all the pci channels on the system to match memory windows. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 29ec16e69afa..b9aca5478048 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -167,9 +167,8 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) /* * Presently the IORESOURCE_MEM case is a bit special, most * SH7751 style PCI controllers have PCI memory at a fixed - * location in the address space where no remapping is desired - * (typically at 0xfd000000, but is_pci_memaddr() will know - * best). With the IORESOURCE_MEM case more care has to be taken + * location in the address space where no remapping is desired. + * With the IORESOURCE_MEM case more care has to be taken * to inhibit page table mapping for legacy cores, but this is * punted off to __ioremap(). * -- PFM. -- cgit v1.2.3 From aa5d3ff99cc1f3dfe262ab9dd9179131fcfe39fd Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 19 Feb 2008 21:35:40 +0900 Subject: sh: export board_pci_channels in one place Instead of sometimes exporting board_pci_channels[] in the board specific code just export it in one place. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index b9aca5478048..8aaacc99b710 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -187,3 +187,5 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *addr) iounmap(addr); } EXPORT_SYMBOL(pci_iounmap); + +EXPORT_SYMBOL(board_pci_channels); -- cgit v1.2.3 From 9ade1217c9ba39ad2f004a898ddfbb815fd5fe74 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 20 Apr 2009 15:38:25 +0900 Subject: sh: pci: Drop asm-generic/pci.h, so we can use our own fixups. The new PCI code wants its own bus<->resource mappings instead of the generic equivalents, so drop the asm-generic include in preparation. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 8aaacc99b710..6d659cd93c9d 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -72,6 +72,20 @@ void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus) pci_read_bridge_bases(bus); } +void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) +{ + region->start = res->start; + region->end = res->end; +} + +void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + res->start = region->start; + res->end = region->end; +} + void pcibios_align_resource(void *data, struct resource *res, resource_size_t size, resource_size_t align) __attribute__ ((weak)); -- cgit v1.2.3 From a3c0e0d0032d5bbfd7dc04827a257c717d432a5b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 20 Apr 2009 16:14:29 +0900 Subject: sh: pci: Consolidate pcibios_align_resource() definitions. This introduces a saner pcibios_align_resource() that can be used regardless of whether pci-auto or pci-new are being used, and consolidates it in pci-lib.c. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 6d659cd93c9d..f670988e033d 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -86,29 +86,6 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, res->end = region->end; } -void pcibios_align_resource(void *data, struct resource *res, - resource_size_t size, resource_size_t align) - __attribute__ ((weak)); - -/* - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - */ -void pcibios_align_resource(void *data, struct resource *res, - resource_size_t size, resource_size_t align) -{ - if (res->flags & IORESOURCE_IO) { - resource_size_t start = res->start; - - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} - int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; -- cgit v1.2.3 From 0bb34a6bf1f71d5ad2abfda582a2c2794957bc7b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 20 Apr 2009 16:38:00 +0900 Subject: sh: pci: Consolidate pci_iomap() and use the generic I/O base. This consolidates the pci_iomap() definitions and reworks how the I/O port base is handled. PCI channels can register their own I/O map base, or if none is provided, the system-wide generic I/O base is used instead. Functionally nothing changes, while this allows us to kill off lots of I/O address special casing and lookups. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index f670988e033d..d39f24091ade 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -144,39 +144,4 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) -{ - resource_size_t start = pci_resource_start(dev, bar); - resource_size_t len = pci_resource_len(dev, bar); - unsigned long flags = pci_resource_flags(dev, bar); - - if (unlikely(!len || !start)) - return NULL; - if (maxlen && len > maxlen) - len = maxlen; - - /* - * Presently the IORESOURCE_MEM case is a bit special, most - * SH7751 style PCI controllers have PCI memory at a fixed - * location in the address space where no remapping is desired. - * With the IORESOURCE_MEM case more care has to be taken - * to inhibit page table mapping for legacy cores, but this is - * punted off to __ioremap(). - * -- PFM. - */ - if (flags & IORESOURCE_IO) - return ioport_map(start, len); - if (flags & IORESOURCE_MEM) - return ioremap(start, len); - - return NULL; -} -EXPORT_SYMBOL(pci_iomap); - -void pci_iounmap(struct pci_dev *dev, void __iomem *addr) -{ - iounmap(addr); -} -EXPORT_SYMBOL(pci_iounmap); - EXPORT_SYMBOL(board_pci_channels); -- cgit v1.2.3 From 5160d3f782a5e0cdb3bdaa8a891a1fb9d9ab83ec Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 20 Apr 2009 18:47:21 +0900 Subject: sh: pci: Consolidate bus<->resource mapping in pci-lib. Now that the io and mem offsets are tracked accordingly, the pci-new version of the bus<->resource mappers can be used generically. This moves them in to pci-lib. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index d39f24091ade..c15a6f0ad500 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -72,20 +72,6 @@ void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus) pci_read_bridge_bases(bus); } -void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, - struct resource *res) -{ - region->start = res->start; - region->end = res->end; -} - -void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, - struct pci_bus_region *region) -{ - res->start = region->start; - res->end = region->end; -} - int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; -- cgit v1.2.3 From 3f8daeacd7ed7a502daf0998e2515cea4f467f21 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 20 Apr 2009 18:53:41 +0900 Subject: sh: pci: Consolidate the remaining common bits. This moves the remaining common bits in to pci-lib. Thereby reducing pci.c/pci-new.c to simple bus fixups and controller registration. As more platforms are moved over, the old code will disappear completely and the pci-new bits will be rolled in to pci-lib, eventually replacing pci.c completely. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 58 ----------------------------------------------- 1 file changed, 58 deletions(-) (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index c15a6f0ad500..8c332b2a4641 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -72,62 +72,4 @@ void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus) pci_read_bridge_bases(bus); } -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for(idx=0; idx<6; idx++) { - if (!(mask & (1 << idx))) - continue; - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because " - "of resource collisions\n", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", - pci_name(dev), old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -/* - * If we set up a device for bus mastering, we need to check and set - * the latency timer as it may not be properly set. - */ -static unsigned int pcibios_max_latency = 255; - -void pcibios_set_master(struct pci_dev *dev) -{ - u8 lat; - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - else - return; - printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", - pci_name(dev), lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} - EXPORT_SYMBOL(board_pci_channels); -- cgit v1.2.3 From 805fcc88999162b361ef0b0ce25782ef65f147d7 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 20 Apr 2009 21:46:42 +0900 Subject: sh: pci: Kill off the last remnants of the now unused pci-auto code. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 75 ----------------------------------------------- 1 file changed, 75 deletions(-) delete mode 100644 arch/sh/drivers/pci/pci.c (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c deleted file mode 100644 index 8c332b2a4641..000000000000 --- a/arch/sh/drivers/pci/pci.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * arch/sh/drivers/pci/pci.c - * - * Copyright (c) 2002 M. R. Brown - * Copyright (c) 2004 - 2006 Paul Mundt - * - * These functions are collected here to reduce duplication of common - * code amongst the many platform-specific PCI support code files. - * - * These routines require the following board-specific routines: - * void pcibios_fixup_irqs(); - * - * See include/asm-sh/pci.h for more information. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include - -static int __init pcibios_init(void) -{ - struct pci_channel *p; - struct pci_bus *bus; - int busno; - - /* init channels */ - busno = 0; - for (p = board_pci_channels; p->init; p++) { - if (p->init(p) == 0) - p->enabled = 1; - else - pr_err("Unable to init pci channel %d\n", busno); - busno++; - } - -#ifdef CONFIG_PCI_AUTO - /* assign resources */ - busno = 0; - for (p = board_pci_channels; p->init; p++) - if (p->enabled) - busno = pciauto_assign_resources(busno, p) + 1; -#endif - - /* scan the buses */ - busno = 0; - for (p = board_pci_channels; p->init; p++) { - if (p->enabled) { - bus = pci_scan_bus(busno, p->pci_ops, p); - busno = bus->subordinate + 1; - } - } - - pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq); - - dma_debug_add_bus(&pci_bus_type); - - return 0; -} -subsys_initcall(pcibios_init); - -/* - * Called after each bus is probed, but before its children - * are examined. - */ -void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus) -{ - pci_read_bridge_bases(bus); -} - -EXPORT_SYMBOL(board_pci_channels); -- cgit v1.2.3 From cf242007a1eb29dcf93d1cb34713ec9b3f4a0e1b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 20 Apr 2009 21:53:33 +0900 Subject: sh: pci: Rename pci-new.c to pci.c. pci-new.c is now in a state to replace the old pci.c, rename it accordingly. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 364 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 arch/sh/drivers/pci/pci.c (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c new file mode 100644 index 000000000000..54d77cbb8b39 --- /dev/null +++ b/arch/sh/drivers/pci/pci.c @@ -0,0 +1,364 @@ +/* + * New-style PCI core. + * + * Copyright (c) 2004 - 2009 Paul Mundt + * Copyright (c) 2002 M. R. Brown + * + * Modelled after arch/mips/pci/pci.c: + * Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org) + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +unsigned long PCIBIOS_MIN_IO = 0x0000; +unsigned long PCIBIOS_MIN_MEM = 0; + +/* + * The PCI controller list. + */ +static struct pci_channel *hose_head, **hose_tail = &hose_head; + +static int pci_initialized; + +static void __devinit pcibios_scanbus(struct pci_channel *hose) +{ + static int next_busno; + struct pci_bus *bus; + + bus = pci_scan_bus(next_busno, hose->pci_ops, hose); + if (bus) { + next_busno = bus->subordinate + 1; + /* Don't allow 8-bit bus number overflow inside the hose - + reserve some space for bridges. */ + if (next_busno > 224) + next_busno = 0; + + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); + pci_enable_bridges(bus); + } +} + +static DEFINE_MUTEX(pci_scan_mutex); + +void __devinit register_pci_controller(struct pci_channel *hose) +{ + if (request_resource(&iomem_resource, hose->mem_resource) < 0) + goto out; + if (request_resource(&ioport_resource, hose->io_resource) < 0) { + release_resource(hose->mem_resource); + goto out; + } + + *hose_tail = hose; + hose_tail = &hose->next; + + /* + * Do not panic here but later - this might hapen before console init. + */ + if (!hose->io_map_base) { + printk(KERN_WARNING + "registering PCI controller with io_map_base unset\n"); + } + + /* + * Scan the bus if it is register after the PCI subsystem + * initialization. + */ + if (pci_initialized) { + mutex_lock(&pci_scan_mutex); + pcibios_scanbus(hose); + mutex_unlock(&pci_scan_mutex); + } + + return; + +out: + printk(KERN_WARNING + "Skipping PCI bus scan due to resource conflict\n"); +} + +static int __init pcibios_init(void) +{ + struct pci_channel *hose; + + /* Scan all of the recorded PCI controllers. */ + for (hose = hose_head; hose; hose = hose->next) + pcibios_scanbus(hose); + + pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq); + + dma_debug_add_bus(&pci_bus_type); + + pci_initialized = 1; + + return 0; +} +subsys_initcall(pcibios_init); + +static void pcibios_fixup_device_resources(struct pci_dev *dev, + struct pci_bus *bus) +{ + /* Update device resources. */ + struct pci_channel *hose = bus->sysdata; + unsigned long offset = 0; + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + if (!dev->resource[i].start) + continue; + if (dev->resource[i].flags & IORESOURCE_PCI_FIXED) + continue; + if (dev->resource[i].flags & IORESOURCE_IO) + offset = hose->io_offset; + else if (dev->resource[i].flags & IORESOURCE_MEM) + offset = hose->mem_offset; + + dev->resource[i].start += offset; + dev->resource[i].end += offset; + } +} + +/* + * Called after each bus is probed, but before its children + * are examined. + */ +void __devinit pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_dev *dev = bus->self; + struct list_head *ln; + struct pci_channel *chan = bus->sysdata; + + if (!dev) { + bus->resource[0] = chan->io_resource; + bus->resource[1] = chan->mem_resource; + } + + for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { + dev = pci_dev_b(ln); + + if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) + pcibios_fixup_device_resources(dev, bus); + } +} + +/* + * We need to avoid collisions with `mirrored' VGA ports + * and other strange ISA hardware, so we always want the + * addresses to be allocated in the 0x000-0x0ff region + * modulo 0x400. + */ +void pcibios_align_resource(void *data, struct resource *res, + resource_size_t size, resource_size_t align) +{ + struct pci_dev *dev = data; + struct pci_channel *chan = dev->sysdata; + resource_size_t start = res->start; + + if (res->flags & IORESOURCE_IO) { + if (start < PCIBIOS_MIN_IO + chan->io_resource->start) + start = PCIBIOS_MIN_IO + chan->io_resource->start; + + /* + * Put everything into 0x00-0xff region modulo 0x400. + */ + if (start & 0x300) { + start = (start + 0x3ff) & ~0x3ff; + res->start = start; + } + } else if (res->flags & IORESOURCE_MEM) { + if (start < PCIBIOS_MIN_MEM + chan->mem_resource->start) + start = PCIBIOS_MIN_MEM + chan->mem_resource->start; + } + + res->start = start; +} + +void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) +{ + struct pci_channel *hose = dev->sysdata; + unsigned long offset = 0; + + if (res->flags & IORESOURCE_IO) + offset = hose->io_offset; + else if (res->flags & IORESOURCE_MEM) + offset = hose->mem_offset; + + region->start = res->start - offset; + region->end = res->end - offset; +} + +void __devinit +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + struct pci_channel *hose = dev->sysdata; + unsigned long offset = 0; + + if (res->flags & IORESOURCE_IO) + offset = hose->io_offset; + else if (res->flags & IORESOURCE_MEM) + offset = hose->mem_offset; + + res->start = region->start + offset; + res->end = region->end + offset; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx=0; idx < PCI_NUM_RESOURCES; idx++) { + /* Only set up the requested stuff */ + if (!(mask & (1<resource[idx]; + if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) + continue; + if ((idx == PCI_ROM_RESOURCE) && + (!(r->flags & IORESOURCE_ROM_ENABLE))) + continue; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available " + "because of resource collisions\n", + pci_name(dev)); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", + pci_name(dev), old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +/* + * If we set up a device for bus mastering, we need to check and set + * the latency timer as it may not be properly set. + */ +static unsigned int pcibios_max_latency = 255; + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", + pci_name(dev), lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} + +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + +char * __devinit pcibios_setup(char *str) +{ + return str; +} + +int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, int write_combine) +{ + /* + * I/O space can be accessed via normal processor loads and stores on + * this platform but for now we elect not to do this and portable + * drivers should not do this anyway. + */ + if (mmap_state == pci_mmap_io) + return -EINVAL; + + /* + * Ignore write-combine; for now only return uncached mappings. + */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); +} + +static void __iomem *ioport_map_pci(struct pci_dev *dev, + unsigned long port, unsigned int nr) +{ + struct pci_channel *chan = dev->sysdata; + + if (!chan->io_map_base) + chan->io_map_base = generic_io_base; + + return (void __iomem *)(chan->io_map_base + port); +} + +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +{ + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); + unsigned long flags = pci_resource_flags(dev, bar); + + if (unlikely(!len || !start)) + return NULL; + if (maxlen && len > maxlen) + len = maxlen; + + if (flags & IORESOURCE_IO) + return ioport_map_pci(dev, start, len); + + /* + * Presently the IORESOURCE_MEM case is a bit special, most + * SH7751 style PCI controllers have PCI memory at a fixed + * location in the address space where no remapping is desired. + * With the IORESOURCE_MEM case more care has to be taken + * to inhibit page table mapping for legacy cores, but this is + * punted off to __ioremap(). + * -- PFM. + */ + if (flags & IORESOURCE_MEM) { + if (flags & IORESOURCE_CACHEABLE) + return ioremap(start, len); + + return ioremap_nocache(start, len); + } + + return NULL; +} +EXPORT_SYMBOL(pci_iomap); + +void pci_iounmap(struct pci_dev *dev, void __iomem *addr) +{ + iounmap(addr); +} +EXPORT_SYMBOL(pci_iounmap); + +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pcibios_resource_to_bus); +EXPORT_SYMBOL(pcibios_bus_to_resource); +EXPORT_SYMBOL(PCIBIOS_MIN_IO); +EXPORT_SYMBOL(PCIBIOS_MIN_MEM); +#endif -- cgit v1.2.3 From 8c6b44d00aca45edf69b35220ba4dce962c482f8 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 16 Jun 2009 06:01:58 +0900 Subject: sh: pci: Allow register_pci_controller() to handle overlapping regions. Some host controllers (such as SH7786) have overlapping regions that are fixed in hardware. The resource allocator does the right thing in managing this space already, so the conflict case is non-fatal. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'arch/sh/drivers/pci/pci.c') diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 54d77cbb8b39..9a1c423ad167 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -53,12 +53,8 @@ static DEFINE_MUTEX(pci_scan_mutex); void __devinit register_pci_controller(struct pci_channel *hose) { - if (request_resource(&iomem_resource, hose->mem_resource) < 0) - goto out; - if (request_resource(&ioport_resource, hose->io_resource) < 0) { - release_resource(hose->mem_resource); - goto out; - } + request_resource(&iomem_resource, hose->mem_resource); + request_resource(&ioport_resource, hose->io_resource); *hose_tail = hose; hose_tail = &hose->next; @@ -80,12 +76,6 @@ void __devinit register_pci_controller(struct pci_channel *hose) pcibios_scanbus(hose); mutex_unlock(&pci_scan_mutex); } - - return; - -out: - printk(KERN_WARNING - "Skipping PCI bus scan due to resource conflict\n"); } static int __init pcibios_init(void) -- cgit v1.2.3