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

Commit 3262b21e authored by Ganesan Ramalingam's avatar Ganesan Ramalingam Committed by Ralf Baechle
Browse files

MIPS: Netlogic: XLP9XX USB support



XLP9XX has a USB 3.0 controller on-chip with 2 xHCI ports. The USB
block is similar to the one on XLP2XX, so update usb-init-xlp2.c
to handle XLP9XX as well.

Signed-off-by: default avatarGanesan Ramalingam <ganesanr@broadcom.com>
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/6285/
parent b6ba1c52
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -188,6 +188,9 @@
#define PCI_DEVICE_ID_NLM_MMC		0x1018
#define PCI_DEVICE_ID_NLM_XHCI		0x101d

#define PCI_DEVICE_ID_XLP9XX_SATA	0x901A
#define PCI_DEVICE_ID_XLP9XX_XHCI	0x901D

#ifndef __ASSEMBLY__

#define nlm_read_pci_reg(b, r)		nlm_read_reg(b, r)
+2 −0
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@
#define PIC_2XX_XHCI_0_IRQ		23
#define PIC_2XX_XHCI_1_IRQ		24
#define PIC_2XX_XHCI_2_IRQ		25
#define PIC_9XX_XHCI_0_IRQ		23
#define PIC_9XX_XHCI_1_IRQ		24

#define PIC_MMC_IRQ			29
#define PIC_I2C_0_IRQ			30
+4 −0
Original line number Diff line number Diff line
@@ -72,6 +72,10 @@ int nlm_irq_to_irt(int irq)
	/* bypass for 9xx */
	if (cpu_is_xlp9xx()) {
		switch (irq) {
		case PIC_9XX_XHCI_0_IRQ:
			return 114;
		case PIC_9XX_XHCI_1_IRQ:
			return 115;
		case PIC_UART_0_IRQ:
			return 133;
		case PIC_UART_1_IRQ:
+75 −13
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/platform_device.h>
#include <linux/irq.h>

@@ -84,11 +85,13 @@
#define nlm_write_usb_reg(b, r, v)	nlm_write_reg(b, r, v)

#define nlm_xlpii_get_usb_pcibase(node, inst)			\
	nlm_pcicfg_base(XLP2XX_IO_USB_OFFSET(node, inst))
			nlm_pcicfg_base(cpu_is_xlp9xx() ?	\
			XLP9XX_IO_USB_OFFSET(node, inst) :	\
			XLP2XX_IO_USB_OFFSET(node, inst))
#define nlm_xlpii_get_usb_regbase(node, inst)		\
	(nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)

static void xlpii_usb_ack(struct irq_data *data)
static void xlp2xx_usb_ack(struct irq_data *data)
{
	u64 port_addr;

@@ -109,6 +112,29 @@ static void xlpii_usb_ack(struct irq_data *data)
	nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
}

static void xlp9xx_usb_ack(struct irq_data *data)
{
	u64 port_addr;
	int node, irq;

	/* Find the node and irq on the node */
	irq = data->irq % NLM_IRQS_PER_NODE;
	node = data->irq / NLM_IRQS_PER_NODE;

	switch (irq) {
	case PIC_9XX_XHCI_0_IRQ:
		port_addr = nlm_xlpii_get_usb_regbase(node, 1);
		break;
	case PIC_9XX_XHCI_1_IRQ:
		port_addr = nlm_xlpii_get_usb_regbase(node, 2);
		break;
	default:
		pr_err("No matching USB irq %d node  %d!\n", irq, node);
		return;
	}
	nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
}

static void nlm_xlpii_usb_hw_reset(int node, int port)
{
	u64 port_addr, xhci_base, pci_base;
@@ -178,17 +204,33 @@ static void nlm_xlpii_usb_hw_reset(int node, int port)

static int __init nlm_platform_xlpii_usb_init(void)
{
	int node;

	if (!cpu_is_xlpii())
		return 0;

	if (!cpu_is_xlp9xx()) {
		/* XLP 2XX single node */
		pr_info("Initializing 2XX USB Interface\n");
		nlm_xlpii_usb_hw_reset(0, 1);
		nlm_xlpii_usb_hw_reset(0, 2);
		nlm_xlpii_usb_hw_reset(0, 3);
	nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlpii_usb_ack);
	nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlpii_usb_ack);
	nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlpii_usb_ack);
		nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlp2xx_usb_ack);
		nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlp2xx_usb_ack);
		nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlp2xx_usb_ack);
		return 0;
	}

	/* XLP 9XX, multi-node */
	pr_info("Initializing 9XX USB Interface\n");
	for (node = 0; node < NLM_NR_NODES; node++) {
		if (!nlm_node_present(node))
			continue;
		nlm_xlpii_usb_hw_reset(node, 1);
		nlm_xlpii_usb_hw_reset(node, 2);
		nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_0_IRQ, xlp9xx_usb_ack);
		nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_1_IRQ, xlp9xx_usb_ack);
	}
	return 0;
}

@@ -196,8 +238,26 @@ arch_initcall(nlm_platform_xlpii_usb_init);

static u64 xlp_usb_dmamask = ~(u32)0;

/* Fixup IRQ for USB devices on XLP the SoC PCIe bus */
static void nlm_usb_fixup_final(struct pci_dev *dev)
/* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */
static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev)
{
	int node;

	node = xlp_socdev_to_node(dev);
	dev->dev.dma_mask		= &xlp_usb_dmamask;
	dev->dev.coherent_dma_mask	= DMA_BIT_MASK(32);
	switch (dev->devfn) {
	case 0x21:
		dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_0_IRQ);
		break;
	case 0x22:
		dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ);
		break;
	}
}

/* Fixup the IRQ for USB devices which is exist on XLP2XX SOC PCIE bus */
static void nlm_xlp2xx_usb_fixup_final(struct pci_dev *dev)
{
	dev->dev.dma_mask		= &xlp_usb_dmamask;
	dev->dev.coherent_dma_mask	= DMA_BIT_MASK(32);
@@ -214,5 +274,7 @@ static void nlm_usb_fixup_final(struct pci_dev *dev)
	}
}

DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_XHCI,
		nlm_xlp9xx_usb_fixup_final);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI,
		nlm_usb_fixup_final);
		nlm_xlp2xx_usb_fixup_final);