diff options
Diffstat (limited to 'arch/powerpc/kernel/pci-common.c')
| -rw-r--r-- | arch/powerpc/kernel/pci-common.c | 143 | 
1 files changed, 56 insertions, 87 deletions
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 905a24bb7ac..b49c72fd7f1 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -21,6 +21,7 @@  #include <linux/string.h>  #include <linux/init.h>  #include <linux/bootmem.h> +#include <linux/delay.h>  #include <linux/export.h>  #include <linux/of_address.h>  #include <linux/of_pci.h> @@ -120,6 +121,25 @@ resource_size_t pcibios_window_alignment(struct pci_bus *bus,  	return 1;  } +void pcibios_reset_secondary_bus(struct pci_dev *dev) +{ +	u16 ctrl; + +	if (ppc_md.pcibios_reset_secondary_bus) { +		ppc_md.pcibios_reset_secondary_bus(dev); +		return; +	} + +	pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl); +	ctrl |= PCI_BRIDGE_CTL_BUS_RESET; +	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); +	msleep(2); + +	ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; +	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); +	ssleep(1); +} +  static resource_size_t pcibios_io_size(const struct pci_controller *hose)  {  #ifdef CONFIG_PPC64 @@ -201,26 +221,6 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)  	return NULL;  } -static ssize_t pci_show_devspec(struct device *dev, -		struct device_attribute *attr, char *buf) -{ -	struct pci_dev *pdev; -	struct device_node *np; - -	pdev = to_pci_dev (dev); -	np = pci_device_to_OF_node(pdev); -	if (np == NULL || np->full_name == NULL) -		return 0; -	return sprintf(buf, "%s", np->full_name); -} -static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); - -/* Add sysfs properties */ -int pcibios_add_platform_entries(struct pci_dev *pdev) -{ -	return device_create_file(&pdev->dev, &dev_attr_devspec); -} -  /*   * Reads the interrupt pin to determine if interrupt is use by card.   * If the interrupt is used, then gets the interrupt line from the @@ -228,7 +228,7 @@ int pcibios_add_platform_entries(struct pci_dev *pdev)   */  static int pci_read_irq_line(struct pci_dev *pci_dev)  { -	struct of_irq oirq; +	struct of_phandle_args oirq;  	unsigned int virq;  	pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev)); @@ -237,7 +237,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)  	memset(&oirq, 0xff, sizeof(oirq));  #endif  	/* Try to get a mapping from the device-tree */ -	if (of_irq_map_pci(pci_dev, &oirq)) { +	if (of_irq_parse_pci(pci_dev, &oirq)) {  		u8 line, pin;  		/* If that fails, lets fallback to what is in the config @@ -263,11 +263,10 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)  			irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);  	} else {  		pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", -			 oirq.size, oirq.specifier[0], oirq.specifier[1], -			 of_node_full_name(oirq.controller)); +			 oirq.args_count, oirq.args[0], oirq.args[1], +			 of_node_full_name(oirq.np)); -		virq = irq_create_of_mapping(oirq.controller, oirq.specifier, -					     oirq.size); +		virq = irq_create_of_mapping(&oirq);  	}  	if(virq == NO_IRQ) {  		pr_debug(" Failed to map !\n"); @@ -667,60 +666,36 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,  void pci_process_bridge_OF_ranges(struct pci_controller *hose,  				  struct device_node *dev, int primary)  { -	const __be32 *ranges; -	int rlen; -	int pna = of_n_addr_cells(dev); -	int np = pna + 5;  	int memno = 0; -	u32 pci_space; -	unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;  	struct resource *res; +	struct of_pci_range range; +	struct of_pci_range_parser parser;  	printk(KERN_INFO "PCI host bridge %s %s ranges:\n",  	       dev->full_name, primary ? "(primary)" : ""); -	/* Get ranges property */ -	ranges = of_get_property(dev, "ranges", &rlen); -	if (ranges == NULL) +	/* Check for ranges property */ +	if (of_pci_range_parser_init(&parser, dev))  		return;  	/* Parse it */ -	while ((rlen -= np * 4) >= 0) { -		/* Read next ranges element */ -		pci_space = of_read_number(ranges, 1); -		pci_addr = of_read_number(ranges + 1, 2); -		cpu_addr = of_translate_address(dev, ranges + 3); -		size = of_read_number(ranges + pna + 3, 2); -		ranges += np; - +	for_each_of_pci_range(&parser, &range) {  		/* If we failed translation or got a zero-sized region  		 * (some FW try to feed us with non sensical zero sized regions  		 * such as power3 which look like some kind of attempt at exposing  		 * the VGA memory hole)  		 */ -		if (cpu_addr == OF_BAD_ADDR || size == 0) +		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)  			continue; -		/* Now consume following elements while they are contiguous */ -		for (; rlen >= np * sizeof(u32); -		     ranges += np, rlen -= np * 4) { -			if (of_read_number(ranges, 1) != pci_space) -				break; -			pci_next = of_read_number(ranges + 1, 2); -			cpu_next = of_translate_address(dev, ranges + 3); -			if (pci_next != pci_addr + size || -			    cpu_next != cpu_addr + size) -				break; -			size += of_read_number(ranges + pna + 3, 2); -		} -  		/* Act based on address space type */  		res = NULL; -		switch ((pci_space >> 24) & 0x3) { -		case 1:		/* PCI IO space */ +		switch (range.flags & IORESOURCE_TYPE_BITS) { +		case IORESOURCE_IO:  			printk(KERN_INFO  			       "  IO 0x%016llx..0x%016llx -> 0x%016llx\n", -			       cpu_addr, cpu_addr + size - 1, pci_addr); +			       range.cpu_addr, range.cpu_addr + range.size - 1, +			       range.pci_addr);  			/* We support only one IO range */  			if (hose->pci_io_size) { @@ -730,11 +705,12 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,  			}  #ifdef CONFIG_PPC32  			/* On 32 bits, limit I/O space to 16MB */ -			if (size > 0x01000000) -				size = 0x01000000; +			if (range.size > 0x01000000) +				range.size = 0x01000000;  			/* 32 bits needs to map IOs here */ -			hose->io_base_virt = ioremap(cpu_addr, size); +			hose->io_base_virt = ioremap(range.cpu_addr, +						range.size);  			/* Expect trouble if pci_addr is not 0 */  			if (primary) @@ -744,20 +720,20 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,  			/* pci_io_size and io_base_phys always represent IO  			 * space starting at 0 so we factor in pci_addr  			 */ -			hose->pci_io_size = pci_addr + size; -			hose->io_base_phys = cpu_addr - pci_addr; +			hose->pci_io_size = range.pci_addr + range.size; +			hose->io_base_phys = range.cpu_addr - range.pci_addr;  			/* Build resource */  			res = &hose->io_resource; -			res->flags = IORESOURCE_IO; -			res->start = pci_addr; +			range.cpu_addr = range.pci_addr;  			break; -		case 2:		/* PCI Memory space */ -		case 3:		/* PCI 64 bits Memory space */ +		case IORESOURCE_MEM:  			printk(KERN_INFO  			       " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n", -			       cpu_addr, cpu_addr + size - 1, pci_addr, -			       (pci_space & 0x40000000) ? "Prefetch" : ""); +			       range.cpu_addr, range.cpu_addr + range.size - 1, +			       range.pci_addr, +			       (range.pci_space & 0x40000000) ? +			       "Prefetch" : "");  			/* We support only 3 memory ranges */  			if (memno >= 3) { @@ -766,28 +742,21 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,  				continue;  			}  			/* Handles ISA memory hole space here */ -			if (pci_addr == 0) { +			if (range.pci_addr == 0) {  				if (primary || isa_mem_base == 0) -					isa_mem_base = cpu_addr; -				hose->isa_mem_phys = cpu_addr; -				hose->isa_mem_size = size; +					isa_mem_base = range.cpu_addr; +				hose->isa_mem_phys = range.cpu_addr; +				hose->isa_mem_size = range.size;  			}  			/* Build resource */ -			hose->mem_offset[memno] = cpu_addr - pci_addr; +			hose->mem_offset[memno] = range.cpu_addr - +							range.pci_addr;  			res = &hose->mem_resources[memno++]; -			res->flags = IORESOURCE_MEM; -			if (pci_space & 0x40000000) -				res->flags |= IORESOURCE_PREFETCH; -			res->start = cpu_addr;  			break;  		}  		if (res != NULL) { -			res->name = dev->full_name; -			res->end = res->start + size - 1; -			res->parent = NULL; -			res->sibling = NULL; -			res->child = NULL; +			of_pci_range_to_resource(&range, dev, res);  		}  	}  } @@ -836,7 +805,7 @@ static void pcibios_fixup_resources(struct pci_dev *dev)  		 * at 0 as unset as well, except if PCI_PROBE_ONLY is also set  		 * since in that case, we don't want to re-assign anything  		 */ -		pcibios_resource_to_bus(dev, ®, res); +		pcibios_resource_to_bus(dev->bus, ®, res);  		if (pci_has_flag(PCI_REASSIGN_ALL_RSRC) ||  		    (reg.start == 0 && !pci_has_flag(PCI_PROBE_ONLY))) {  			/* Only print message if not re-assigning */ @@ -887,7 +856,7 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus,  	/* Job is a bit different between memory and IO */  	if (res->flags & IORESOURCE_MEM) { -		pcibios_resource_to_bus(dev, ®ion, res); +		pcibios_resource_to_bus(dev->bus, ®ion, res);  		/* If the BAR is non-0 then it's probably been initialized */  		if (region.start != 0)  | 
