xref: /OK3568_Linux_fs/kernel/arch/mips/netlogic/xlp/usb-init-xlp2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2003-2013 Broadcom Corporation
3*4882a593Smuzhiyun  * All Rights Reserved
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * This software is available to you under a choice of one of two
6*4882a593Smuzhiyun  * licenses.  You may choose to be licensed under the terms of the GNU
7*4882a593Smuzhiyun  * General Public License (GPL) Version 2, available from the file
8*4882a593Smuzhiyun  * COPYING in the main directory of this source tree, or the Broadcom
9*4882a593Smuzhiyun  * license below:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
12*4882a593Smuzhiyun  * modification, are permitted provided that the following conditions
13*4882a593Smuzhiyun  * are met:
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * 1. Redistributions of source code must retain the above copyright
16*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer.
17*4882a593Smuzhiyun  * 2. Redistributions in binary form must reproduce the above copyright
18*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer in
19*4882a593Smuzhiyun  *    the documentation and/or other materials provided with the
20*4882a593Smuzhiyun  *    distribution.
21*4882a593Smuzhiyun  *
22*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
23*4882a593Smuzhiyun  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24*4882a593Smuzhiyun  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*4882a593Smuzhiyun  * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
26*4882a593Smuzhiyun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28*4882a593Smuzhiyun  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29*4882a593Smuzhiyun  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30*4882a593Smuzhiyun  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31*4882a593Smuzhiyun  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32*4882a593Smuzhiyun  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include <linux/dma-mapping.h>
36*4882a593Smuzhiyun #include <linux/kernel.h>
37*4882a593Smuzhiyun #include <linux/delay.h>
38*4882a593Smuzhiyun #include <linux/init.h>
39*4882a593Smuzhiyun #include <linux/pci.h>
40*4882a593Smuzhiyun #include <linux/pci_ids.h>
41*4882a593Smuzhiyun #include <linux/platform_device.h>
42*4882a593Smuzhiyun #include <linux/irq.h>
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #include <asm/netlogic/common.h>
45*4882a593Smuzhiyun #include <asm/netlogic/haldefs.h>
46*4882a593Smuzhiyun #include <asm/netlogic/xlp-hal/iomap.h>
47*4882a593Smuzhiyun #include <asm/netlogic/xlp-hal/xlp.h>
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #define XLPII_USB3_CTL_0		0xc0
50*4882a593Smuzhiyun #define XLPII_VAUXRST			BIT(0)
51*4882a593Smuzhiyun #define XLPII_VCCRST			BIT(1)
52*4882a593Smuzhiyun #define XLPII_NUM2PORT			9
53*4882a593Smuzhiyun #define XLPII_NUM3PORT			13
54*4882a593Smuzhiyun #define XLPII_RTUNEREQ			BIT(20)
55*4882a593Smuzhiyun #define XLPII_MS_CSYSREQ		BIT(21)
56*4882a593Smuzhiyun #define XLPII_XS_CSYSREQ		BIT(22)
57*4882a593Smuzhiyun #define XLPII_RETENABLEN		BIT(23)
58*4882a593Smuzhiyun #define XLPII_TX2RX			BIT(24)
59*4882a593Smuzhiyun #define XLPII_XHCIREV			BIT(25)
60*4882a593Smuzhiyun #define XLPII_ECCDIS			BIT(26)
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #define XLPII_USB3_INT_REG		0xc2
63*4882a593Smuzhiyun #define XLPII_USB3_INT_MASK		0xc3
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define XLPII_USB_PHY_TEST		0xc6
66*4882a593Smuzhiyun #define XLPII_PRESET			BIT(0)
67*4882a593Smuzhiyun #define XLPII_ATERESET			BIT(1)
68*4882a593Smuzhiyun #define XLPII_LOOPEN			BIT(2)
69*4882a593Smuzhiyun #define XLPII_TESTPDHSP			BIT(3)
70*4882a593Smuzhiyun #define XLPII_TESTPDSSP			BIT(4)
71*4882a593Smuzhiyun #define XLPII_TESTBURNIN		BIT(5)
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun #define XLPII_USB_PHY_LOS_LV		0xc9
74*4882a593Smuzhiyun #define XLPII_LOSLEV			0
75*4882a593Smuzhiyun #define XLPII_LOSBIAS			5
76*4882a593Smuzhiyun #define XLPII_SQRXTX			8
77*4882a593Smuzhiyun #define XLPII_TXBOOST			11
78*4882a593Smuzhiyun #define XLPII_RSLKSEL			16
79*4882a593Smuzhiyun #define XLPII_FSEL			20
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun #define XLPII_USB_RFCLK_REG		0xcc
82*4882a593Smuzhiyun #define XLPII_VVLD			30
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #define nlm_read_usb_reg(b, r)		nlm_read_reg(b, r)
85*4882a593Smuzhiyun #define nlm_write_usb_reg(b, r, v)	nlm_write_reg(b, r, v)
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun #define nlm_xlpii_get_usb_pcibase(node, inst)			\
88*4882a593Smuzhiyun 			nlm_pcicfg_base(cpu_is_xlp9xx() ?	\
89*4882a593Smuzhiyun 			XLP9XX_IO_USB_OFFSET(node, inst) :	\
90*4882a593Smuzhiyun 			XLP2XX_IO_USB_OFFSET(node, inst))
91*4882a593Smuzhiyun #define nlm_xlpii_get_usb_regbase(node, inst)		\
92*4882a593Smuzhiyun 	(nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
93*4882a593Smuzhiyun 
xlp2xx_usb_ack(struct irq_data * data)94*4882a593Smuzhiyun static void xlp2xx_usb_ack(struct irq_data *data)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	u64 port_addr;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	switch (data->irq) {
99*4882a593Smuzhiyun 	case PIC_2XX_XHCI_0_IRQ:
100*4882a593Smuzhiyun 		port_addr = nlm_xlpii_get_usb_regbase(0, 1);
101*4882a593Smuzhiyun 		break;
102*4882a593Smuzhiyun 	case PIC_2XX_XHCI_1_IRQ:
103*4882a593Smuzhiyun 		port_addr = nlm_xlpii_get_usb_regbase(0, 2);
104*4882a593Smuzhiyun 		break;
105*4882a593Smuzhiyun 	case PIC_2XX_XHCI_2_IRQ:
106*4882a593Smuzhiyun 		port_addr = nlm_xlpii_get_usb_regbase(0, 3);
107*4882a593Smuzhiyun 		break;
108*4882a593Smuzhiyun 	default:
109*4882a593Smuzhiyun 		pr_err("No matching USB irq!\n");
110*4882a593Smuzhiyun 		return;
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 	nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
xlp9xx_usb_ack(struct irq_data * data)115*4882a593Smuzhiyun static void xlp9xx_usb_ack(struct irq_data *data)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	u64 port_addr;
118*4882a593Smuzhiyun 	int node, irq;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	/* Find the node and irq on the node */
121*4882a593Smuzhiyun 	irq = data->irq % NLM_IRQS_PER_NODE;
122*4882a593Smuzhiyun 	node = data->irq / NLM_IRQS_PER_NODE;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	switch (irq) {
125*4882a593Smuzhiyun 	case PIC_9XX_XHCI_0_IRQ:
126*4882a593Smuzhiyun 		port_addr = nlm_xlpii_get_usb_regbase(node, 1);
127*4882a593Smuzhiyun 		break;
128*4882a593Smuzhiyun 	case PIC_9XX_XHCI_1_IRQ:
129*4882a593Smuzhiyun 		port_addr = nlm_xlpii_get_usb_regbase(node, 2);
130*4882a593Smuzhiyun 		break;
131*4882a593Smuzhiyun 	case PIC_9XX_XHCI_2_IRQ:
132*4882a593Smuzhiyun 		port_addr = nlm_xlpii_get_usb_regbase(node, 3);
133*4882a593Smuzhiyun 		break;
134*4882a593Smuzhiyun 	default:
135*4882a593Smuzhiyun 		pr_err("No matching USB irq %d node  %d!\n", irq, node);
136*4882a593Smuzhiyun 		return;
137*4882a593Smuzhiyun 	}
138*4882a593Smuzhiyun 	nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
nlm_xlpii_usb_hw_reset(int node,int port)141*4882a593Smuzhiyun static void nlm_xlpii_usb_hw_reset(int node, int port)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	u64 port_addr, xhci_base, pci_base;
144*4882a593Smuzhiyun 	void __iomem *corebase;
145*4882a593Smuzhiyun 	u32 val;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	port_addr = nlm_xlpii_get_usb_regbase(node, port);
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	/* Set frequency */
150*4882a593Smuzhiyun 	val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV);
151*4882a593Smuzhiyun 	val &= ~(0x3f << XLPII_FSEL);
152*4882a593Smuzhiyun 	val |= (0x27 << XLPII_FSEL);
153*4882a593Smuzhiyun 	nlm_write_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV, val);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	val = nlm_read_usb_reg(port_addr, XLPII_USB_RFCLK_REG);
156*4882a593Smuzhiyun 	val |= (1 << XLPII_VVLD);
157*4882a593Smuzhiyun 	nlm_write_usb_reg(port_addr, XLPII_USB_RFCLK_REG, val);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	/* PHY reset */
160*4882a593Smuzhiyun 	val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_TEST);
161*4882a593Smuzhiyun 	val &= (XLPII_ATERESET | XLPII_LOOPEN | XLPII_TESTPDHSP
162*4882a593Smuzhiyun 		| XLPII_TESTPDSSP | XLPII_TESTBURNIN);
163*4882a593Smuzhiyun 	nlm_write_usb_reg(port_addr, XLPII_USB_PHY_TEST, val);
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	/* Setup control register */
166*4882a593Smuzhiyun 	val =  XLPII_VAUXRST | XLPII_VCCRST | (1 << XLPII_NUM2PORT)
167*4882a593Smuzhiyun 		| (1 << XLPII_NUM3PORT) | XLPII_MS_CSYSREQ | XLPII_XS_CSYSREQ
168*4882a593Smuzhiyun 		| XLPII_RETENABLEN | XLPII_XHCIREV;
169*4882a593Smuzhiyun 	nlm_write_usb_reg(port_addr, XLPII_USB3_CTL_0, val);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	/* Enable interrupts */
172*4882a593Smuzhiyun 	nlm_write_usb_reg(port_addr, XLPII_USB3_INT_MASK, 0x00000001);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	/* Clear all interrupts */
175*4882a593Smuzhiyun 	nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	udelay(2000);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	/* XHCI configuration at PCI mem */
180*4882a593Smuzhiyun 	pci_base = nlm_xlpii_get_usb_pcibase(node, port);
181*4882a593Smuzhiyun 	xhci_base = nlm_read_usb_reg(pci_base, 0x4) & ~0xf;
182*4882a593Smuzhiyun 	corebase = ioremap(xhci_base, 0x10000);
183*4882a593Smuzhiyun 	if (!corebase)
184*4882a593Smuzhiyun 		return;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	writel(0x240002, corebase + 0xc2c0);
187*4882a593Smuzhiyun 	/* GCTL 0xc110 */
188*4882a593Smuzhiyun 	val = readl(corebase + 0xc110);
189*4882a593Smuzhiyun 	val &= ~(0x3 << 12);
190*4882a593Smuzhiyun 	val |= (1 << 12);
191*4882a593Smuzhiyun 	writel(val, corebase + 0xc110);
192*4882a593Smuzhiyun 	udelay(100);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	/* PHYCFG 0xc200 */
195*4882a593Smuzhiyun 	val = readl(corebase + 0xc200);
196*4882a593Smuzhiyun 	val &= ~(1 << 6);
197*4882a593Smuzhiyun 	writel(val, corebase + 0xc200);
198*4882a593Smuzhiyun 	udelay(100);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	/* PIPECTL 0xc2c0 */
201*4882a593Smuzhiyun 	val = readl(corebase + 0xc2c0);
202*4882a593Smuzhiyun 	val &= ~(1 << 17);
203*4882a593Smuzhiyun 	writel(val, corebase + 0xc2c0);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	iounmap(corebase);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
nlm_platform_xlpii_usb_init(void)208*4882a593Smuzhiyun static int __init nlm_platform_xlpii_usb_init(void)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	int node;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	if (!cpu_is_xlpii())
213*4882a593Smuzhiyun 		return 0;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	if (!cpu_is_xlp9xx()) {
216*4882a593Smuzhiyun 		/* XLP 2XX single node */
217*4882a593Smuzhiyun 		pr_info("Initializing 2XX USB Interface\n");
218*4882a593Smuzhiyun 		nlm_xlpii_usb_hw_reset(0, 1);
219*4882a593Smuzhiyun 		nlm_xlpii_usb_hw_reset(0, 2);
220*4882a593Smuzhiyun 		nlm_xlpii_usb_hw_reset(0, 3);
221*4882a593Smuzhiyun 		nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlp2xx_usb_ack);
222*4882a593Smuzhiyun 		nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlp2xx_usb_ack);
223*4882a593Smuzhiyun 		nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlp2xx_usb_ack);
224*4882a593Smuzhiyun 		return 0;
225*4882a593Smuzhiyun 	}
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	/* XLP 9XX, multi-node */
228*4882a593Smuzhiyun 	pr_info("Initializing 9XX/5XX USB Interface\n");
229*4882a593Smuzhiyun 	for (node = 0; node < NLM_NR_NODES; node++) {
230*4882a593Smuzhiyun 		if (!nlm_node_present(node))
231*4882a593Smuzhiyun 			continue;
232*4882a593Smuzhiyun 		nlm_xlpii_usb_hw_reset(node, 1);
233*4882a593Smuzhiyun 		nlm_xlpii_usb_hw_reset(node, 2);
234*4882a593Smuzhiyun 		nlm_xlpii_usb_hw_reset(node, 3);
235*4882a593Smuzhiyun 		nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_0_IRQ, xlp9xx_usb_ack);
236*4882a593Smuzhiyun 		nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_1_IRQ, xlp9xx_usb_ack);
237*4882a593Smuzhiyun 		nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_2_IRQ, xlp9xx_usb_ack);
238*4882a593Smuzhiyun 	}
239*4882a593Smuzhiyun 	return 0;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun arch_initcall(nlm_platform_xlpii_usb_init);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun static u64 xlp_usb_dmamask = ~(u32)0;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun /* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */
nlm_xlp9xx_usb_fixup_final(struct pci_dev * dev)247*4882a593Smuzhiyun static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun 	int node;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	node = xlp_socdev_to_node(dev);
252*4882a593Smuzhiyun 	dev->dev.dma_mask		= &xlp_usb_dmamask;
253*4882a593Smuzhiyun 	dev->dev.coherent_dma_mask	= DMA_BIT_MASK(32);
254*4882a593Smuzhiyun 	switch (dev->devfn) {
255*4882a593Smuzhiyun 	case 0x21:
256*4882a593Smuzhiyun 		dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_0_IRQ);
257*4882a593Smuzhiyun 		break;
258*4882a593Smuzhiyun 	case 0x22:
259*4882a593Smuzhiyun 		dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ);
260*4882a593Smuzhiyun 		break;
261*4882a593Smuzhiyun 	case 0x23:
262*4882a593Smuzhiyun 		dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_2_IRQ);
263*4882a593Smuzhiyun 		break;
264*4882a593Smuzhiyun 	}
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun /* Fixup the IRQ for USB devices which is exist on XLP2XX SOC PCIE bus */
nlm_xlp2xx_usb_fixup_final(struct pci_dev * dev)268*4882a593Smuzhiyun static void nlm_xlp2xx_usb_fixup_final(struct pci_dev *dev)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	dev->dev.dma_mask		= &xlp_usb_dmamask;
271*4882a593Smuzhiyun 	dev->dev.coherent_dma_mask	= DMA_BIT_MASK(32);
272*4882a593Smuzhiyun 	switch (dev->devfn) {
273*4882a593Smuzhiyun 	case 0x21:
274*4882a593Smuzhiyun 		dev->irq = PIC_2XX_XHCI_0_IRQ;
275*4882a593Smuzhiyun 		break;
276*4882a593Smuzhiyun 	case 0x22:
277*4882a593Smuzhiyun 		dev->irq = PIC_2XX_XHCI_1_IRQ;
278*4882a593Smuzhiyun 		break;
279*4882a593Smuzhiyun 	case 0x23:
280*4882a593Smuzhiyun 		dev->irq = PIC_2XX_XHCI_2_IRQ;
281*4882a593Smuzhiyun 		break;
282*4882a593Smuzhiyun 	}
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_XHCI,
286*4882a593Smuzhiyun 		nlm_xlp9xx_usb_fixup_final);
287*4882a593Smuzhiyun DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI,
288*4882a593Smuzhiyun 		nlm_xlp2xx_usb_fixup_final);
289