* Re: [PATCH OF 07/14] of: move of_irq_map_pci() into generic code [not found] ` <1295843342-1122-8-git-send-email-bigeasy@linutronix.de> @ 2011-02-16 21:53 ` Grant Likely 2011-02-17 7:49 ` Michal Simek 0 siblings, 1 reply; 2+ messages in thread From: Grant Likely @ 2011-02-16 21:53 UTC (permalink / raw) To: Sebastian Andrzej Siewior Cc: Michal Simek, microblaze-uclinux, devicetree-discuss, x86, linux-kernel, sodaville, Sebastian Andrzej Siewior, linuxppc-dev On Sun, Jan 23, 2011 at 9:28 PM, Sebastian Andrzej Siewior <bigeasy@linutronix•de> wrote: > From: Sebastian Andrzej Siewior <sebastian@breakpoint•cc> > > There is a tiny difference between PPC32 and PPC64. Microblaze uses the > PPC32 variant. > > Cc: devicetree-discuss@lists•ozlabs.org > Cc: Benjamin Herrenschmidt <benh@kernel•crashing.org> > Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint•cc> I've got this one in my devicetree/next branch which is pulled into linux-next. I've not received an ack from Ben yet. Michal, is this okay by you? http://git.secretlab.ca/?p=3Dlinux-2.6.git;a=3Dcommit;h=3D04bea68b2f0eeebb0= 89ecc67b618795925268b4a g. > --- > =A0arch/microblaze/include/asm/pci-bridge.h | =A0 12 ++++ > =A0arch/microblaze/include/asm/prom.h =A0 =A0 =A0 | =A0 15 ----- > =A0arch/microblaze/kernel/prom_parse.c =A0 =A0 =A0| =A0 77 --------------= ------------- > =A0arch/microblaze/pci/pci-common.c =A0 =A0 =A0 =A0 | =A0 =A01 + > =A0arch/powerpc/include/asm/pci-bridge.h =A0 =A0| =A0 10 ++++ > =A0arch/powerpc/include/asm/prom.h =A0 =A0 =A0 =A0 =A0| =A0 15 ----- > =A0arch/powerpc/kernel/pci-common.c =A0 =A0 =A0 =A0 | =A0 =A01 + > =A0arch/powerpc/kernel/prom_parse.c =A0 =A0 =A0 =A0 | =A0 84 ------------= ------------------ > =A0drivers/of/Kconfig =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0 = =A06 ++ > =A0drivers/of/Makefile =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0 = =A01 + > =A0drivers/of/of_pci.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0 8= 0 ++++++++++++++++++++++++++++ > =A0include/linux/of_pci.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0 20 ++= +++++ > =A012 files changed, 131 insertions(+), 191 deletions(-) > =A0create mode 100644 drivers/of/of_pci.c > =A0create mode 100644 include/linux/of_pci.h > > diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/i= nclude/asm/pci-bridge.h > index 0c68764..c2a40a4 100644 > --- a/arch/microblaze/include/asm/pci-bridge.h > +++ b/arch/microblaze/include/asm/pci-bridge.h > @@ -104,11 +104,22 @@ struct pci_controller { > =A0 =A0 =A0 =A0int global_number; =A0 =A0 =A0/* PCI domain number */ > =A0}; > > +#ifdef CONFIG_PCI > =A0static inline struct pci_controller *pci_bus_to_host(const struct pci_= bus *bus) > =A0{ > =A0 =A0 =A0 =A0return bus->sysdata; > =A0} > > +static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus= ) > +{ > + =A0 =A0 =A0 struct pci_controller *host; > + > + =A0 =A0 =A0 if (bus->self) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return pci_device_to_OF_node(bus->self); > + =A0 =A0 =A0 host =3D pci_bus_to_host(bus); > + =A0 =A0 =A0 return host ? host->dn : NULL; > +} > + > =A0static inline int isa_vaddr_is_ioport(void __iomem *address) > =A0{ > =A0 =A0 =A0 =A0/* No specific ISA handling on ppc32 at this stage, it > @@ -116,6 +127,7 @@ static inline int isa_vaddr_is_ioport(void __iomem *a= ddress) > =A0 =A0 =A0 =A0 */ > =A0 =A0 =A0 =A0return 0; > =A0} > +#endif > > =A0/* These are used for config access before all the PCI probing > =A0 =A0has been done. */ > diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include= /asm/prom.h > index 2e72af0..d0890d3 100644 > --- a/arch/microblaze/include/asm/prom.h > +++ b/arch/microblaze/include/asm/prom.h > @@ -64,21 +64,6 @@ extern void kdump_move_device_tree(void); > =A0/* CPU OF node matching */ > =A0struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); > > -/** > - * of_irq_map_pci - Resolve the interrupt for a PCI device > - * @pdev: =A0 =A0 =A0the device whose interrupt is to be resolved > - * @out_irq: =A0 structure of_irq filled by this function > - * > - * This function resolves the PCI interrupt for a given PCI device. If a > - * device-node exists for a given pci_dev, it will use normal OF tree > - * walking. If not, it will implement standard swizzling and walk up the > - * PCI tree until an device-node is found, at which point it will finish > - * resolving using the OF tree walking. > - */ > -struct pci_dev; > -struct of_irq; > -extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); > - > =A0#endif /* __ASSEMBLY__ */ > =A0#endif /* __KERNEL__ */ > > diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel= /prom_parse.c > index 9ae24f4..47187cc 100644 > --- a/arch/microblaze/kernel/prom_parse.c > +++ b/arch/microblaze/kernel/prom_parse.c > @@ -2,88 +2,11 @@ > > =A0#include <linux/kernel.h> > =A0#include <linux/string.h> > -#include <linux/pci_regs.h> > =A0#include <linux/module.h> > =A0#include <linux/ioport.h> > =A0#include <linux/etherdevice.h> > =A0#include <linux/of_address.h> > =A0#include <asm/prom.h> > -#include <asm/pci-bridge.h> > - > -#ifdef CONFIG_PCI > -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) > -{ > - =A0 =A0 =A0 struct device_node *dn, *ppnode; > - =A0 =A0 =A0 struct pci_dev *ppdev; > - =A0 =A0 =A0 u32 lspec; > - =A0 =A0 =A0 u32 laddr[3]; > - =A0 =A0 =A0 u8 pin; > - =A0 =A0 =A0 int rc; > - > - =A0 =A0 =A0 /* Check if we have a device node, if yes, fallback to stan= dard OF > - =A0 =A0 =A0 =A0* parsing > - =A0 =A0 =A0 =A0*/ > - =A0 =A0 =A0 dn =3D pci_device_to_OF_node(pdev); > - =A0 =A0 =A0 if (dn) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return of_irq_map_one(dn, 0, out_irq); > - > - =A0 =A0 =A0 /* Ok, we don't, time to have fun. Let's start by building = up an > - =A0 =A0 =A0 =A0* interrupt spec. =A0we assume #interrupt-cells is 1, wh= ich is standard > - =A0 =A0 =A0 =A0* for PCI. If you do different, then don't use that rout= ine. > - =A0 =A0 =A0 =A0*/ > - =A0 =A0 =A0 rc =3D pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); > - =A0 =A0 =A0 if (rc !=3D 0) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return rc; > - =A0 =A0 =A0 /* No pin, exit */ > - =A0 =A0 =A0 if (pin =3D=3D 0) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV; > - > - =A0 =A0 =A0 /* Now we walk up the PCI tree */ > - =A0 =A0 =A0 lspec =3D pin; > - =A0 =A0 =A0 for (;;) { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Get the pci_dev of our parent */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppdev =3D pdev->bus->self; > - > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Ouch, it's a host bridge... */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ppdev =3D=3D NULL) { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct pci_controller *host= ; > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 host =3D pci_bus_to_host(pd= ev->bus); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppnode =3D host ? host->dn = : NULL; > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* No node for host bridge = ? give up */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ppnode =3D=3D NULL) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -EIN= VAL; > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We found a P2P bridge, c= heck if it has a node */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppnode =3D pci_device_to_OF= _node(ppdev); > - > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Ok, we have found a parent with a device= -node, hand over to > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the OF parsing code. > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* We build a unit address from the linux= device to be used for > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* resolution. Note that we use the linux= bus number which may > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* not match your firmware bus numbering. > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Fortunately, in most cases, interrupt-= map-mask doesn't > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* include the bus number as part of the = matching. > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* You should still be careful about that= though if you intend > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* to rely on this function (you ship =A0= a firmware that doesn't > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* create device nodes for all PCI device= s). > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ppnode) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break; > - > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We can only get here if we hit a P2P bri= dge with no node, > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* let's do standard swizzling and try ag= ain > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 lspec =3D pci_swizzle_interrupt_pin(pdev, l= spec); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdev =3D ppdev; > - =A0 =A0 =A0 } > - > - =A0 =A0 =A0 laddr[0] =3D (pdev->bus->number << 16) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 | (pdev->devfn << 8); > - =A0 =A0 =A0 laddr[1] =A0=3D laddr[2] =3D 0; > - =A0 =A0 =A0 return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); > -} > -EXPORT_SYMBOL_GPL(of_irq_map_pci); > -#endif /* CONFIG_PCI */ > > =A0void of_parse_dma_window(struct device_node *dn, const void *dma_windo= w_prop, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned long *busno, unsigned long *phys,= unsigned long *size) > diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-c= ommon.c > index e363615..1e01a12 100644 > --- a/arch/microblaze/pci/pci-common.c > +++ b/arch/microblaze/pci/pci-common.c > @@ -29,6 +29,7 @@ > =A0#include <linux/slab.h> > =A0#include <linux/of.h> > =A0#include <linux/of_address.h> > +#include <linux/of_pci.h> > > =A0#include <asm/processor.h> > =A0#include <asm/io.h> > diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include= /asm/pci-bridge.h > index 51e9e6f..edeb80f 100644 > --- a/arch/powerpc/include/asm/pci-bridge.h > +++ b/arch/powerpc/include/asm/pci-bridge.h > @@ -171,6 +171,16 @@ static inline struct pci_controller *pci_bus_to_host= (const struct pci_bus *bus) > =A0 =A0 =A0 =A0return bus->sysdata; > =A0} > > +static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus= ) > +{ > + =A0 =A0 =A0 struct pci_controller *host; > + > + =A0 =A0 =A0 if (bus->self) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return pci_device_to_OF_node(bus->self); > + =A0 =A0 =A0 host =3D pci_bus_to_host(bus); > + =A0 =A0 =A0 return host ? host->dn : NULL; > +} > + > =A0static inline int isa_vaddr_is_ioport(void __iomem *address) > =A0{ > =A0 =A0 =A0 =A0/* No specific ISA handling on ppc32 at this stage, it > diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/p= rom.h > index d727575..c189aa5 100644 > --- a/arch/powerpc/include/asm/prom.h > +++ b/arch/powerpc/include/asm/prom.h > @@ -70,21 +70,6 @@ static inline int of_node_to_nid(struct device_node *d= evice) { return 0; } > =A0#endif > =A0#define of_node_to_nid of_node_to_nid > > -/** > - * of_irq_map_pci - Resolve the interrupt for a PCI device > - * @pdev: =A0 =A0 =A0the device whose interrupt is to be resolved > - * @out_irq: =A0 structure of_irq filled by this function > - * > - * This function resolves the PCI interrupt for a given PCI device. If a > - * device-node exists for a given pci_dev, it will use normal OF tree > - * walking. If not, it will implement standard swizzling and walk up the > - * PCI tree until an device-node is found, at which point it will finish > - * resolving using the OF tree walking. > - */ > -struct pci_dev; > -struct of_irq; > -extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); > - > =A0extern void of_instantiate_rtc(void); > > =A0/* These includes are put at the bottom because they may contain thing= s > diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-c= ommon.c > index 10a44e6..eb341be 100644 > --- a/arch/powerpc/kernel/pci-common.c > +++ b/arch/powerpc/kernel/pci-common.c > @@ -22,6 +22,7 @@ > =A0#include <linux/init.h> > =A0#include <linux/bootmem.h> > =A0#include <linux/of_address.h> > +#include <linux/of_pci.h> > =A0#include <linux/mm.h> > =A0#include <linux/list.h> > =A0#include <linux/syscalls.h> > diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_= parse.c > index c2b7a07..47187cc 100644 > --- a/arch/powerpc/kernel/prom_parse.c > +++ b/arch/powerpc/kernel/prom_parse.c > @@ -2,95 +2,11 @@ > > =A0#include <linux/kernel.h> > =A0#include <linux/string.h> > -#include <linux/pci_regs.h> > =A0#include <linux/module.h> > =A0#include <linux/ioport.h> > =A0#include <linux/etherdevice.h> > =A0#include <linux/of_address.h> > =A0#include <asm/prom.h> > -#include <asm/pci-bridge.h> > - > -#ifdef CONFIG_PCI > -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) > -{ > - =A0 =A0 =A0 struct device_node *dn, *ppnode; > - =A0 =A0 =A0 struct pci_dev *ppdev; > - =A0 =A0 =A0 u32 lspec; > - =A0 =A0 =A0 u32 laddr[3]; > - =A0 =A0 =A0 u8 pin; > - =A0 =A0 =A0 int rc; > - > - =A0 =A0 =A0 /* Check if we have a device node, if yes, fallback to stan= dard OF > - =A0 =A0 =A0 =A0* parsing > - =A0 =A0 =A0 =A0*/ > - =A0 =A0 =A0 dn =3D pci_device_to_OF_node(pdev); > - =A0 =A0 =A0 if (dn) { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 rc =3D of_irq_map_one(dn, 0, out_irq); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!rc) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return rc; > - =A0 =A0 =A0 } > - > - =A0 =A0 =A0 /* Ok, we don't, time to have fun. Let's start by building = up an > - =A0 =A0 =A0 =A0* interrupt spec. =A0we assume #interrupt-cells is 1, wh= ich is standard > - =A0 =A0 =A0 =A0* for PCI. If you do different, then don't use that rout= ine. > - =A0 =A0 =A0 =A0*/ > - =A0 =A0 =A0 rc =3D pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); > - =A0 =A0 =A0 if (rc !=3D 0) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return rc; > - =A0 =A0 =A0 /* No pin, exit */ > - =A0 =A0 =A0 if (pin =3D=3D 0) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV; > - > - =A0 =A0 =A0 /* Now we walk up the PCI tree */ > - =A0 =A0 =A0 lspec =3D pin; > - =A0 =A0 =A0 for (;;) { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Get the pci_dev of our parent */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppdev =3D pdev->bus->self; > - > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Ouch, it's a host bridge... */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ppdev =3D=3D NULL) { > -#ifdef CONFIG_PPC64 > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppnode =3D pci_bus_to_OF_no= de(pdev->bus); > -#else > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct pci_controller *host= ; > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 host =3D pci_bus_to_host(pd= ev->bus); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppnode =3D host ? host->dn = : NULL; > -#endif > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* No node for host bridge = ? give up */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ppnode =3D=3D NULL) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -EIN= VAL; > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We found a P2P bridge, c= heck if it has a node */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppnode =3D pci_device_to_OF= _node(ppdev); > - > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Ok, we have found a parent with a device= -node, hand over to > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the OF parsing code. > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* We build a unit address from the linux= device to be used for > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* resolution. Note that we use the linux= bus number which may > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* not match your firmware bus numbering. > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Fortunately, in most cases, interrupt-= map-mask doesn't include > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the bus number as part of the matching= . > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* You should still be careful about that= though if you intend > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* to rely on this function (you ship =A0= a firmware that doesn't > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* create device nodes for all PCI device= s). > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ppnode) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break; > - > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We can only get here if we hit a P2P bri= dge with no node, > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* let's do standard swizzling and try ag= ain > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 lspec =3D pci_swizzle_interrupt_pin(pdev, l= spec); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdev =3D ppdev; > - =A0 =A0 =A0 } > - > - =A0 =A0 =A0 laddr[0] =3D (pdev->bus->number << 16) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 | (pdev->devfn << 8); > - =A0 =A0 =A0 laddr[1] =A0=3D laddr[2] =3D 0; > - =A0 =A0 =A0 return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); > -} > -EXPORT_SYMBOL_GPL(of_irq_map_pci); > -#endif /* CONFIG_PCI */ > > =A0void of_parse_dma_window(struct device_node *dn, const void *dma_windo= w_prop, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned long *busno, unsigned long *phys,= unsigned long *size) > diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig > index 3c6e100..c71cff1 100644 > --- a/drivers/of/Kconfig > +++ b/drivers/of/Kconfig > @@ -69,4 +69,10 @@ config OF_MDIO > =A0 =A0 =A0 =A0help > =A0 =A0 =A0 =A0 =A0OpenFirmware MDIO bus (Ethernet PHY) accessors > > +config OF_PCI > + =A0 =A0 =A0 def_tristate PCI > + =A0 =A0 =A0 depends on PCI && !SPARC > + =A0 =A0 =A0 help > + =A0 =A0 =A0 =A0 OpenFirmware PCI bus accessors > + > =A0endmenu # OF > diff --git a/drivers/of/Makefile b/drivers/of/Makefile > index 3ab21a0..f7861ed 100644 > --- a/drivers/of/Makefile > +++ b/drivers/of/Makefile > @@ -9,3 +9,4 @@ obj-$(CONFIG_OF_I2C) =A0 =A0+=3D of_i2c.o > =A0obj-$(CONFIG_OF_NET) =A0 +=3D of_net.o > =A0obj-$(CONFIG_OF_SPI) =A0 +=3D of_spi.o > =A0obj-$(CONFIG_OF_MDIO) =A0+=3D of_mdio.o > +obj-$(CONFIG_OF_PCI) =A0 +=3D of_pci.o > diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c > new file mode 100644 > index 0000000..dd862d2 > --- /dev/null > +++ b/drivers/of/of_pci.c > @@ -0,0 +1,80 @@ > +#include <linux/kernel.h> > +#include <linux/of_pci.h> > +#include <asm/prom.h> > + > +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) > +{ > + =A0 =A0 =A0 struct device_node *dn, *ppnode; > + =A0 =A0 =A0 struct pci_dev *ppdev; > + =A0 =A0 =A0 u32 lspec; > + =A0 =A0 =A0 __be32 lspec_be; > + =A0 =A0 =A0 __be32 laddr[3]; > + =A0 =A0 =A0 u8 pin; > + =A0 =A0 =A0 int rc; > + > + =A0 =A0 =A0 /* Check if we have a device node, if yes, fallback to stan= dard OF > + =A0 =A0 =A0 =A0* parsing > + =A0 =A0 =A0 =A0*/ > + =A0 =A0 =A0 dn =3D pci_device_to_OF_node(pdev); > + =A0 =A0 =A0 if (dn) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rc =3D of_irq_map_one(dn, 0, out_irq); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!rc) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return rc; > + =A0 =A0 =A0 } > + > + =A0 =A0 =A0 /* Ok, we don't, time to have fun. Let's start by building = up an > + =A0 =A0 =A0 =A0* interrupt spec. =A0we assume #interrupt-cells is 1, wh= ich is standard > + =A0 =A0 =A0 =A0* for PCI. If you do different, then don't use that rout= ine. > + =A0 =A0 =A0 =A0*/ > + =A0 =A0 =A0 rc =3D pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); > + =A0 =A0 =A0 if (rc !=3D 0) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return rc; > + =A0 =A0 =A0 /* No pin, exit */ > + =A0 =A0 =A0 if (pin =3D=3D 0) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV; > + > + =A0 =A0 =A0 /* Now we walk up the PCI tree */ > + =A0 =A0 =A0 lspec =3D pin; > + =A0 =A0 =A0 for (;;) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Get the pci_dev of our parent */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppdev =3D pdev->bus->self; > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Ouch, it's a host bridge... */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ppdev =3D=3D NULL) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppnode =3D pci_bus_to_OF_no= de(pdev->bus); > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* No node for host bridge = ? give up */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ppnode =3D=3D NULL) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -EIN= VAL; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We found a P2P bridge, c= heck if it has a node */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppnode =3D pci_device_to_OF= _node(ppdev); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Ok, we have found a parent with a device= -node, hand over to > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the OF parsing code. > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* We build a unit address from the linux= device to be used for > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* resolution. Note that we use the linux= bus number which may > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* not match your firmware bus numbering. > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Fortunately, in most cases, interrupt-= map-mask doesn't > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* include the bus number as part of the = matching. > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* You should still be careful about that= though if you intend > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* to rely on this function (you ship =A0= a firmware that doesn't > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* create device nodes for all PCI device= s). > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ppnode) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break; > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We can only get here if we hit a P2P bri= dge with no node, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* let's do standard swizzling and try ag= ain > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lspec =3D pci_swizzle_interrupt_pin(pdev, l= spec); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdev =3D ppdev; > + =A0 =A0 =A0 } > + > + =A0 =A0 =A0 lspec_be =3D cpu_to_be32(lspec); > + =A0 =A0 =A0 laddr[0] =3D cpu_to_be32((pdev->bus->number << 16) | (pdev-= >devfn << 8)); > + =A0 =A0 =A0 laddr[1] =A0=3D laddr[2] =3D cpu_to_be32(0); > + =A0 =A0 =A0 return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq)= ; > +} > +EXPORT_SYMBOL_GPL(of_irq_map_pci); > diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h > new file mode 100644 > index 0000000..9b0ba67 > --- /dev/null > +++ b/include/linux/of_pci.h > @@ -0,0 +1,20 @@ > +#ifndef __OF_PCI_H > +#define __OF_PCI_H > + > +#include <linux/pci.h> > + > +/** > + * of_irq_map_pci - Resolve the interrupt for a PCI device > + * @pdev: =A0 =A0 =A0 the device whose interrupt is to be resolved > + * @out_irq: =A0 =A0structure of_irq filled by this function > + * > + * This function resolves the PCI interrupt for a given PCI device. If a > + * device-node exists for a given pci_dev, it will use normal OF tree > + * walking. If not, it will implement standard swizzling and walk up the > + * PCI tree until an device-node is found, at which point it will finish > + * resolving using the OF tree walking. > + */ > +struct pci_dev; > +struct of_irq; > +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); > +#endif > -- > 1.7.3.2 > > _______________________________________________ > devicetree-discuss mailing list > devicetree-discuss@lists•ozlabs.org > https://lists.ozlabs.org/listinfo/devicetree-discuss > --=20 Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. ^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH OF 07/14] of: move of_irq_map_pci() into generic code 2011-02-16 21:53 ` [PATCH OF 07/14] of: move of_irq_map_pci() into generic code Grant Likely @ 2011-02-17 7:49 ` Michal Simek 0 siblings, 0 replies; 2+ messages in thread From: Michal Simek @ 2011-02-17 7:49 UTC (permalink / raw) To: Grant Likely Cc: Michal Simek, microblaze-uclinux, devicetree-discuss, x86, linux-kernel, sodaville, Sebastian Andrzej Siewior, linuxppc-dev, Sebastian Andrzej Siewior Grant Likely wrote: > On Sun, Jan 23, 2011 at 9:28 PM, Sebastian Andrzej Siewior > <bigeasy@linutronix•de> wrote: >> From: Sebastian Andrzej Siewior <sebastian@breakpoint•cc> >> >> There is a tiny difference between PPC32 and PPC64. Microblaze uses the >> PPC32 variant. >> >> Cc: devicetree-discuss@lists•ozlabs.org >> Cc: Benjamin Herrenschmidt <benh@kernel•crashing.org> >> Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint•cc> > > I've got this one in my devicetree/next branch which is pulled into > linux-next. I've not received an ack from Ben yet. Michal, is this > okay by you? yep. No problem. I don't have pci hw for testing but compilation is fine. If you like: Acked-by: Michal Simek <monstr@monstr•eu> Thanks, Michal > > http://git.secretlab.ca/?p=linux-2.6.git;a=commit;h=04bea68b2f0eeebb089ecc67b618795925268b4a > > g. > >> --- >> arch/microblaze/include/asm/pci-bridge.h | 12 ++++ >> arch/microblaze/include/asm/prom.h | 15 ----- >> arch/microblaze/kernel/prom_parse.c | 77 --------------------------- >> arch/microblaze/pci/pci-common.c | 1 + >> arch/powerpc/include/asm/pci-bridge.h | 10 ++++ >> arch/powerpc/include/asm/prom.h | 15 ----- >> arch/powerpc/kernel/pci-common.c | 1 + >> arch/powerpc/kernel/prom_parse.c | 84 ------------------------------ >> drivers/of/Kconfig | 6 ++ >> drivers/of/Makefile | 1 + >> drivers/of/of_pci.c | 80 ++++++++++++++++++++++++++++ >> include/linux/of_pci.h | 20 +++++++ >> 12 files changed, 131 insertions(+), 191 deletions(-) >> create mode 100644 drivers/of/of_pci.c >> create mode 100644 include/linux/of_pci.h >> >> diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h >> index 0c68764..c2a40a4 100644 >> --- a/arch/microblaze/include/asm/pci-bridge.h >> +++ b/arch/microblaze/include/asm/pci-bridge.h >> @@ -104,11 +104,22 @@ struct pci_controller { >> int global_number; /* PCI domain number */ >> }; >> >> +#ifdef CONFIG_PCI >> static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) >> { >> return bus->sysdata; >> } >> >> +static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) >> +{ >> + struct pci_controller *host; >> + >> + if (bus->self) >> + return pci_device_to_OF_node(bus->self); >> + host = pci_bus_to_host(bus); >> + return host ? host->dn : NULL; >> +} >> + >> static inline int isa_vaddr_is_ioport(void __iomem *address) >> { >> /* No specific ISA handling on ppc32 at this stage, it >> @@ -116,6 +127,7 @@ static inline int isa_vaddr_is_ioport(void __iomem *address) >> */ >> return 0; >> } >> +#endif >> >> /* These are used for config access before all the PCI probing >> has been done. */ >> diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h >> index 2e72af0..d0890d3 100644 >> --- a/arch/microblaze/include/asm/prom.h >> +++ b/arch/microblaze/include/asm/prom.h >> @@ -64,21 +64,6 @@ extern void kdump_move_device_tree(void); >> /* CPU OF node matching */ >> struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); >> >> -/** >> - * of_irq_map_pci - Resolve the interrupt for a PCI device >> - * @pdev: the device whose interrupt is to be resolved >> - * @out_irq: structure of_irq filled by this function >> - * >> - * This function resolves the PCI interrupt for a given PCI device. If a >> - * device-node exists for a given pci_dev, it will use normal OF tree >> - * walking. If not, it will implement standard swizzling and walk up the >> - * PCI tree until an device-node is found, at which point it will finish >> - * resolving using the OF tree walking. >> - */ >> -struct pci_dev; >> -struct of_irq; >> -extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); >> - >> #endif /* __ASSEMBLY__ */ >> #endif /* __KERNEL__ */ >> >> diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c >> index 9ae24f4..47187cc 100644 >> --- a/arch/microblaze/kernel/prom_parse.c >> +++ b/arch/microblaze/kernel/prom_parse.c >> @@ -2,88 +2,11 @@ >> >> #include <linux/kernel.h> >> #include <linux/string.h> >> -#include <linux/pci_regs.h> >> #include <linux/module.h> >> #include <linux/ioport.h> >> #include <linux/etherdevice.h> >> #include <linux/of_address.h> >> #include <asm/prom.h> >> -#include <asm/pci-bridge.h> >> - >> -#ifdef CONFIG_PCI >> -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) >> -{ >> - struct device_node *dn, *ppnode; >> - struct pci_dev *ppdev; >> - u32 lspec; >> - u32 laddr[3]; >> - u8 pin; >> - int rc; >> - >> - /* Check if we have a device node, if yes, fallback to standard OF >> - * parsing >> - */ >> - dn = pci_device_to_OF_node(pdev); >> - if (dn) >> - return of_irq_map_one(dn, 0, out_irq); >> - >> - /* Ok, we don't, time to have fun. Let's start by building up an >> - * interrupt spec. we assume #interrupt-cells is 1, which is standard >> - * for PCI. If you do different, then don't use that routine. >> - */ >> - rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); >> - if (rc != 0) >> - return rc; >> - /* No pin, exit */ >> - if (pin == 0) >> - return -ENODEV; >> - >> - /* Now we walk up the PCI tree */ >> - lspec = pin; >> - for (;;) { >> - /* Get the pci_dev of our parent */ >> - ppdev = pdev->bus->self; >> - >> - /* Ouch, it's a host bridge... */ >> - if (ppdev == NULL) { >> - struct pci_controller *host; >> - host = pci_bus_to_host(pdev->bus); >> - ppnode = host ? host->dn : NULL; >> - /* No node for host bridge ? give up */ >> - if (ppnode == NULL) >> - return -EINVAL; >> - } else >> - /* We found a P2P bridge, check if it has a node */ >> - ppnode = pci_device_to_OF_node(ppdev); >> - >> - /* Ok, we have found a parent with a device-node, hand over to >> - * the OF parsing code. >> - * We build a unit address from the linux device to be used for >> - * resolution. Note that we use the linux bus number which may >> - * not match your firmware bus numbering. >> - * Fortunately, in most cases, interrupt-map-mask doesn't >> - * include the bus number as part of the matching. >> - * You should still be careful about that though if you intend >> - * to rely on this function (you ship a firmware that doesn't >> - * create device nodes for all PCI devices). >> - */ >> - if (ppnode) >> - break; >> - >> - /* We can only get here if we hit a P2P bridge with no node, >> - * let's do standard swizzling and try again >> - */ >> - lspec = pci_swizzle_interrupt_pin(pdev, lspec); >> - pdev = ppdev; >> - } >> - >> - laddr[0] = (pdev->bus->number << 16) >> - | (pdev->devfn << 8); >> - laddr[1] = laddr[2] = 0; >> - return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); >> -} >> -EXPORT_SYMBOL_GPL(of_irq_map_pci); >> -#endif /* CONFIG_PCI */ >> >> void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, >> unsigned long *busno, unsigned long *phys, unsigned long *size) >> diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c >> index e363615..1e01a12 100644 >> --- a/arch/microblaze/pci/pci-common.c >> +++ b/arch/microblaze/pci/pci-common.c >> @@ -29,6 +29,7 @@ >> #include <linux/slab.h> >> #include <linux/of.h> >> #include <linux/of_address.h> >> +#include <linux/of_pci.h> >> >> #include <asm/processor.h> >> #include <asm/io.h> >> diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h >> index 51e9e6f..edeb80f 100644 >> --- a/arch/powerpc/include/asm/pci-bridge.h >> +++ b/arch/powerpc/include/asm/pci-bridge.h >> @@ -171,6 +171,16 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) >> return bus->sysdata; >> } >> >> +static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) >> +{ >> + struct pci_controller *host; >> + >> + if (bus->self) >> + return pci_device_to_OF_node(bus->self); >> + host = pci_bus_to_host(bus); >> + return host ? host->dn : NULL; >> +} >> + >> static inline int isa_vaddr_is_ioport(void __iomem *address) >> { >> /* No specific ISA handling on ppc32 at this stage, it >> diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h >> index d727575..c189aa5 100644 >> --- a/arch/powerpc/include/asm/prom.h >> +++ b/arch/powerpc/include/asm/prom.h >> @@ -70,21 +70,6 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; } >> #endif >> #define of_node_to_nid of_node_to_nid >> >> -/** >> - * of_irq_map_pci - Resolve the interrupt for a PCI device >> - * @pdev: the device whose interrupt is to be resolved >> - * @out_irq: structure of_irq filled by this function >> - * >> - * This function resolves the PCI interrupt for a given PCI device. If a >> - * device-node exists for a given pci_dev, it will use normal OF tree >> - * walking. If not, it will implement standard swizzling and walk up the >> - * PCI tree until an device-node is found, at which point it will finish >> - * resolving using the OF tree walking. >> - */ >> -struct pci_dev; >> -struct of_irq; >> -extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); >> - >> extern void of_instantiate_rtc(void); >> >> /* These includes are put at the bottom because they may contain things >> diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c >> index 10a44e6..eb341be 100644 >> --- a/arch/powerpc/kernel/pci-common.c >> +++ b/arch/powerpc/kernel/pci-common.c >> @@ -22,6 +22,7 @@ >> #include <linux/init.h> >> #include <linux/bootmem.h> >> #include <linux/of_address.h> >> +#include <linux/of_pci.h> >> #include <linux/mm.h> >> #include <linux/list.h> >> #include <linux/syscalls.h> >> diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c >> index c2b7a07..47187cc 100644 >> --- a/arch/powerpc/kernel/prom_parse.c >> +++ b/arch/powerpc/kernel/prom_parse.c >> @@ -2,95 +2,11 @@ >> >> #include <linux/kernel.h> >> #include <linux/string.h> >> -#include <linux/pci_regs.h> >> #include <linux/module.h> >> #include <linux/ioport.h> >> #include <linux/etherdevice.h> >> #include <linux/of_address.h> >> #include <asm/prom.h> >> -#include <asm/pci-bridge.h> >> - >> -#ifdef CONFIG_PCI >> -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) >> -{ >> - struct device_node *dn, *ppnode; >> - struct pci_dev *ppdev; >> - u32 lspec; >> - u32 laddr[3]; >> - u8 pin; >> - int rc; >> - >> - /* Check if we have a device node, if yes, fallback to standard OF >> - * parsing >> - */ >> - dn = pci_device_to_OF_node(pdev); >> - if (dn) { >> - rc = of_irq_map_one(dn, 0, out_irq); >> - if (!rc) >> - return rc; >> - } >> - >> - /* Ok, we don't, time to have fun. Let's start by building up an >> - * interrupt spec. we assume #interrupt-cells is 1, which is standard >> - * for PCI. If you do different, then don't use that routine. >> - */ >> - rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); >> - if (rc != 0) >> - return rc; >> - /* No pin, exit */ >> - if (pin == 0) >> - return -ENODEV; >> - >> - /* Now we walk up the PCI tree */ >> - lspec = pin; >> - for (;;) { >> - /* Get the pci_dev of our parent */ >> - ppdev = pdev->bus->self; >> - >> - /* Ouch, it's a host bridge... */ >> - if (ppdev == NULL) { >> -#ifdef CONFIG_PPC64 >> - ppnode = pci_bus_to_OF_node(pdev->bus); >> -#else >> - struct pci_controller *host; >> - host = pci_bus_to_host(pdev->bus); >> - ppnode = host ? host->dn : NULL; >> -#endif >> - /* No node for host bridge ? give up */ >> - if (ppnode == NULL) >> - return -EINVAL; >> - } else >> - /* We found a P2P bridge, check if it has a node */ >> - ppnode = pci_device_to_OF_node(ppdev); >> - >> - /* Ok, we have found a parent with a device-node, hand over to >> - * the OF parsing code. >> - * We build a unit address from the linux device to be used for >> - * resolution. Note that we use the linux bus number which may >> - * not match your firmware bus numbering. >> - * Fortunately, in most cases, interrupt-map-mask doesn't include >> - * the bus number as part of the matching. >> - * You should still be careful about that though if you intend >> - * to rely on this function (you ship a firmware that doesn't >> - * create device nodes for all PCI devices). >> - */ >> - if (ppnode) >> - break; >> - >> - /* We can only get here if we hit a P2P bridge with no node, >> - * let's do standard swizzling and try again >> - */ >> - lspec = pci_swizzle_interrupt_pin(pdev, lspec); >> - pdev = ppdev; >> - } >> - >> - laddr[0] = (pdev->bus->number << 16) >> - | (pdev->devfn << 8); >> - laddr[1] = laddr[2] = 0; >> - return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); >> -} >> -EXPORT_SYMBOL_GPL(of_irq_map_pci); >> -#endif /* CONFIG_PCI */ >> >> void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, >> unsigned long *busno, unsigned long *phys, unsigned long *size) >> diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig >> index 3c6e100..c71cff1 100644 >> --- a/drivers/of/Kconfig >> +++ b/drivers/of/Kconfig >> @@ -69,4 +69,10 @@ config OF_MDIO >> help >> OpenFirmware MDIO bus (Ethernet PHY) accessors >> >> +config OF_PCI >> + def_tristate PCI >> + depends on PCI && !SPARC >> + help >> + OpenFirmware PCI bus accessors >> + >> endmenu # OF >> diff --git a/drivers/of/Makefile b/drivers/of/Makefile >> index 3ab21a0..f7861ed 100644 >> --- a/drivers/of/Makefile >> +++ b/drivers/of/Makefile >> @@ -9,3 +9,4 @@ obj-$(CONFIG_OF_I2C) += of_i2c.o >> obj-$(CONFIG_OF_NET) += of_net.o >> obj-$(CONFIG_OF_SPI) += of_spi.o >> obj-$(CONFIG_OF_MDIO) += of_mdio.o >> +obj-$(CONFIG_OF_PCI) += of_pci.o >> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c >> new file mode 100644 >> index 0000000..dd862d2 >> --- /dev/null >> +++ b/drivers/of/of_pci.c >> @@ -0,0 +1,80 @@ >> +#include <linux/kernel.h> >> +#include <linux/of_pci.h> >> +#include <asm/prom.h> >> + >> +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) >> +{ >> + struct device_node *dn, *ppnode; >> + struct pci_dev *ppdev; >> + u32 lspec; >> + __be32 lspec_be; >> + __be32 laddr[3]; >> + u8 pin; >> + int rc; >> + >> + /* Check if we have a device node, if yes, fallback to standard OF >> + * parsing >> + */ >> + dn = pci_device_to_OF_node(pdev); >> + if (dn) { >> + rc = of_irq_map_one(dn, 0, out_irq); >> + if (!rc) >> + return rc; >> + } >> + >> + /* Ok, we don't, time to have fun. Let's start by building up an >> + * interrupt spec. we assume #interrupt-cells is 1, which is standard >> + * for PCI. If you do different, then don't use that routine. >> + */ >> + rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); >> + if (rc != 0) >> + return rc; >> + /* No pin, exit */ >> + if (pin == 0) >> + return -ENODEV; >> + >> + /* Now we walk up the PCI tree */ >> + lspec = pin; >> + for (;;) { >> + /* Get the pci_dev of our parent */ >> + ppdev = pdev->bus->self; >> + >> + /* Ouch, it's a host bridge... */ >> + if (ppdev == NULL) { >> + ppnode = pci_bus_to_OF_node(pdev->bus); >> + >> + /* No node for host bridge ? give up */ >> + if (ppnode == NULL) >> + return -EINVAL; >> + } else { >> + /* We found a P2P bridge, check if it has a node */ >> + ppnode = pci_device_to_OF_node(ppdev); >> + } >> + >> + /* Ok, we have found a parent with a device-node, hand over to >> + * the OF parsing code. >> + * We build a unit address from the linux device to be used for >> + * resolution. Note that we use the linux bus number which may >> + * not match your firmware bus numbering. >> + * Fortunately, in most cases, interrupt-map-mask doesn't >> + * include the bus number as part of the matching. >> + * You should still be careful about that though if you intend >> + * to rely on this function (you ship a firmware that doesn't >> + * create device nodes for all PCI devices). >> + */ >> + if (ppnode) >> + break; >> + >> + /* We can only get here if we hit a P2P bridge with no node, >> + * let's do standard swizzling and try again >> + */ >> + lspec = pci_swizzle_interrupt_pin(pdev, lspec); >> + pdev = ppdev; >> + } >> + >> + lspec_be = cpu_to_be32(lspec); >> + laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); >> + laddr[1] = laddr[2] = cpu_to_be32(0); >> + return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq); >> +} >> +EXPORT_SYMBOL_GPL(of_irq_map_pci); >> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h >> new file mode 100644 >> index 0000000..9b0ba67 >> --- /dev/null >> +++ b/include/linux/of_pci.h >> @@ -0,0 +1,20 @@ >> +#ifndef __OF_PCI_H >> +#define __OF_PCI_H >> + >> +#include <linux/pci.h> >> + >> +/** >> + * of_irq_map_pci - Resolve the interrupt for a PCI device >> + * @pdev: the device whose interrupt is to be resolved >> + * @out_irq: structure of_irq filled by this function >> + * >> + * This function resolves the PCI interrupt for a given PCI device. If a >> + * device-node exists for a given pci_dev, it will use normal OF tree >> + * walking. If not, it will implement standard swizzling and walk up the >> + * PCI tree until an device-node is found, at which point it will finish >> + * resolving using the OF tree walking. >> + */ >> +struct pci_dev; >> +struct of_irq; >> +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); >> +#endif >> -- >> 1.7.3.2 >> >> _______________________________________________ >> devicetree-discuss mailing list >> devicetree-discuss@lists•ozlabs.org >> https://lists.ozlabs.org/listinfo/devicetree-discuss >> > > > -- Michal Simek, Ing. (M.Eng) w: www.monstr.eu p: +42-0-721842854 Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/ Microblaze U-BOOT custodian ^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2011-02-17 7:49 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1295843342-1122-1-git-send-email-bigeasy@linutronix.de>
[not found] ` <1295843342-1122-8-git-send-email-bigeasy@linutronix.de>
2011-02-16 21:53 ` [PATCH OF 07/14] of: move of_irq_map_pci() into generic code Grant Likely
2011-02-17 7:49 ` Michal Simek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox