mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 18:39:59 +00:00
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>
This commit is contained in:
parent
3572a2c37f
commit
a48cf37ac8
2 changed files with 61 additions and 0 deletions
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/*
|
||||
* Each pci channel is a top-level PCI bus seem by CPU. A machine with
|
||||
|
@ -26,6 +27,7 @@
|
|||
struct pci_controller {
|
||||
struct pci_controller *next;
|
||||
struct pci_bus *bus;
|
||||
struct device_node *of_node;
|
||||
|
||||
struct pci_ops *pci_ops;
|
||||
struct resource *mem_resource;
|
||||
|
@ -142,4 +144,8 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
|
|||
|
||||
extern char * (*pcibios_plat_setup)(char *str);
|
||||
|
||||
/* this function parses memory ranges from a device node */
|
||||
extern void __devinit pci_load_of_ranges(struct pci_controller *hose,
|
||||
struct device_node *node);
|
||||
|
||||
#endif /* _ASM_PCI_H */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/cpu-info.h>
|
||||
|
||||
|
@ -114,9 +115,63 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
|
|||
pci_bus_assign_resources(bus);
|
||||
pci_enable_bridges(bus);
|
||||
}
|
||||
bus->dev.of_node = hose->of_node;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
void __devinit pci_load_of_ranges(struct pci_controller *hose,
|
||||
struct device_node *node)
|
||||
{
|
||||
const __be32 *ranges;
|
||||
int rlen;
|
||||
int pna = of_n_addr_cells(node);
|
||||
int np = pna + 5;
|
||||
|
||||
pr_info("PCI host bridge %s ranges:\n", node->full_name);
|
||||
ranges = of_get_property(node, "ranges", &rlen);
|
||||
if (ranges == NULL)
|
||||
return;
|
||||
hose->of_node = node;
|
||||
|
||||
while ((rlen -= np * 4) >= 0) {
|
||||
u32 pci_space;
|
||||
struct resource *res = NULL;
|
||||
u64 addr, size;
|
||||
|
||||
pci_space = be32_to_cpup(&ranges[0]);
|
||||
addr = of_translate_address(node, ranges + 3);
|
||||
size = of_read_number(ranges + pna + 3, 2);
|
||||
ranges += np;
|
||||
switch ((pci_space >> 24) & 0x3) {
|
||||
case 1: /* PCI IO space */
|
||||
pr_info(" IO 0x%016llx..0x%016llx\n",
|
||||
addr, addr + size - 1);
|
||||
hose->io_map_base =
|
||||
(unsigned long)ioremap(addr, size);
|
||||
res = hose->io_resource;
|
||||
res->flags = IORESOURCE_IO;
|
||||
break;
|
||||
case 2: /* PCI Memory space */
|
||||
case 3: /* PCI 64 bits Memory space */
|
||||
pr_info(" MEM 0x%016llx..0x%016llx\n",
|
||||
addr, addr + size - 1);
|
||||
res = hose->mem_resource;
|
||||
res->flags = IORESOURCE_MEM;
|
||||
break;
|
||||
}
|
||||
if (res != NULL) {
|
||||
res->start = addr;
|
||||
res->name = node->full_name;
|
||||
res->end = res->start + size - 1;
|
||||
res->parent = NULL;
|
||||
res->sibling = NULL;
|
||||
res->child = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static DEFINE_MUTEX(pci_scan_mutex);
|
||||
|
||||
void __devinit register_pci_controller(struct pci_controller *hose)
|
||||
|
|
Loading…
Reference in a new issue