1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2003-2012 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/platform_device.h>
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #include <asm/netlogic/haldefs.h>
43*4882a593Smuzhiyun #include <asm/netlogic/xlp-hal/iomap.h>
44*4882a593Smuzhiyun #include <asm/netlogic/xlp-hal/xlp.h>
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun * USB glue logic registers, used only during initialization
48*4882a593Smuzhiyun */
49*4882a593Smuzhiyun #define USB_CTL_0 0x01
50*4882a593Smuzhiyun #define USB_PHY_0 0x0A
51*4882a593Smuzhiyun #define USB_PHY_RESET 0x01
52*4882a593Smuzhiyun #define USB_PHY_PORT_RESET_0 0x10
53*4882a593Smuzhiyun #define USB_PHY_PORT_RESET_1 0x20
54*4882a593Smuzhiyun #define USB_CONTROLLER_RESET 0x01
55*4882a593Smuzhiyun #define USB_INT_STATUS 0x0E
56*4882a593Smuzhiyun #define USB_INT_EN 0x0F
57*4882a593Smuzhiyun #define USB_PHY_INTERRUPT_EN 0x01
58*4882a593Smuzhiyun #define USB_OHCI_INTERRUPT_EN 0x02
59*4882a593Smuzhiyun #define USB_OHCI_INTERRUPT1_EN 0x04
60*4882a593Smuzhiyun #define USB_OHCI_INTERRUPT2_EN 0x08
61*4882a593Smuzhiyun #define USB_CTRL_INTERRUPT_EN 0x10
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun #define nlm_read_usb_reg(b, r) nlm_read_reg(b, r)
64*4882a593Smuzhiyun #define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v)
65*4882a593Smuzhiyun #define nlm_get_usb_pcibase(node, inst) \
66*4882a593Smuzhiyun nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst))
67*4882a593Smuzhiyun #define nlm_get_usb_regbase(node, inst) \
68*4882a593Smuzhiyun (nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
69*4882a593Smuzhiyun
nlm_usb_intr_en(int node,int port)70*4882a593Smuzhiyun static void nlm_usb_intr_en(int node, int port)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun uint32_t val;
73*4882a593Smuzhiyun uint64_t port_addr;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun port_addr = nlm_get_usb_regbase(node, port);
76*4882a593Smuzhiyun val = nlm_read_usb_reg(port_addr, USB_INT_EN);
77*4882a593Smuzhiyun val = USB_CTRL_INTERRUPT_EN | USB_OHCI_INTERRUPT_EN |
78*4882a593Smuzhiyun USB_OHCI_INTERRUPT1_EN | USB_OHCI_INTERRUPT2_EN;
79*4882a593Smuzhiyun nlm_write_usb_reg(port_addr, USB_INT_EN, val);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
nlm_usb_hw_reset(int node,int port)82*4882a593Smuzhiyun static void nlm_usb_hw_reset(int node, int port)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun uint64_t port_addr;
85*4882a593Smuzhiyun uint32_t val;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /* reset USB phy */
88*4882a593Smuzhiyun port_addr = nlm_get_usb_regbase(node, port);
89*4882a593Smuzhiyun val = nlm_read_usb_reg(port_addr, USB_PHY_0);
90*4882a593Smuzhiyun val &= ~(USB_PHY_RESET | USB_PHY_PORT_RESET_0 | USB_PHY_PORT_RESET_1);
91*4882a593Smuzhiyun nlm_write_usb_reg(port_addr, USB_PHY_0, val);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun mdelay(100);
94*4882a593Smuzhiyun val = nlm_read_usb_reg(port_addr, USB_CTL_0);
95*4882a593Smuzhiyun val &= ~(USB_CONTROLLER_RESET);
96*4882a593Smuzhiyun val |= 0x4;
97*4882a593Smuzhiyun nlm_write_usb_reg(port_addr, USB_CTL_0, val);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
nlm_platform_usb_init(void)100*4882a593Smuzhiyun static int __init nlm_platform_usb_init(void)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun if (cpu_is_xlpii())
103*4882a593Smuzhiyun return 0;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun pr_info("Initializing USB Interface\n");
106*4882a593Smuzhiyun nlm_usb_hw_reset(0, 0);
107*4882a593Smuzhiyun nlm_usb_hw_reset(0, 3);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* Enable PHY interrupts */
110*4882a593Smuzhiyun nlm_usb_intr_en(0, 0);
111*4882a593Smuzhiyun nlm_usb_intr_en(0, 3);
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun return 0;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun arch_initcall(nlm_platform_usb_init);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun static u64 xlp_usb_dmamask = ~(u32)0;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /* Fixup the IRQ for USB devices which is exist on XLP SOC PCIE bus */
nlm_usb_fixup_final(struct pci_dev * dev)121*4882a593Smuzhiyun static void nlm_usb_fixup_final(struct pci_dev *dev)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun dev->dev.dma_mask = &xlp_usb_dmamask;
124*4882a593Smuzhiyun dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
125*4882a593Smuzhiyun switch (dev->devfn) {
126*4882a593Smuzhiyun case 0x10:
127*4882a593Smuzhiyun dev->irq = PIC_EHCI_0_IRQ;
128*4882a593Smuzhiyun break;
129*4882a593Smuzhiyun case 0x11:
130*4882a593Smuzhiyun dev->irq = PIC_OHCI_0_IRQ;
131*4882a593Smuzhiyun break;
132*4882a593Smuzhiyun case 0x12:
133*4882a593Smuzhiyun dev->irq = PIC_OHCI_1_IRQ;
134*4882a593Smuzhiyun break;
135*4882a593Smuzhiyun case 0x13:
136*4882a593Smuzhiyun dev->irq = PIC_EHCI_1_IRQ;
137*4882a593Smuzhiyun break;
138*4882a593Smuzhiyun case 0x14:
139*4882a593Smuzhiyun dev->irq = PIC_OHCI_2_IRQ;
140*4882a593Smuzhiyun break;
141*4882a593Smuzhiyun case 0x15:
142*4882a593Smuzhiyun dev->irq = PIC_OHCI_3_IRQ;
143*4882a593Smuzhiyun break;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_EHCI,
147*4882a593Smuzhiyun nlm_usb_fixup_final);
148*4882a593Smuzhiyun DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_OHCI,
149*4882a593Smuzhiyun nlm_usb_fixup_final);
150