uboot/drivers/usb/host/ehci-vf.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2015 Sanchayan Maity <sanchayan.maity@toradex.com>
   4 * Copyright (C) 2015 Toradex AG
   5 *
   6 * Based on ehci-mx6 driver
   7 */
   8
   9#include <common.h>
  10#include <dm.h>
  11#include <log.h>
  12#include <usb.h>
  13#include <errno.h>
  14#include <asm/global_data.h>
  15#include <linux/compiler.h>
  16#include <asm/io.h>
  17#include <asm-generic/gpio.h>
  18#include <asm/arch/clock.h>
  19#include <asm/arch/imx-regs.h>
  20#include <asm/arch/crm_regs.h>
  21#include <asm/mach-imx/iomux-v3.h>
  22#include <asm/mach-imx/regs-usbphy.h>
  23#include <linux/delay.h>
  24#include <usb/ehci-ci.h>
  25#include <linux/libfdt.h>
  26#include <fdtdec.h>
  27
  28#include "ehci.h"
  29
  30#define USB_NC_REG_OFFSET                               0x00000800
  31
  32#define ANADIG_PLL_CTRL_EN_USB_CLKS             (1 << 6)
  33
  34#define UCTRL_OVER_CUR_POL      (1 << 8) /* OTG Polarity of Overcurrent */
  35#define UCTRL_OVER_CUR_DIS      (1 << 7) /* Disable OTG Overcurrent Detection */
  36
  37/* USBCMD */
  38#define UCMD_RUN_STOP           (1 << 0) /* controller run/stop */
  39#define UCMD_RESET                      (1 << 1) /* controller reset */
  40
  41DECLARE_GLOBAL_DATA_PTR;
  42
  43static const unsigned phy_bases[] = {
  44        USB_PHY0_BASE_ADDR,
  45        USB_PHY1_BASE_ADDR,
  46};
  47
  48static const unsigned nc_reg_bases[] = {
  49        USBC0_BASE_ADDR,
  50        USBC1_BASE_ADDR,
  51};
  52
  53static void usb_internal_phy_clock_gate(int index)
  54{
  55        void __iomem *phy_reg;
  56
  57        phy_reg = (void __iomem *)phy_bases[index];
  58        clrbits_le32(phy_reg + USBPHY_CTRL, USBPHY_CTRL_CLKGATE);
  59}
  60
  61static void usb_power_config(int index)
  62{
  63        struct anadig_reg __iomem *anadig =
  64                (struct anadig_reg __iomem *)ANADIG_BASE_ADDR;
  65        void __iomem *pll_ctrl;
  66
  67        switch (index) {
  68        case 0:
  69                pll_ctrl = &anadig->pll3_ctrl;
  70                clrbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_BYPASS);
  71                setbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_ENABLE
  72                         | ANADIG_PLL3_CTRL_POWERDOWN
  73                         | ANADIG_PLL_CTRL_EN_USB_CLKS);
  74                break;
  75        case 1:
  76                pll_ctrl = &anadig->pll7_ctrl;
  77                clrbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_BYPASS);
  78                setbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_ENABLE
  79                         | ANADIG_PLL7_CTRL_POWERDOWN
  80                         | ANADIG_PLL_CTRL_EN_USB_CLKS);
  81                break;
  82        default:
  83                return;
  84        }
  85}
  86
  87static void usb_phy_enable(int index, struct usb_ehci *ehci)
  88{
  89        void __iomem *phy_reg;
  90        void __iomem *phy_ctrl;
  91        void __iomem *usb_cmd;
  92
  93        phy_reg = (void __iomem *)phy_bases[index];
  94        phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
  95        usb_cmd = (void __iomem *)&ehci->usbcmd;
  96
  97        /* Stop then Reset */
  98        clrbits_le32(usb_cmd, UCMD_RUN_STOP);
  99        while (readl(usb_cmd) & UCMD_RUN_STOP)
 100                ;
 101
 102        setbits_le32(usb_cmd, UCMD_RESET);
 103        while (readl(usb_cmd) & UCMD_RESET)
 104                ;
 105
 106        /* Reset USBPHY module */
 107        setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST);
 108        udelay(10);
 109
 110        /* Remove CLKGATE and SFTRST */
 111        clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
 112        udelay(10);
 113
 114        /* Power up the PHY */
 115        writel(0, phy_reg + USBPHY_PWD);
 116
 117        /* Enable FS/LS device */
 118        setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 |
 119                 USBPHY_CTRL_ENUTMILEVEL3);
 120}
 121
 122static void usb_oc_config(int index)
 123{
 124        void __iomem *ctrl;
 125
 126        ctrl = (void __iomem *)(nc_reg_bases[index] + USB_NC_REG_OFFSET);
 127
 128        setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
 129        setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
 130}
 131
 132int __weak board_usb_phy_mode(int port)
 133{
 134        return 0;
 135}
 136
 137int __weak board_ehci_hcd_init(int port)
 138{
 139        return 0;
 140}
 141
 142int ehci_vf_common_init(struct usb_ehci *ehci, int index)
 143{
 144        int ret;
 145
 146        /* Do board specific initialisation */
 147        ret = board_ehci_hcd_init(index);
 148        if (ret)
 149                return ret;
 150
 151        usb_power_config(index);
 152        usb_oc_config(index);
 153        usb_internal_phy_clock_gate(index);
 154        usb_phy_enable(index, ehci);
 155
 156        return 0;
 157}
 158
 159#if !CONFIG_IS_ENABLED(DM_USB)
 160int ehci_hcd_init(int index, enum usb_init_type init,
 161                struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 162{
 163        struct usb_ehci *ehci;
 164        enum usb_init_type type;
 165        int ret;
 166
 167        if (index >= ARRAY_SIZE(nc_reg_bases))
 168                return -EINVAL;
 169
 170        ehci = (struct usb_ehci *)nc_reg_bases[index];
 171
 172        ret = ehci_vf_common_init(index);
 173        if (ret)
 174                return ret;
 175
 176        *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
 177        *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
 178                        HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
 179
 180        type = board_usb_phy_mode(index);
 181        if (type != init)
 182                return -ENODEV;
 183
 184        if (init == USB_INIT_DEVICE) {
 185                setbits_le32(&ehci->usbmode, CM_DEVICE);
 186                writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
 187                setbits_le32(&ehci->portsc, USB_EN);
 188        } else if (init == USB_INIT_HOST) {
 189                setbits_le32(&ehci->usbmode, CM_HOST);
 190                writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
 191                setbits_le32(&ehci->portsc, USB_EN);
 192        }
 193
 194        return 0;
 195}
 196
 197int ehci_hcd_stop(int index)
 198{
 199        return 0;
 200}
 201#else
 202/* Possible port types (dual role mode) */
 203enum dr_mode {
 204        DR_MODE_NONE = 0,
 205        DR_MODE_HOST,           /* supports host operation */
 206        DR_MODE_DEVICE,         /* supports device operation */
 207        DR_MODE_OTG,            /* supports both */
 208};
 209
 210struct ehci_vf_priv_data {
 211        struct ehci_ctrl ctrl;
 212        struct usb_ehci *ehci;
 213        struct gpio_desc cdet_gpio;
 214        enum usb_init_type init_type;
 215        enum dr_mode dr_mode;
 216        u32 portnr;
 217};
 218
 219static int vf_usb_of_to_plat(struct udevice *dev)
 220{
 221        struct ehci_vf_priv_data *priv = dev_get_priv(dev);
 222        const void *dt_blob = gd->fdt_blob;
 223        int node = dev_of_offset(dev);
 224        const char *mode;
 225
 226        priv->portnr = dev_seq(dev);
 227
 228        priv->ehci = dev_read_addr_ptr(dev);
 229        mode = fdt_getprop(dt_blob, node, "dr_mode", NULL);
 230        if (mode) {
 231                if (0 == strcmp(mode, "host")) {
 232                        priv->dr_mode = DR_MODE_HOST;
 233                        priv->init_type = USB_INIT_HOST;
 234                } else if (0 == strcmp(mode, "peripheral")) {
 235                        priv->dr_mode = DR_MODE_DEVICE;
 236                        priv->init_type = USB_INIT_DEVICE;
 237                } else if (0 == strcmp(mode, "otg")) {
 238                        priv->dr_mode = DR_MODE_OTG;
 239                        /*
 240                         * We set init_type to device by default when OTG
 241                         * mode is requested. If a valid gpio is provided
 242                         * we will switch the init_type based on the state
 243                         * of the gpio pin.
 244                         */
 245                        priv->init_type = USB_INIT_DEVICE;
 246                } else {
 247                        debug("%s: Cannot decode dr_mode '%s'\n",
 248                              __func__, mode);
 249                        return -EINVAL;
 250                }
 251        } else {
 252                priv->dr_mode = DR_MODE_HOST;
 253                priv->init_type = USB_INIT_HOST;
 254        }
 255
 256        if (priv->dr_mode == DR_MODE_OTG) {
 257                gpio_request_by_name_nodev(offset_to_ofnode(node),
 258                                           "fsl,cdet-gpio", 0, &priv->cdet_gpio,
 259                                           GPIOD_IS_IN);
 260                if (dm_gpio_is_valid(&priv->cdet_gpio)) {
 261                        if (dm_gpio_get_value(&priv->cdet_gpio))
 262                                priv->init_type = USB_INIT_DEVICE;
 263                        else
 264                                priv->init_type = USB_INIT_HOST;
 265                }
 266        }
 267
 268        return 0;
 269}
 270
 271static int vf_init_after_reset(struct ehci_ctrl *dev)
 272{
 273        struct ehci_vf_priv_data *priv = dev->priv;
 274        enum usb_init_type type = priv->init_type;
 275        struct usb_ehci *ehci = priv->ehci;
 276        int ret;
 277
 278        ret = ehci_vf_common_init(priv->ehci, priv->portnr);
 279        if (ret)
 280                return ret;
 281
 282        if (type == USB_INIT_DEVICE)
 283                return 0;
 284
 285        setbits_le32(&ehci->usbmode, CM_HOST);
 286        writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
 287        setbits_le32(&ehci->portsc, USB_EN);
 288
 289        mdelay(10);
 290
 291        return 0;
 292}
 293
 294static const struct ehci_ops vf_ehci_ops = {
 295        .init_after_reset = vf_init_after_reset
 296};
 297
 298static int vf_usb_bind(struct udevice *dev)
 299{
 300        /*
 301         * Without this hack, if we return ENODEV for USB Controller 0, on
 302         * probe for the next controller, USB Controller 1 will be given a
 303         * sequence number of 0. This conflicts with our requirement of
 304         * sequence numbers while initialising the peripherals.
 305         *
 306         * FIXME: Check that this still works OK with the new sequence numbers
 307         */
 308
 309        return 0;
 310}
 311
 312static int ehci_usb_probe(struct udevice *dev)
 313{
 314        struct usb_plat *plat = dev_get_plat(dev);
 315        struct ehci_vf_priv_data *priv = dev_get_priv(dev);
 316        struct usb_ehci *ehci = priv->ehci;
 317        struct ehci_hccr *hccr;
 318        struct ehci_hcor *hcor;
 319        int ret;
 320
 321        ret = ehci_vf_common_init(ehci, priv->portnr);
 322        if (ret)
 323                return ret;
 324
 325        if (priv->init_type != plat->init_type)
 326                return -ENODEV;
 327
 328        if (priv->init_type == USB_INIT_HOST) {
 329                setbits_le32(&ehci->usbmode, CM_HOST);
 330                writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
 331                setbits_le32(&ehci->portsc, USB_EN);
 332        }
 333
 334        mdelay(10);
 335
 336        hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
 337        hcor = (struct ehci_hcor *)((uint32_t)hccr +
 338                                HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 339
 340        return ehci_register(dev, hccr, hcor, &vf_ehci_ops, 0, priv->init_type);
 341}
 342
 343static const struct udevice_id vf_usb_ids[] = {
 344        { .compatible = "fsl,vf610-usb" },
 345        { }
 346};
 347
 348U_BOOT_DRIVER(usb_ehci) = {
 349        .name = "ehci_vf",
 350        .id = UCLASS_USB,
 351        .of_match = vf_usb_ids,
 352        .bind = vf_usb_bind,
 353        .probe = ehci_usb_probe,
 354        .remove = ehci_deregister,
 355        .ops = &ehci_usb_ops,
 356        .of_to_plat = vf_usb_of_to_plat,
 357        .plat_auto      = sizeof(struct usb_plat),
 358        .priv_auto      = sizeof(struct ehci_vf_priv_data),
 359        .flags = DM_FLAG_ALLOC_PRIV_DMA,
 360};
 361#endif
 362