uboot/drivers/usb/host/ehci-fsl.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2009, 2011, 2016 Freescale Semiconductor, Inc.
   3 *
   4 * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
   5 *
   6 * Author: Tor Krill tor@excito.com
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <pci.h>
  13#include <usb.h>
  14#include <asm/io.h>
  15#include <usb/ehci-ci.h>
  16#include <hwconfig.h>
  17#include <fsl_usb.h>
  18#include <fdt_support.h>
  19#include <dm.h>
  20
  21#include "ehci.h"
  22
  23DECLARE_GLOBAL_DATA_PTR;
  24
  25#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
  26#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
  27#endif
  28
  29#ifdef CONFIG_DM_USB
  30struct ehci_fsl_priv {
  31        struct ehci_ctrl ehci;
  32        fdt_addr_t hcd_base;
  33        char *phy_type;
  34};
  35#endif
  36
  37static void set_txfifothresh(struct usb_ehci *, u32);
  38#ifdef CONFIG_DM_USB
  39static int ehci_fsl_init(struct ehci_fsl_priv *priv, struct usb_ehci *ehci,
  40                  struct ehci_hccr *hccr, struct ehci_hcor *hcor);
  41#else
  42static int ehci_fsl_init(int index, struct usb_ehci *ehci,
  43                         struct ehci_hccr *hccr, struct ehci_hcor *hcor);
  44#endif
  45
  46/* Check USB PHY clock valid */
  47static int usb_phy_clk_valid(struct usb_ehci *ehci)
  48{
  49        if (!((in_be32(&ehci->control) & PHY_CLK_VALID) ||
  50                        in_be32(&ehci->prictrl))) {
  51                printf("USB PHY clock invalid!\n");
  52                return 0;
  53        } else {
  54                return 1;
  55        }
  56}
  57
  58#ifdef CONFIG_DM_USB
  59static int ehci_fsl_ofdata_to_platdata(struct udevice *dev)
  60{
  61        struct ehci_fsl_priv *priv = dev_get_priv(dev);
  62        const void *prop;
  63
  64        prop = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy_type",
  65                           NULL);
  66        if (prop) {
  67                priv->phy_type = (char *)prop;
  68                debug("phy_type %s\n", priv->phy_type);
  69        }
  70
  71        return 0;
  72}
  73
  74static int ehci_fsl_init_after_reset(struct ehci_ctrl *ctrl)
  75{
  76        struct usb_ehci *ehci = NULL;
  77        struct ehci_fsl_priv *priv = container_of(ctrl, struct ehci_fsl_priv,
  78                                                   ehci);
  79
  80        ehci = (struct usb_ehci *)priv->hcd_base;
  81        if (ehci_fsl_init(priv, ehci, priv->ehci.hccr, priv->ehci.hcor) < 0)
  82                return -ENXIO;
  83
  84        return 0;
  85}
  86
  87static const struct ehci_ops fsl_ehci_ops = {
  88        .init_after_reset = ehci_fsl_init_after_reset,
  89};
  90
  91static int ehci_fsl_probe(struct udevice *dev)
  92{
  93        struct ehci_fsl_priv *priv = dev_get_priv(dev);
  94        struct usb_ehci *ehci = NULL;
  95        struct ehci_hccr *hccr;
  96        struct ehci_hcor *hcor;
  97
  98        /*
  99         * Get the base address for EHCI controller from the device node
 100         */
 101        priv->hcd_base = devfdt_get_addr(dev);
 102        if (priv->hcd_base == FDT_ADDR_T_NONE) {
 103                debug("Can't get the EHCI register base address\n");
 104                return -ENXIO;
 105        }
 106        ehci = (struct usb_ehci *)priv->hcd_base;
 107        hccr = (struct ehci_hccr *)(&ehci->caplength);
 108        hcor = (struct ehci_hcor *)
 109                ((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 110
 111        if (ehci_fsl_init(priv, ehci, hccr, hcor) < 0)
 112                return -ENXIO;
 113
 114        debug("ehci-fsl: init hccr %x and hcor %x hc_length %d\n",
 115              (u32)hccr, (u32)hcor,
 116              (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 117
 118        return ehci_register(dev, hccr, hcor, &fsl_ehci_ops, 0, USB_INIT_HOST);
 119}
 120
 121static const struct udevice_id ehci_usb_ids[] = {
 122        { .compatible = "fsl-usb2-mph", },
 123        { .compatible = "fsl-usb2-dr", },
 124        { }
 125};
 126
 127U_BOOT_DRIVER(ehci_fsl) = {
 128        .name   = "ehci_fsl",
 129        .id     = UCLASS_USB,
 130        .of_match = ehci_usb_ids,
 131        .ofdata_to_platdata = ehci_fsl_ofdata_to_platdata,
 132        .probe = ehci_fsl_probe,
 133        .remove = ehci_deregister,
 134        .ops    = &ehci_usb_ops,
 135        .platdata_auto_alloc_size = sizeof(struct usb_platdata),
 136        .priv_auto_alloc_size = sizeof(struct ehci_fsl_priv),
 137        .flags  = DM_FLAG_ALLOC_PRIV_DMA,
 138};
 139#else
 140/*
 141 * Create the appropriate control structures to manage
 142 * a new EHCI host controller.
 143 *
 144 * Excerpts from linux ehci fsl driver.
 145 */
 146int ehci_hcd_init(int index, enum usb_init_type init,
 147                struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 148{
 149        struct usb_ehci *ehci = NULL;
 150
 151        switch (index) {
 152        case 0:
 153                ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR;
 154                break;
 155        case 1:
 156                ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB2_ADDR;
 157                break;
 158        default:
 159                printf("ERROR: wrong controller index!!\n");
 160                return -EINVAL;
 161        };
 162
 163        *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
 164        *hcor = (struct ehci_hcor *)((uint32_t) *hccr +
 165                        HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
 166
 167        return ehci_fsl_init(index, ehci, *hccr, *hcor);
 168}
 169
 170/*
 171 * Destroy the appropriate control structures corresponding
 172 * the the EHCI host controller.
 173 */
 174int ehci_hcd_stop(int index)
 175{
 176        return 0;
 177}
 178#endif
 179
 180#ifdef CONFIG_DM_USB
 181static int ehci_fsl_init(struct ehci_fsl_priv *priv, struct usb_ehci *ehci,
 182                  struct ehci_hccr *hccr, struct ehci_hcor *hcor)
 183#else
 184static int ehci_fsl_init(int index, struct usb_ehci *ehci,
 185                         struct ehci_hccr *hccr, struct ehci_hcor *hcor)
 186#endif
 187{
 188        const char *phy_type = NULL;
 189#ifndef CONFIG_DM_USB
 190        size_t len;
 191        char current_usb_controller[5];
 192#endif
 193#ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 194        char usb_phy[5];
 195
 196        usb_phy[0] = '\0';
 197#endif
 198        if (has_erratum_a007075()) {
 199                /*
 200                 * A 5ms delay is needed after applying soft-reset to the
 201                 * controller to let external ULPI phy come out of reset.
 202                 * This delay needs to be added before re-initializing
 203                 * the controller after soft-resetting completes
 204                 */
 205                mdelay(5);
 206        }
 207
 208        /* Set to Host mode */
 209        setbits_le32(&ehci->usbmode, CM_HOST);
 210
 211        out_be32(&ehci->snoop1, SNOOP_SIZE_2GB);
 212        out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB);
 213
 214        /* Init phy */
 215#ifdef CONFIG_DM_USB
 216        if (priv->phy_type)
 217                phy_type = priv->phy_type;
 218#else
 219        memset(current_usb_controller, '\0', 5);
 220        snprintf(current_usb_controller, sizeof(current_usb_controller),
 221                 "usb%d", index+1);
 222
 223        if (hwconfig_sub(current_usb_controller, "phy_type"))
 224                phy_type = hwconfig_subarg(current_usb_controller,
 225                                "phy_type", &len);
 226#endif
 227        else
 228                phy_type = getenv("usb_phy_type");
 229
 230        if (!phy_type) {
 231#ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 232                /* if none specified assume internal UTMI */
 233                strcpy(usb_phy, "utmi");
 234                phy_type = usb_phy;
 235#else
 236                printf("WARNING: USB phy type not defined !!\n");
 237                return -1;
 238#endif
 239        }
 240
 241        if (!strncmp(phy_type, "utmi", 4)) {
 242#if defined(CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY)
 243                clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
 244                                PHY_CLK_SEL_UTMI);
 245                clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
 246                                UTMI_PHY_EN);
 247                udelay(1000); /* delay required for PHY Clk to appear */
 248#endif
 249                out_le32(&(hcor)->or_portsc[0], PORT_PTS_UTMI);
 250                clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
 251                                USB_EN);
 252        } else {
 253                clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
 254                                PHY_CLK_SEL_ULPI);
 255                clrsetbits_be32(&ehci->control, UTMI_PHY_EN |
 256                                CONTROL_REGISTER_W1C_MASK, USB_EN);
 257                udelay(1000); /* delay required for PHY Clk to appear */
 258                if (!usb_phy_clk_valid(ehci))
 259                        return -EINVAL;
 260                out_le32(&(hcor)->or_portsc[0], PORT_PTS_ULPI);
 261        }
 262
 263        out_be32(&ehci->prictrl, 0x0000000c);
 264        out_be32(&ehci->age_cnt_limit, 0x00000040);
 265        out_be32(&ehci->sictrl, 0x00000001);
 266
 267        in_le32(&ehci->usbmode);
 268
 269        if (has_erratum_a007798())
 270                set_txfifothresh(ehci, TXFIFOTHRESH);
 271
 272        if (has_erratum_a004477()) {
 273                /*
 274                 * When reset is issued while any ULPI transaction is ongoing
 275                 * then it may result to corruption of ULPI Function Control
 276                 * Register which eventually causes phy clock to enter low
 277                 * power mode which stops the clock. Thus delay is required
 278                 * before reset to let ongoing ULPI transaction complete.
 279                 */
 280                udelay(1);
 281        }
 282        return 0;
 283}
 284
 285/*
 286 * Setting the value of TXFIFO_THRESH field in TXFILLTUNING register
 287 * to counter DDR latencies in writing data into Tx buffer.
 288 * This prevents Tx buffer from getting underrun
 289 */
 290static void set_txfifothresh(struct usb_ehci *ehci, u32 txfifo_thresh)
 291{
 292        u32 cmd;
 293        cmd = ehci_readl(&ehci->txfilltuning);
 294        cmd &= ~TXFIFO_THRESH_MASK;
 295        cmd |= TXFIFO_THRESH(txfifo_thresh);
 296        ehci_writel(&ehci->txfilltuning, cmd);
 297}
 298