linux/arch/mips/netlogic/xlp/usb-init-xlp2.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2003-2013 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/pci_ids.h>
  41#include <linux/platform_device.h>
  42#include <linux/irq.h>
  43
  44#include <asm/netlogic/common.h>
  45#include <asm/netlogic/haldefs.h>
  46#include <asm/netlogic/xlp-hal/iomap.h>
  47#include <asm/netlogic/xlp-hal/xlp.h>
  48
  49#define XLPII_USB3_CTL_0                0xc0
  50#define XLPII_VAUXRST                   BIT(0)
  51#define XLPII_VCCRST                    BIT(1)
  52#define XLPII_NUM2PORT                  9
  53#define XLPII_NUM3PORT                  13
  54#define XLPII_RTUNEREQ                  BIT(20)
  55#define XLPII_MS_CSYSREQ                BIT(21)
  56#define XLPII_XS_CSYSREQ                BIT(22)
  57#define XLPII_RETENABLEN                BIT(23)
  58#define XLPII_TX2RX                     BIT(24)
  59#define XLPII_XHCIREV                   BIT(25)
  60#define XLPII_ECCDIS                    BIT(26)
  61
  62#define XLPII_USB3_INT_REG              0xc2
  63#define XLPII_USB3_INT_MASK             0xc3
  64
  65#define XLPII_USB_PHY_TEST              0xc6
  66#define XLPII_PRESET                    BIT(0)
  67#define XLPII_ATERESET                  BIT(1)
  68#define XLPII_LOOPEN                    BIT(2)
  69#define XLPII_TESTPDHSP                 BIT(3)
  70#define XLPII_TESTPDSSP                 BIT(4)
  71#define XLPII_TESTBURNIN                BIT(5)
  72
  73#define XLPII_USB_PHY_LOS_LV            0xc9
  74#define XLPII_LOSLEV                    0
  75#define XLPII_LOSBIAS                   5
  76#define XLPII_SQRXTX                    8
  77#define XLPII_TXBOOST                   11
  78#define XLPII_RSLKSEL                   16
  79#define XLPII_FSEL                      20
  80
  81#define XLPII_USB_RFCLK_REG             0xcc
  82#define XLPII_VVLD                      30
  83
  84#define nlm_read_usb_reg(b, r)          nlm_read_reg(b, r)
  85#define nlm_write_usb_reg(b, r, v)      nlm_write_reg(b, r, v)
  86
  87#define nlm_xlpii_get_usb_pcibase(node, inst)                   \
  88                        nlm_pcicfg_base(cpu_is_xlp9xx() ?       \
  89                        XLP9XX_IO_USB_OFFSET(node, inst) :      \
  90                        XLP2XX_IO_USB_OFFSET(node, inst))
  91#define nlm_xlpii_get_usb_regbase(node, inst)           \
  92        (nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
  93
  94static void xlp2xx_usb_ack(struct irq_data *data)
  95{
  96        u64 port_addr;
  97
  98        switch (data->irq) {
  99        case PIC_2XX_XHCI_0_IRQ:
 100                port_addr = nlm_xlpii_get_usb_regbase(0, 1);
 101                break;
 102        case PIC_2XX_XHCI_1_IRQ:
 103                port_addr = nlm_xlpii_get_usb_regbase(0, 2);
 104                break;
 105        case PIC_2XX_XHCI_2_IRQ:
 106                port_addr = nlm_xlpii_get_usb_regbase(0, 3);
 107                break;
 108        default:
 109                pr_err("No matching USB irq!\n");
 110                return;
 111        }
 112        nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
 113}
 114
 115static void xlp9xx_usb_ack(struct irq_data *data)
 116{
 117        u64 port_addr;
 118        int node, irq;
 119
 120        /* Find the node and irq on the node */
 121        irq = data->irq % NLM_IRQS_PER_NODE;
 122        node = data->irq / NLM_IRQS_PER_NODE;
 123
 124        switch (irq) {
 125        case PIC_9XX_XHCI_0_IRQ:
 126                port_addr = nlm_xlpii_get_usb_regbase(node, 1);
 127                break;
 128        case PIC_9XX_XHCI_1_IRQ:
 129                port_addr = nlm_xlpii_get_usb_regbase(node, 2);
 130                break;
 131        case PIC_9XX_XHCI_2_IRQ:
 132                port_addr = nlm_xlpii_get_usb_regbase(node, 3);
 133                break;
 134        default:
 135                pr_err("No matching USB irq %d node  %d!\n", irq, node);
 136                return;
 137        }
 138        nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
 139}
 140
 141static void nlm_xlpii_usb_hw_reset(int node, int port)
 142{
 143        u64 port_addr, xhci_base, pci_base;
 144        void __iomem *corebase;
 145        u32 val;
 146
 147        port_addr = nlm_xlpii_get_usb_regbase(node, port);
 148
 149        /* Set frequency */
 150        val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV);
 151        val &= ~(0x3f << XLPII_FSEL);
 152        val |= (0x27 << XLPII_FSEL);
 153        nlm_write_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV, val);
 154
 155        val = nlm_read_usb_reg(port_addr, XLPII_USB_RFCLK_REG);
 156        val |= (1 << XLPII_VVLD);
 157        nlm_write_usb_reg(port_addr, XLPII_USB_RFCLK_REG, val);
 158
 159        /* PHY reset */
 160        val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_TEST);
 161        val &= (XLPII_ATERESET | XLPII_LOOPEN | XLPII_TESTPDHSP
 162                | XLPII_TESTPDSSP | XLPII_TESTBURNIN);
 163        nlm_write_usb_reg(port_addr, XLPII_USB_PHY_TEST, val);
 164
 165        /* Setup control register */
 166        val =  XLPII_VAUXRST | XLPII_VCCRST | (1 << XLPII_NUM2PORT)
 167                | (1 << XLPII_NUM3PORT) | XLPII_MS_CSYSREQ | XLPII_XS_CSYSREQ
 168                | XLPII_RETENABLEN | XLPII_XHCIREV;
 169        nlm_write_usb_reg(port_addr, XLPII_USB3_CTL_0, val);
 170
 171        /* Enable interrupts */
 172        nlm_write_usb_reg(port_addr, XLPII_USB3_INT_MASK, 0x00000001);
 173
 174        /* Clear all interrupts */
 175        nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
 176
 177        udelay(2000);
 178
 179        /* XHCI configuration at PCI mem */
 180        pci_base = nlm_xlpii_get_usb_pcibase(node, port);
 181        xhci_base = nlm_read_usb_reg(pci_base, 0x4) & ~0xf;
 182        corebase = ioremap(xhci_base, 0x10000);
 183        if (!corebase)
 184                return;
 185
 186        writel(0x240002, corebase + 0xc2c0);
 187        /* GCTL 0xc110 */
 188        val = readl(corebase + 0xc110);
 189        val &= ~(0x3 << 12);
 190        val |= (1 << 12);
 191        writel(val, corebase + 0xc110);
 192        udelay(100);
 193
 194        /* PHYCFG 0xc200 */
 195        val = readl(corebase + 0xc200);
 196        val &= ~(1 << 6);
 197        writel(val, corebase + 0xc200);
 198        udelay(100);
 199
 200        /* PIPECTL 0xc2c0 */
 201        val = readl(corebase + 0xc2c0);
 202        val &= ~(1 << 17);
 203        writel(val, corebase + 0xc2c0);
 204
 205        iounmap(corebase);
 206}
 207
 208static int __init nlm_platform_xlpii_usb_init(void)
 209{
 210        int node;
 211
 212        if (!cpu_is_xlpii())
 213                return 0;
 214
 215        if (!cpu_is_xlp9xx()) {
 216                /* XLP 2XX single node */
 217                pr_info("Initializing 2XX USB Interface\n");
 218                nlm_xlpii_usb_hw_reset(0, 1);
 219                nlm_xlpii_usb_hw_reset(0, 2);
 220                nlm_xlpii_usb_hw_reset(0, 3);
 221                nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlp2xx_usb_ack);
 222                nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlp2xx_usb_ack);
 223                nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlp2xx_usb_ack);
 224                return 0;
 225        }
 226
 227        /* XLP 9XX, multi-node */
 228        pr_info("Initializing 9XX/5XX USB Interface\n");
 229        for (node = 0; node < NLM_NR_NODES; node++) {
 230                if (!nlm_node_present(node))
 231                        continue;
 232                nlm_xlpii_usb_hw_reset(node, 1);
 233                nlm_xlpii_usb_hw_reset(node, 2);
 234                nlm_xlpii_usb_hw_reset(node, 3);
 235                nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_0_IRQ, xlp9xx_usb_ack);
 236                nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_1_IRQ, xlp9xx_usb_ack);
 237                nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_2_IRQ, xlp9xx_usb_ack);
 238        }
 239        return 0;
 240}
 241
 242arch_initcall(nlm_platform_xlpii_usb_init);
 243
 244static u64 xlp_usb_dmamask = ~(u32)0;
 245
 246/* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */
 247static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev)
 248{
 249        int node;
 250
 251        node = xlp_socdev_to_node(dev);
 252        dev->dev.dma_mask               = &xlp_usb_dmamask;
 253        dev->dev.coherent_dma_mask      = DMA_BIT_MASK(32);
 254        switch (dev->devfn) {
 255        case 0x21:
 256                dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_0_IRQ);
 257                break;
 258        case 0x22:
 259                dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ);
 260                break;
 261        case 0x23:
 262                dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_2_IRQ);
 263                break;
 264        }
 265}
 266
 267/* Fixup the IRQ for USB devices which is exist on XLP2XX SOC PCIE bus */
 268static void nlm_xlp2xx_usb_fixup_final(struct pci_dev *dev)
 269{
 270        dev->dev.dma_mask               = &xlp_usb_dmamask;
 271        dev->dev.coherent_dma_mask      = DMA_BIT_MASK(32);
 272        switch (dev->devfn) {
 273        case 0x21:
 274                dev->irq = PIC_2XX_XHCI_0_IRQ;
 275                break;
 276        case 0x22:
 277                dev->irq = PIC_2XX_XHCI_1_IRQ;
 278                break;
 279        case 0x23:
 280                dev->irq = PIC_2XX_XHCI_2_IRQ;
 281                break;
 282        }
 283}
 284
 285DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_XHCI,
 286                nlm_xlp9xx_usb_fixup_final);
 287DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI,
 288                nlm_xlp2xx_usb_fixup_final);
 289