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

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
...@@ -188,6 +188,9 @@ ...@@ -188,6 +188,9 @@
#define PCI_DEVICE_ID_NLM_MMC 0x1018 #define PCI_DEVICE_ID_NLM_MMC 0x1018
#define PCI_DEVICE_ID_NLM_XHCI 0x101d #define PCI_DEVICE_ID_NLM_XHCI 0x101d
#define PCI_DEVICE_ID_XLP9XX_SATA 0x901A
#define PCI_DEVICE_ID_XLP9XX_XHCI 0x901D
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#define nlm_read_pci_reg(b, r) nlm_read_reg(b, r) #define nlm_read_pci_reg(b, r) nlm_read_reg(b, r)
......
...@@ -50,6 +50,8 @@ ...@@ -50,6 +50,8 @@
#define PIC_2XX_XHCI_0_IRQ 23 #define PIC_2XX_XHCI_0_IRQ 23
#define PIC_2XX_XHCI_1_IRQ 24 #define PIC_2XX_XHCI_1_IRQ 24
#define PIC_2XX_XHCI_2_IRQ 25 #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_MMC_IRQ 29
#define PIC_I2C_0_IRQ 30 #define PIC_I2C_0_IRQ 30
......
...@@ -72,6 +72,10 @@ int nlm_irq_to_irt(int irq) ...@@ -72,6 +72,10 @@ int nlm_irq_to_irt(int irq)
/* bypass for 9xx */ /* bypass for 9xx */
if (cpu_is_xlp9xx()) { if (cpu_is_xlp9xx()) {
switch (irq) { switch (irq) {
case PIC_9XX_XHCI_0_IRQ:
return 114;
case PIC_9XX_XHCI_1_IRQ:
return 115;
case PIC_UART_0_IRQ: case PIC_UART_0_IRQ:
return 133; return 133;
case PIC_UART_1_IRQ: case PIC_UART_1_IRQ:
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/irq.h> #include <linux/irq.h>
...@@ -84,11 +85,13 @@ ...@@ -84,11 +85,13 @@
#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v) #define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v)
#define nlm_xlpii_get_usb_pcibase(node, inst) \ #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) \ #define nlm_xlpii_get_usb_regbase(node, inst) \
(nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ) (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; u64 port_addr;
...@@ -109,6 +112,29 @@ static void xlpii_usb_ack(struct irq_data *data) ...@@ -109,6 +112,29 @@ static void xlpii_usb_ack(struct irq_data *data)
nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff); 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) static void nlm_xlpii_usb_hw_reset(int node, int port)
{ {
u64 port_addr, xhci_base, pci_base; u64 port_addr, xhci_base, pci_base;
...@@ -178,17 +204,33 @@ static void nlm_xlpii_usb_hw_reset(int node, int port) ...@@ -178,17 +204,33 @@ static void nlm_xlpii_usb_hw_reset(int node, int port)
static int __init nlm_platform_xlpii_usb_init(void) static int __init nlm_platform_xlpii_usb_init(void)
{ {
int node;
if (!cpu_is_xlpii()) if (!cpu_is_xlpii())
return 0; return 0;
if (!cpu_is_xlp9xx()) {
/* XLP 2XX single node */
pr_info("Initializing 2XX USB Interface\n"); pr_info("Initializing 2XX USB Interface\n");
nlm_xlpii_usb_hw_reset(0, 1); nlm_xlpii_usb_hw_reset(0, 1);
nlm_xlpii_usb_hw_reset(0, 2); nlm_xlpii_usb_hw_reset(0, 2);
nlm_xlpii_usb_hw_reset(0, 3); 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_0_IRQ, xlp2xx_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_1_IRQ, xlp2xx_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_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; return 0;
} }
...@@ -196,8 +238,26 @@ arch_initcall(nlm_platform_xlpii_usb_init); ...@@ -196,8 +238,26 @@ arch_initcall(nlm_platform_xlpii_usb_init);
static u64 xlp_usb_dmamask = ~(u32)0; static u64 xlp_usb_dmamask = ~(u32)0;
/* Fixup IRQ for USB devices on XLP the SoC PCIe bus */ /* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */
static void nlm_usb_fixup_final(struct pci_dev *dev) 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.dma_mask = &xlp_usb_dmamask;
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
...@@ -214,5 +274,7 @@ static void nlm_usb_fixup_final(struct pci_dev *dev) ...@@ -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, DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI,
nlm_usb_fixup_final); nlm_xlp2xx_usb_fixup_final);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment