18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2003-2012 Broadcom Corporation
38c2ecf20Sopenharmony_ci * All Rights Reserved
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
68c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
78c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
88c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the Broadcom
98c2ecf20Sopenharmony_ci * license below:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
128c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
138c2ecf20Sopenharmony_ci * are met:
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
168c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
178c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
188c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
198c2ecf20Sopenharmony_ci *    the documentation and/or other materials provided with the
208c2ecf20Sopenharmony_ci *    distribution.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
238c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
248c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
258c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
268c2ecf20Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
278c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
288c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
298c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
308c2ecf20Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
318c2ecf20Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
328c2ecf20Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
368c2ecf20Sopenharmony_ci#include <linux/kernel.h>
378c2ecf20Sopenharmony_ci#include <linux/delay.h>
388c2ecf20Sopenharmony_ci#include <linux/init.h>
398c2ecf20Sopenharmony_ci#include <linux/pci.h>
408c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#include <asm/netlogic/haldefs.h>
438c2ecf20Sopenharmony_ci#include <asm/netlogic/xlp-hal/iomap.h>
448c2ecf20Sopenharmony_ci#include <asm/netlogic/xlp-hal/xlp.h>
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/*
478c2ecf20Sopenharmony_ci * USB glue logic registers, used only during initialization
488c2ecf20Sopenharmony_ci */
498c2ecf20Sopenharmony_ci#define USB_CTL_0			0x01
508c2ecf20Sopenharmony_ci#define USB_PHY_0			0x0A
518c2ecf20Sopenharmony_ci#define USB_PHY_RESET			0x01
528c2ecf20Sopenharmony_ci#define USB_PHY_PORT_RESET_0		0x10
538c2ecf20Sopenharmony_ci#define USB_PHY_PORT_RESET_1		0x20
548c2ecf20Sopenharmony_ci#define USB_CONTROLLER_RESET		0x01
558c2ecf20Sopenharmony_ci#define USB_INT_STATUS			0x0E
568c2ecf20Sopenharmony_ci#define USB_INT_EN			0x0F
578c2ecf20Sopenharmony_ci#define USB_PHY_INTERRUPT_EN		0x01
588c2ecf20Sopenharmony_ci#define USB_OHCI_INTERRUPT_EN		0x02
598c2ecf20Sopenharmony_ci#define USB_OHCI_INTERRUPT1_EN		0x04
608c2ecf20Sopenharmony_ci#define USB_OHCI_INTERRUPT2_EN		0x08
618c2ecf20Sopenharmony_ci#define USB_CTRL_INTERRUPT_EN		0x10
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci#define nlm_read_usb_reg(b, r)			nlm_read_reg(b, r)
648c2ecf20Sopenharmony_ci#define nlm_write_usb_reg(b, r, v)		nlm_write_reg(b, r, v)
658c2ecf20Sopenharmony_ci#define nlm_get_usb_pcibase(node, inst)		\
668c2ecf20Sopenharmony_ci	nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst))
678c2ecf20Sopenharmony_ci#define nlm_get_usb_regbase(node, inst)		\
688c2ecf20Sopenharmony_ci	(nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic void nlm_usb_intr_en(int node, int port)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	uint32_t val;
738c2ecf20Sopenharmony_ci	uint64_t port_addr;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	port_addr = nlm_get_usb_regbase(node, port);
768c2ecf20Sopenharmony_ci	val = nlm_read_usb_reg(port_addr, USB_INT_EN);
778c2ecf20Sopenharmony_ci	val = USB_CTRL_INTERRUPT_EN  | USB_OHCI_INTERRUPT_EN |
788c2ecf20Sopenharmony_ci		USB_OHCI_INTERRUPT1_EN | USB_OHCI_INTERRUPT2_EN;
798c2ecf20Sopenharmony_ci	nlm_write_usb_reg(port_addr, USB_INT_EN, val);
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic void nlm_usb_hw_reset(int node, int port)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	uint64_t port_addr;
858c2ecf20Sopenharmony_ci	uint32_t val;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* reset USB phy */
888c2ecf20Sopenharmony_ci	port_addr = nlm_get_usb_regbase(node, port);
898c2ecf20Sopenharmony_ci	val = nlm_read_usb_reg(port_addr, USB_PHY_0);
908c2ecf20Sopenharmony_ci	val &= ~(USB_PHY_RESET | USB_PHY_PORT_RESET_0 | USB_PHY_PORT_RESET_1);
918c2ecf20Sopenharmony_ci	nlm_write_usb_reg(port_addr, USB_PHY_0, val);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	mdelay(100);
948c2ecf20Sopenharmony_ci	val = nlm_read_usb_reg(port_addr, USB_CTL_0);
958c2ecf20Sopenharmony_ci	val &= ~(USB_CONTROLLER_RESET);
968c2ecf20Sopenharmony_ci	val |= 0x4;
978c2ecf20Sopenharmony_ci	nlm_write_usb_reg(port_addr, USB_CTL_0, val);
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistatic int __init nlm_platform_usb_init(void)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	if (cpu_is_xlpii())
1038c2ecf20Sopenharmony_ci		return 0;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	pr_info("Initializing USB Interface\n");
1068c2ecf20Sopenharmony_ci	nlm_usb_hw_reset(0, 0);
1078c2ecf20Sopenharmony_ci	nlm_usb_hw_reset(0, 3);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	/* Enable PHY interrupts */
1108c2ecf20Sopenharmony_ci	nlm_usb_intr_en(0, 0);
1118c2ecf20Sopenharmony_ci	nlm_usb_intr_en(0, 3);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	return 0;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ciarch_initcall(nlm_platform_usb_init);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic u64 xlp_usb_dmamask = ~(u32)0;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci/* Fixup the IRQ for USB devices which is exist on XLP SOC PCIE bus */
1218c2ecf20Sopenharmony_cistatic void nlm_usb_fixup_final(struct pci_dev *dev)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	dev->dev.dma_mask		= &xlp_usb_dmamask;
1248c2ecf20Sopenharmony_ci	dev->dev.coherent_dma_mask	= DMA_BIT_MASK(32);
1258c2ecf20Sopenharmony_ci	switch (dev->devfn) {
1268c2ecf20Sopenharmony_ci	case 0x10:
1278c2ecf20Sopenharmony_ci		dev->irq = PIC_EHCI_0_IRQ;
1288c2ecf20Sopenharmony_ci		break;
1298c2ecf20Sopenharmony_ci	case 0x11:
1308c2ecf20Sopenharmony_ci		dev->irq = PIC_OHCI_0_IRQ;
1318c2ecf20Sopenharmony_ci		break;
1328c2ecf20Sopenharmony_ci	case 0x12:
1338c2ecf20Sopenharmony_ci		dev->irq = PIC_OHCI_1_IRQ;
1348c2ecf20Sopenharmony_ci		break;
1358c2ecf20Sopenharmony_ci	case 0x13:
1368c2ecf20Sopenharmony_ci		dev->irq = PIC_EHCI_1_IRQ;
1378c2ecf20Sopenharmony_ci		break;
1388c2ecf20Sopenharmony_ci	case 0x14:
1398c2ecf20Sopenharmony_ci		dev->irq = PIC_OHCI_2_IRQ;
1408c2ecf20Sopenharmony_ci		break;
1418c2ecf20Sopenharmony_ci	case 0x15:
1428c2ecf20Sopenharmony_ci		dev->irq = PIC_OHCI_3_IRQ;
1438c2ecf20Sopenharmony_ci		break;
1448c2ecf20Sopenharmony_ci	}
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_EHCI,
1478c2ecf20Sopenharmony_ci		nlm_usb_fixup_final);
1488c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_OHCI,
1498c2ecf20Sopenharmony_ci		nlm_usb_fixup_final);
150