diff options
author | Ganesan Ramalingam <ganesanr@broadcom.com> | 2013-12-21 06:22:28 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-01-24 16:39:49 -0500 |
commit | 3262b21ef8523175f0758f4deccec048e73d5b18 (patch) | |
tree | 0728cd36407fcd39c3c21c2698ff859cba3c78fd /arch/mips/netlogic | |
parent | b6ba1c5294c3f51fd4cf8b0d60de4ba82ef2a1c9 (diff) |
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: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/6285/
Diffstat (limited to 'arch/mips/netlogic')
-rw-r--r-- | arch/mips/netlogic/xlp/nlm_hal.c | 4 | ||||
-rw-r--r-- | arch/mips/netlogic/xlp/usb-init-xlp2.c | 88 |
2 files changed, 79 insertions, 13 deletions
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index e7ff2d37a464..997cd9ee10de 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c | |||
@@ -72,6 +72,10 @@ int nlm_irq_to_irt(int irq) | |||
72 | /* bypass for 9xx */ | 72 | /* bypass for 9xx */ |
73 | if (cpu_is_xlp9xx()) { | 73 | if (cpu_is_xlp9xx()) { |
74 | switch (irq) { | 74 | switch (irq) { |
75 | case PIC_9XX_XHCI_0_IRQ: | ||
76 | return 114; | ||
77 | case PIC_9XX_XHCI_1_IRQ: | ||
78 | return 115; | ||
75 | case PIC_UART_0_IRQ: | 79 | case PIC_UART_0_IRQ: |
76 | return 133; | 80 | return 133; |
77 | case PIC_UART_1_IRQ: | 81 | case PIC_UART_1_IRQ: |
diff --git a/arch/mips/netlogic/xlp/usb-init-xlp2.c b/arch/mips/netlogic/xlp/usb-init-xlp2.c index 36e9c22afc46..17ade1ce5dfd 100644 --- a/arch/mips/netlogic/xlp/usb-init-xlp2.c +++ b/arch/mips/netlogic/xlp/usb-init-xlp2.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | #include <linux/pci_ids.h> | ||
40 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
41 | #include <linux/irq.h> | 42 | #include <linux/irq.h> |
42 | 43 | ||
@@ -83,12 +84,14 @@ | |||
83 | #define nlm_read_usb_reg(b, r) nlm_read_reg(b, r) | 84 | #define nlm_read_usb_reg(b, r) nlm_read_reg(b, r) |
84 | #define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v) | 85 | #define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v) |
85 | 86 | ||
86 | #define nlm_xlpii_get_usb_pcibase(node, inst) \ | 87 | #define nlm_xlpii_get_usb_pcibase(node, inst) \ |
87 | nlm_pcicfg_base(XLP2XX_IO_USB_OFFSET(node, inst)) | 88 | nlm_pcicfg_base(cpu_is_xlp9xx() ? \ |
89 | XLP9XX_IO_USB_OFFSET(node, inst) : \ | ||
90 | XLP2XX_IO_USB_OFFSET(node, inst)) | ||
88 | #define nlm_xlpii_get_usb_regbase(node, inst) \ | 91 | #define nlm_xlpii_get_usb_regbase(node, inst) \ |
89 | (nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ) | 92 | (nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ) |
90 | 93 | ||
91 | static void xlpii_usb_ack(struct irq_data *data) | 94 | static void xlp2xx_usb_ack(struct irq_data *data) |
92 | { | 95 | { |
93 | u64 port_addr; | 96 | u64 port_addr; |
94 | 97 | ||
@@ -109,6 +112,29 @@ static void xlpii_usb_ack(struct irq_data *data) | |||
109 | nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff); | 112 | nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff); |
110 | } | 113 | } |
111 | 114 | ||
115 | static void xlp9xx_usb_ack(struct irq_data *data) | ||
116 | { | ||
117 | u64 port_addr; | ||
118 | int node, irq; | ||
119 | |||
120 | /* Find the node and irq on the node */ | ||
121 | irq = data->irq % NLM_IRQS_PER_NODE; | ||
122 | node = data->irq / NLM_IRQS_PER_NODE; | ||
123 | |||
124 | switch (irq) { | ||
125 | case PIC_9XX_XHCI_0_IRQ: | ||
126 | port_addr = nlm_xlpii_get_usb_regbase(node, 1); | ||
127 | break; | ||
128 | case PIC_9XX_XHCI_1_IRQ: | ||
129 | port_addr = nlm_xlpii_get_usb_regbase(node, 2); | ||
130 | break; | ||
131 | default: | ||
132 | pr_err("No matching USB irq %d node %d!\n", irq, node); | ||
133 | return; | ||
134 | } | ||
135 | nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff); | ||
136 | } | ||
137 | |||
112 | static void nlm_xlpii_usb_hw_reset(int node, int port) | 138 | static void nlm_xlpii_usb_hw_reset(int node, int port) |
113 | { | 139 | { |
114 | u64 port_addr, xhci_base, pci_base; | 140 | u64 port_addr, xhci_base, pci_base; |
@@ -178,17 +204,33 @@ static void nlm_xlpii_usb_hw_reset(int node, int port) | |||
178 | 204 | ||
179 | static int __init nlm_platform_xlpii_usb_init(void) | 205 | static int __init nlm_platform_xlpii_usb_init(void) |
180 | { | 206 | { |
207 | int node; | ||
208 | |||
181 | if (!cpu_is_xlpii()) | 209 | if (!cpu_is_xlpii()) |
182 | return 0; | 210 | return 0; |
183 | 211 | ||
184 | pr_info("Initializing 2XX USB Interface\n"); | 212 | if (!cpu_is_xlp9xx()) { |
185 | nlm_xlpii_usb_hw_reset(0, 1); | 213 | /* XLP 2XX single node */ |
186 | nlm_xlpii_usb_hw_reset(0, 2); | 214 | pr_info("Initializing 2XX USB Interface\n"); |
187 | nlm_xlpii_usb_hw_reset(0, 3); | 215 | nlm_xlpii_usb_hw_reset(0, 1); |
188 | nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlpii_usb_ack); | 216 | nlm_xlpii_usb_hw_reset(0, 2); |
189 | nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlpii_usb_ack); | 217 | nlm_xlpii_usb_hw_reset(0, 3); |
190 | nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlpii_usb_ack); | 218 | nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlp2xx_usb_ack); |
219 | nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlp2xx_usb_ack); | ||
220 | nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlp2xx_usb_ack); | ||
221 | return 0; | ||
222 | } | ||
191 | 223 | ||
224 | /* XLP 9XX, multi-node */ | ||
225 | pr_info("Initializing 9XX USB Interface\n"); | ||
226 | for (node = 0; node < NLM_NR_NODES; node++) { | ||
227 | if (!nlm_node_present(node)) | ||
228 | continue; | ||
229 | nlm_xlpii_usb_hw_reset(node, 1); | ||
230 | nlm_xlpii_usb_hw_reset(node, 2); | ||
231 | nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_0_IRQ, xlp9xx_usb_ack); | ||
232 | nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_1_IRQ, xlp9xx_usb_ack); | ||
233 | } | ||
192 | return 0; | 234 | return 0; |
193 | } | 235 | } |
194 | 236 | ||
@@ -196,8 +238,26 @@ arch_initcall(nlm_platform_xlpii_usb_init); | |||
196 | 238 | ||
197 | static u64 xlp_usb_dmamask = ~(u32)0; | 239 | static u64 xlp_usb_dmamask = ~(u32)0; |
198 | 240 | ||
199 | /* Fixup IRQ for USB devices on XLP the SoC PCIe bus */ | 241 | /* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */ |
200 | static void nlm_usb_fixup_final(struct pci_dev *dev) | 242 | static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev) |
243 | { | ||
244 | int node; | ||
245 | |||
246 | node = xlp_socdev_to_node(dev); | ||
247 | dev->dev.dma_mask = &xlp_usb_dmamask; | ||
248 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
249 | switch (dev->devfn) { | ||
250 | case 0x21: | ||
251 | dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_0_IRQ); | ||
252 | break; | ||
253 | case 0x22: | ||
254 | dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ); | ||
255 | break; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | /* Fixup the IRQ for USB devices which is exist on XLP2XX SOC PCIE bus */ | ||
260 | static void nlm_xlp2xx_usb_fixup_final(struct pci_dev *dev) | ||
201 | { | 261 | { |
202 | dev->dev.dma_mask = &xlp_usb_dmamask; | 262 | dev->dev.dma_mask = &xlp_usb_dmamask; |
203 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | 263 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); |
@@ -214,5 +274,7 @@ static void nlm_usb_fixup_final(struct pci_dev *dev) | |||
214 | } | 274 | } |
215 | } | 275 | } |
216 | 276 | ||
277 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_XHCI, | ||
278 | nlm_xlp9xx_usb_fixup_final); | ||
217 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI, | 279 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI, |
218 | nlm_usb_fixup_final); | 280 | nlm_xlp2xx_usb_fixup_final); |