1/*
2 * Copyright (c) 2003-2012 Broadcom Corporation
3 * All Rights Reserved
4 *
5 * This software is available to you under a choice of one of two
6 * licenses.  You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the Broadcom
9 * license below:
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in
19 *    the documentation and/or other materials provided with the
20 *    distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <linux/dma-mapping.h>
36#include <linux/kernel.h>
37#include <linux/delay.h>
38#include <linux/init.h>
39#include <linux/pci.h>
40#include <linux/platform_device.h>
41
42#include <asm/netlogic/haldefs.h>
43#include <asm/netlogic/xlp-hal/iomap.h>
44#include <asm/netlogic/xlp-hal/xlp.h>
45
46/*
47 * USB glue logic registers, used only during initialization
48 */
49#define USB_CTL_0			0x01
50#define USB_PHY_0			0x0A
51#define USB_PHY_RESET			0x01
52#define USB_PHY_PORT_RESET_0		0x10
53#define USB_PHY_PORT_RESET_1		0x20
54#define USB_CONTROLLER_RESET		0x01
55#define USB_INT_STATUS			0x0E
56#define USB_INT_EN			0x0F
57#define USB_PHY_INTERRUPT_EN		0x01
58#define USB_OHCI_INTERRUPT_EN		0x02
59#define USB_OHCI_INTERRUPT1_EN		0x04
60#define USB_OHCI_INTERRUPT2_EN		0x08
61#define USB_CTRL_INTERRUPT_EN		0x10
62
63#define nlm_read_usb_reg(b, r)			nlm_read_reg(b, r)
64#define nlm_write_usb_reg(b, r, v)		nlm_write_reg(b, r, v)
65#define nlm_get_usb_pcibase(node, inst)		\
66	nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst))
67#define nlm_get_usb_regbase(node, inst)		\
68	(nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
69
70static void nlm_usb_intr_en(int node, int port)
71{
72	uint32_t val;
73	uint64_t port_addr;
74
75	port_addr = nlm_get_usb_regbase(node, port);
76	val = nlm_read_usb_reg(port_addr, USB_INT_EN);
77	val = USB_CTRL_INTERRUPT_EN  | USB_OHCI_INTERRUPT_EN |
78		USB_OHCI_INTERRUPT1_EN | USB_OHCI_INTERRUPT2_EN;
79	nlm_write_usb_reg(port_addr, USB_INT_EN, val);
80}
81
82static void nlm_usb_hw_reset(int node, int port)
83{
84	uint64_t port_addr;
85	uint32_t val;
86
87	/* reset USB phy */
88	port_addr = nlm_get_usb_regbase(node, port);
89	val = nlm_read_usb_reg(port_addr, USB_PHY_0);
90	val &= ~(USB_PHY_RESET | USB_PHY_PORT_RESET_0 | USB_PHY_PORT_RESET_1);
91	nlm_write_usb_reg(port_addr, USB_PHY_0, val);
92
93	mdelay(100);
94	val = nlm_read_usb_reg(port_addr, USB_CTL_0);
95	val &= ~(USB_CONTROLLER_RESET);
96	val |= 0x4;
97	nlm_write_usb_reg(port_addr, USB_CTL_0, val);
98}
99
100static int __init nlm_platform_usb_init(void)
101{
102	if (cpu_is_xlpii())
103		return 0;
104
105	pr_info("Initializing USB Interface\n");
106	nlm_usb_hw_reset(0, 0);
107	nlm_usb_hw_reset(0, 3);
108
109	/* Enable PHY interrupts */
110	nlm_usb_intr_en(0, 0);
111	nlm_usb_intr_en(0, 3);
112
113	return 0;
114}
115
116arch_initcall(nlm_platform_usb_init);
117
118static u64 xlp_usb_dmamask = ~(u32)0;
119
120/* Fixup the IRQ for USB devices which is exist on XLP SOC PCIE bus */
121static void nlm_usb_fixup_final(struct pci_dev *dev)
122{
123	dev->dev.dma_mask		= &xlp_usb_dmamask;
124	dev->dev.coherent_dma_mask	= DMA_BIT_MASK(32);
125	switch (dev->devfn) {
126	case 0x10:
127		dev->irq = PIC_EHCI_0_IRQ;
128		break;
129	case 0x11:
130		dev->irq = PIC_OHCI_0_IRQ;
131		break;
132	case 0x12:
133		dev->irq = PIC_OHCI_1_IRQ;
134		break;
135	case 0x13:
136		dev->irq = PIC_EHCI_1_IRQ;
137		break;
138	case 0x14:
139		dev->irq = PIC_OHCI_2_IRQ;
140		break;
141	case 0x15:
142		dev->irq = PIC_OHCI_3_IRQ;
143		break;
144	}
145}
146DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_EHCI,
147		nlm_usb_fixup_final);
148DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_OHCI,
149		nlm_usb_fixup_final);
150