Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: pci: parse memory ranges from devicetree

Implement pci_load_of_ranges on MIPS. Due to lack of test hardware only 32bit
bus width is supported. This function is based on pci_process_bridge_OF_ranges
from powerpc.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3729/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

John Crispin and committed by
Ralf Baechle
a48cf37a 3572a2c3

+61
+6
arch/mips/include/asm/pci.h
··· 17 17 */ 18 18 19 19 #include <linux/ioport.h> 20 + #include <linux/of.h> 20 21 21 22 /* 22 23 * Each pci channel is a top-level PCI bus seem by CPU. A machine with ··· 27 26 struct pci_controller { 28 27 struct pci_controller *next; 29 28 struct pci_bus *bus; 29 + struct device_node *of_node; 30 30 31 31 struct pci_ops *pci_ops; 32 32 struct resource *mem_resource; ··· 143 141 #endif 144 142 145 143 extern char * (*pcibios_plat_setup)(char *str); 144 + 145 + /* this function parses memory ranges from a device node */ 146 + extern void __devinit pci_load_of_ranges(struct pci_controller *hose, 147 + struct device_node *node); 146 148 147 149 #endif /* _ASM_PCI_H */
+55
arch/mips/pci/pci.c
··· 16 16 #include <linux/init.h> 17 17 #include <linux/types.h> 18 18 #include <linux/pci.h> 19 + #include <linux/of_address.h> 19 20 20 21 #include <asm/cpu-info.h> 21 22 ··· 115 114 pci_bus_assign_resources(bus); 116 115 pci_enable_bridges(bus); 117 116 } 117 + bus->dev.of_node = hose->of_node; 118 118 } 119 119 } 120 + 121 + #ifdef CONFIG_OF 122 + void __devinit pci_load_of_ranges(struct pci_controller *hose, 123 + struct device_node *node) 124 + { 125 + const __be32 *ranges; 126 + int rlen; 127 + int pna = of_n_addr_cells(node); 128 + int np = pna + 5; 129 + 130 + pr_info("PCI host bridge %s ranges:\n", node->full_name); 131 + ranges = of_get_property(node, "ranges", &rlen); 132 + if (ranges == NULL) 133 + return; 134 + hose->of_node = node; 135 + 136 + while ((rlen -= np * 4) >= 0) { 137 + u32 pci_space; 138 + struct resource *res = NULL; 139 + u64 addr, size; 140 + 141 + pci_space = be32_to_cpup(&ranges[0]); 142 + addr = of_translate_address(node, ranges + 3); 143 + size = of_read_number(ranges + pna + 3, 2); 144 + ranges += np; 145 + switch ((pci_space >> 24) & 0x3) { 146 + case 1: /* PCI IO space */ 147 + pr_info(" IO 0x%016llx..0x%016llx\n", 148 + addr, addr + size - 1); 149 + hose->io_map_base = 150 + (unsigned long)ioremap(addr, size); 151 + res = hose->io_resource; 152 + res->flags = IORESOURCE_IO; 153 + break; 154 + case 2: /* PCI Memory space */ 155 + case 3: /* PCI 64 bits Memory space */ 156 + pr_info(" MEM 0x%016llx..0x%016llx\n", 157 + addr, addr + size - 1); 158 + res = hose->mem_resource; 159 + res->flags = IORESOURCE_MEM; 160 + break; 161 + } 162 + if (res != NULL) { 163 + res->start = addr; 164 + res->name = node->full_name; 165 + res->end = res->start + size - 1; 166 + res->parent = NULL; 167 + res->sibling = NULL; 168 + res->child = NULL; 169 + } 170 + } 171 + } 172 + #endif 120 173 121 174 static DEFINE_MUTEX(pci_scan_mutex); 122 175