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