diff options
author | John Crispin <blogic@openwrt.org> | 2012-05-04 04:50:13 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-05-15 11:49:19 -0400 |
commit | a48cf37ac8a77ddd2370be3c9af411c622ebc425 (patch) | |
tree | 7326beae68f1fafd924b9436ec2c1551e36f94b8 /arch/mips/pci/pci.c | |
parent | 3572a2c37f667ee49333f8863722b8f43eac506b (diff) |
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>
Diffstat (limited to 'arch/mips/pci/pci.c')
-rw-r--r-- | arch/mips/pci/pci.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 0514866fa925..271e8c4a54c7 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include <linux/of_address.h> | ||
19 | 20 | ||
20 | #include <asm/cpu-info.h> | 21 | #include <asm/cpu-info.h> |
21 | 22 | ||
@@ -114,9 +115,63 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose) | |||
114 | pci_bus_assign_resources(bus); | 115 | pci_bus_assign_resources(bus); |
115 | pci_enable_bridges(bus); | 116 | pci_enable_bridges(bus); |
116 | } | 117 | } |
118 | bus->dev.of_node = hose->of_node; | ||
117 | } | 119 | } |
118 | } | 120 | } |
119 | 121 | ||
122 | #ifdef CONFIG_OF | ||
123 | void __devinit pci_load_of_ranges(struct pci_controller *hose, | ||
124 | struct device_node *node) | ||
125 | { | ||
126 | const __be32 *ranges; | ||
127 | int rlen; | ||
128 | int pna = of_n_addr_cells(node); | ||
129 | int np = pna + 5; | ||
130 | |||
131 | pr_info("PCI host bridge %s ranges:\n", node->full_name); | ||
132 | ranges = of_get_property(node, "ranges", &rlen); | ||
133 | if (ranges == NULL) | ||
134 | return; | ||
135 | hose->of_node = node; | ||
136 | |||
137 | while ((rlen -= np * 4) >= 0) { | ||
138 | u32 pci_space; | ||
139 | struct resource *res = NULL; | ||
140 | u64 addr, size; | ||
141 | |||
142 | pci_space = be32_to_cpup(&ranges[0]); | ||
143 | addr = of_translate_address(node, ranges + 3); | ||
144 | size = of_read_number(ranges + pna + 3, 2); | ||
145 | ranges += np; | ||
146 | switch ((pci_space >> 24) & 0x3) { | ||
147 | case 1: /* PCI IO space */ | ||
148 | pr_info(" IO 0x%016llx..0x%016llx\n", | ||
149 | addr, addr + size - 1); | ||
150 | hose->io_map_base = | ||
151 | (unsigned long)ioremap(addr, size); | ||
152 | res = hose->io_resource; | ||
153 | res->flags = IORESOURCE_IO; | ||
154 | break; | ||
155 | case 2: /* PCI Memory space */ | ||
156 | case 3: /* PCI 64 bits Memory space */ | ||
157 | pr_info(" MEM 0x%016llx..0x%016llx\n", | ||
158 | addr, addr + size - 1); | ||
159 | res = hose->mem_resource; | ||
160 | res->flags = IORESOURCE_MEM; | ||
161 | break; | ||
162 | } | ||
163 | if (res != NULL) { | ||
164 | res->start = addr; | ||
165 | res->name = node->full_name; | ||
166 | res->end = res->start + size - 1; | ||
167 | res->parent = NULL; | ||
168 | res->sibling = NULL; | ||
169 | res->child = NULL; | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | #endif | ||
174 | |||
120 | static DEFINE_MUTEX(pci_scan_mutex); | 175 | static DEFINE_MUTEX(pci_scan_mutex); |
121 | 176 | ||
122 | void __devinit register_pci_controller(struct pci_controller *hose) | 177 | void __devinit register_pci_controller(struct pci_controller *hose) |