Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6ba1c52 authored by Jayachandran C's avatar Jayachandran C Committed by Ralf Baechle
Browse files

MIPS: PCI: Netlogic XLP9XX support



Add PCI support for Netlogic XLP9XX. The PCI registers and
SoC bus numbers have changed in XLP9XX.

Also skip a few (bus,dev,fn) combinations which have issues when
read.

Signed-off-by: default avatarJayachandran C <jchandra@broadcom.com>
Signed-off-by: default avatarJohn Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/6284/
parent 98d4884c
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -63,6 +63,12 @@
#define PCIE_INT_EN0			0x261
#define PCIE_INT_EN1			0x262

/* XLP9XX has basic changes */
#define PCIE_9XX_BYTE_SWAP_MEM_BASE	0x25c
#define PCIE_9XX_BYTE_SWAP_MEM_LIM	0x25d
#define PCIE_9XX_BYTE_SWAP_IO_BASE	0x25e
#define PCIE_9XX_BYTE_SWAP_IO_LIM	0x25f

/* other */
#define PCIE_NLINKS			4

@@ -78,8 +84,8 @@

#define nlm_read_pcie_reg(b, r)		nlm_read_reg(b, r)
#define nlm_write_pcie_reg(b, r, v)	nlm_write_reg(b, r, v)
#define nlm_get_pcie_base(node, inst)	\
			nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, inst))
#define nlm_get_pcie_base(node, inst)	nlm_pcicfg_base(cpu_is_xlp9xx() ? \
	XLP9XX_IO_PCIE_OFFSET(node, inst) : XLP_IO_PCIE_OFFSET(node, inst))

#ifdef CONFIG_PCI_MSI
void xlp_init_node_msi_irqs(int node, int link);
+3 −0
Original line number Diff line number Diff line
@@ -84,6 +84,9 @@ void xlp_mmu_init(void);
void nlm_hal_init(void);
int xlp_get_dram_map(int n, uint64_t *dram_map);

struct pci_dev;
int xlp_socdev_to_node(const struct pci_dev *dev);

/* Device tree related */
void xlp_early_init_devtree(void);
void *xlp_dt_init(void *fdtp);
+5 −0
Original line number Diff line number Diff line
@@ -76,6 +76,11 @@ int nlm_irq_to_irt(int irq)
			return 133;
		case PIC_UART_1_IRQ:
			return 134;
		case PIC_PCIE_LINK_LEGACY_IRQ(0):
		case PIC_PCIE_LINK_LEGACY_IRQ(1):
		case PIC_PCIE_LINK_LEGACY_IRQ(2):
		case PIC_PCIE_LINK_LEGACY_IRQ(3):
			return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
		}
		return -1;
	}
+74 −21
Original line number Diff line number Diff line
@@ -67,9 +67,22 @@ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn,
	u32 *cfgaddr;

	where &= ~3;
	if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954)
	if (cpu_is_xlp9xx()) {
		/* be very careful on SoC buses */
		if (bus->number == 0) {
			/* Scan only existing nodes - uboot bug? */
			if (PCI_SLOT(devfn) != 0 ||
					   !nlm_node_present(PCI_FUNC(devfn)))
				return 0xffffffff;

		} else if (bus->parent->number == 0) {	/* SoC bus */
			if (PCI_SLOT(devfn) == 0)	/* b.0.0 hangs */
				return 0xffffffff;
			if (devfn == 44)		/* b.5.4 hangs */
				return 0xffffffff;
		}
	} else if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954) {
		return 0xffffffff;
	}
	cfgaddr = (u32 *)(pci_config_base +
			pci_cfg_addr(bus->number, devfn, where));
	data = *cfgaddr;
@@ -167,18 +180,35 @@ struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev)
{
	struct pci_bus *bus, *p;

	/* Find the bridge on bus 0 */
	bus = dev->bus;

	if (cpu_is_xlp9xx()) {
		/* find bus with grand parent number == 0 */
		for (p = bus->parent; p && p->parent && p->parent->number != 0;
				p = p->parent)
			bus = p;
		return (p && p->parent) ? bus->self : NULL;
	} else {
		/* Find the bridge on bus 0 */
		for (p = bus->parent; p && p->number != 0; p = p->parent)
			bus = p;

		return p ? bus->self : NULL;
	}
}

int xlp_socdev_to_node(const struct pci_dev *lnkdev)
{
	if (cpu_is_xlp9xx())
		return PCI_FUNC(lnkdev->bus->self->devfn);
	else
		return PCI_SLOT(lnkdev->devfn) / 8;
}

int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	struct pci_dev *lnkdev;
	int lnkslot, lnkfunc;
	int lnkfunc, node;

	/*
	 * For XLP PCIe, there is an IRQ per Link, find out which
@@ -187,9 +217,11 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
	lnkdev = xlp_get_pcie_link(dev);
	if (lnkdev == NULL)
		return 0;

	lnkfunc = PCI_FUNC(lnkdev->devfn);
	lnkslot = PCI_SLOT(lnkdev->devfn);
	return nlm_irq_to_xirq(lnkslot / 8, PIC_PCIE_LINK_LEGACY_IRQ(lnkfunc));
	node = xlp_socdev_to_node(lnkdev);

	return nlm_irq_to_xirq(node, PIC_PCIE_LINK_LEGACY_IRQ(lnkfunc));
}

/* Do platform specific device initialization at pci_enable_device() time */
@@ -216,10 +248,30 @@ static void xlp_config_pci_bswap(int node, int link)
	 *  Enable byte swap in hardware. Program each link's PCIe SWAP regions
	 * from the link's address ranges.
	 */
	if (cpu_is_xlp9xx()) {
		reg = nlm_read_bridge_reg(nbubase,
				BRIDGE_9XX_PCIEMEM_BASE0 + link);
		nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_MEM_BASE, reg);

		reg = nlm_read_bridge_reg(nbubase,
				BRIDGE_9XX_PCIEMEM_LIMIT0 + link);
		nlm_write_pci_reg(lnkbase,
				PCIE_9XX_BYTE_SWAP_MEM_LIM, reg | 0xfff);

		reg = nlm_read_bridge_reg(nbubase,
				BRIDGE_9XX_PCIEIO_BASE0 + link);
		nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_IO_BASE, reg);

		reg = nlm_read_bridge_reg(nbubase,
				BRIDGE_9XX_PCIEIO_LIMIT0 + link);
		nlm_write_pci_reg(lnkbase,
				PCIE_9XX_BYTE_SWAP_IO_LIM, reg | 0xfff);
	} else {
		reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link);
		nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg);

	reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_LIMIT0 + link);
		reg = nlm_read_bridge_reg(nbubase,
					BRIDGE_PCIEMEM_LIMIT0 + link);
		nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff);

		reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link);
@@ -228,6 +280,7 @@ static void xlp_config_pci_bswap(int node, int link)
		reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link);
		nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff);
	}
}
#else
/* Swap configuration not needed in little-endian mode */
static inline void xlp_config_pci_bswap(int node, int link) {}
@@ -260,7 +313,7 @@ static int __init pcibios_init(void)

			/* put in intpin and irq - u-boot does not */
			reg = nlm_read_pci_reg(pciebase, 0xf);
			reg &= ~0x1fu;
			reg &= ~0x1ffu;
			reg |= (1 << 8) | PIC_PCIE_LINK_LEGACY_IRQ(link);
			nlm_write_pci_reg(pciebase, 0xf, reg);
			pr_info("XLP PCIe: Link %d-%d initialized.\n", n, link);