uboot/drivers/usb/host/ehci-mx5.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
   4 * Copyright (C) 2010 Freescale Semiconductor, Inc.
   5 */
   6
   7#include <common.h>
   8#include <log.h>
   9#include <usb.h>
  10#include <errno.h>
  11#include <linux/compiler.h>
  12#include <linux/delay.h>
  13#include <usb/ehci-ci.h>
  14#include <asm/global_data.h>
  15#include <asm/io.h>
  16#include <asm/arch/imx-regs.h>
  17#include <asm/arch/clock.h>
  18#include <dm.h>
  19#include <power/regulator.h>
  20
  21#include "ehci.h"
  22
  23#define MX5_USBOTHER_REGS_OFFSET 0x800
  24
  25
  26#define MXC_OTG_OFFSET                  0
  27#define MXC_H1_OFFSET                   0x200
  28#define MXC_H2_OFFSET                   0x400
  29#define MXC_H3_OFFSET                   0x600
  30
  31#define MXC_USBCTRL_OFFSET              0
  32#define MXC_USB_PHY_CTR_FUNC_OFFSET     0x8
  33#define MXC_USB_PHY_CTR_FUNC2_OFFSET    0xc
  34#define MXC_USB_CTRL_1_OFFSET           0x10
  35#define MXC_USBH2CTRL_OFFSET            0x14
  36#define MXC_USBH3CTRL_OFFSET            0x18
  37
  38/* USB_CTRL */
  39/* OTG wakeup intr enable */
  40#define MXC_OTG_UCTRL_OWIE_BIT          (1 << 27)
  41/* OTG power mask */
  42#define MXC_OTG_UCTRL_OPM_BIT           (1 << 24)
  43/* OTG power pin polarity */
  44#define MXC_OTG_UCTRL_O_PWR_POL_BIT     (1 << 24)
  45/* Host1 ULPI interrupt enable */
  46#define MXC_H1_UCTRL_H1UIE_BIT          (1 << 12)
  47/* HOST1 wakeup intr enable */
  48#define MXC_H1_UCTRL_H1WIE_BIT          (1 << 11)
  49/* HOST1 power mask */
  50#define MXC_H1_UCTRL_H1PM_BIT           (1 << 8)
  51/* HOST1 power pin polarity */
  52#define MXC_H1_UCTRL_H1_PWR_POL_BIT     (1 << 8)
  53
  54/* USB_PHY_CTRL_FUNC */
  55/* OTG Polarity of Overcurrent */
  56#define MXC_OTG_PHYCTRL_OC_POL_BIT      (1 << 9)
  57/* OTG Disable Overcurrent Event */
  58#define MXC_OTG_PHYCTRL_OC_DIS_BIT      (1 << 8)
  59/* UH1 Polarity of Overcurrent */
  60#define MXC_H1_OC_POL_BIT               (1 << 6)
  61/* UH1 Disable Overcurrent Event */
  62#define MXC_H1_OC_DIS_BIT               (1 << 5)
  63/* OTG Power Pin Polarity */
  64#define MXC_OTG_PHYCTRL_PWR_POL_BIT     (1 << 3)
  65
  66/* USBH2CTRL */
  67#define MXC_H2_UCTRL_H2_OC_POL_BIT      (1 << 31)
  68#define MXC_H2_UCTRL_H2_OC_DIS_BIT      (1 << 30)
  69#define MXC_H2_UCTRL_H2UIE_BIT          (1 << 8)
  70#define MXC_H2_UCTRL_H2WIE_BIT          (1 << 7)
  71#define MXC_H2_UCTRL_H2PM_BIT           (1 << 4)
  72#define MXC_H2_UCTRL_H2_PWR_POL_BIT     (1 << 4)
  73
  74/* USBH3CTRL */
  75#define MXC_H3_UCTRL_H3_OC_POL_BIT      (1 << 31)
  76#define MXC_H3_UCTRL_H3_OC_DIS_BIT      (1 << 30)
  77#define MXC_H3_UCTRL_H3UIE_BIT          (1 << 8)
  78#define MXC_H3_UCTRL_H3WIE_BIT          (1 << 7)
  79#define MXC_H3_UCTRL_H3_PWR_POL_BIT     (1 << 4)
  80
  81/* USB_CTRL_1 */
  82#define MXC_USB_CTRL_UH1_EXT_CLK_EN     (1 << 25)
  83
  84int mxc_set_usbcontrol(int port, unsigned int flags)
  85{
  86        unsigned int v;
  87        void __iomem *usb_base = (void __iomem *)OTG_BASE_ADDR;
  88        void __iomem *usbother_base;
  89        int ret = 0;
  90
  91        usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
  92
  93        switch (port) {
  94        case 0: /* OTG port */
  95                if (flags & MXC_EHCI_INTERNAL_PHY) {
  96                        v = __raw_readl(usbother_base +
  97                                        MXC_USB_PHY_CTR_FUNC_OFFSET);
  98                        if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
  99                                v |= MXC_OTG_PHYCTRL_OC_POL_BIT;
 100                        else
 101                                v &= ~MXC_OTG_PHYCTRL_OC_POL_BIT;
 102                        if (flags & MXC_EHCI_POWER_PINS_ENABLED)
 103                                /* OC/USBPWR is used */
 104                                v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
 105                        else
 106                                /* OC/USBPWR is not used */
 107                                v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
 108#ifdef CONFIG_MX51
 109                        if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
 110                                v |= MXC_OTG_PHYCTRL_PWR_POL_BIT;
 111                        else
 112                                v &= ~MXC_OTG_PHYCTRL_PWR_POL_BIT;
 113#endif
 114                        __raw_writel(v, usbother_base +
 115                                        MXC_USB_PHY_CTR_FUNC_OFFSET);
 116
 117                        v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
 118#ifdef CONFIG_MX51
 119                        if (flags & MXC_EHCI_POWER_PINS_ENABLED)
 120                                v &= ~MXC_OTG_UCTRL_OPM_BIT;
 121                        else
 122                                v |= MXC_OTG_UCTRL_OPM_BIT;
 123#endif
 124#ifdef CONFIG_MX53
 125                        if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
 126                                v |= MXC_OTG_UCTRL_O_PWR_POL_BIT;
 127                        else
 128                                v &= ~MXC_OTG_UCTRL_O_PWR_POL_BIT;
 129#endif
 130                        __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
 131                }
 132                break;
 133        case 1: /* Host 1 ULPI */
 134#ifdef CONFIG_MX51
 135                /* The clock for the USBH1 ULPI port will come externally
 136                   from the PHY. */
 137                v = __raw_readl(usbother_base + MXC_USB_CTRL_1_OFFSET);
 138                __raw_writel(v | MXC_USB_CTRL_UH1_EXT_CLK_EN, usbother_base +
 139                                MXC_USB_CTRL_1_OFFSET);
 140#endif
 141
 142                v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
 143#ifdef CONFIG_MX51
 144                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
 145                        v &= ~MXC_H1_UCTRL_H1PM_BIT; /* H1 power mask unused */
 146                else
 147                        v |= MXC_H1_UCTRL_H1PM_BIT; /* H1 power mask used */
 148#endif
 149#ifdef CONFIG_MX53
 150                if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
 151                        v |= MXC_H1_UCTRL_H1_PWR_POL_BIT;
 152                else
 153                        v &= ~MXC_H1_UCTRL_H1_PWR_POL_BIT;
 154#endif
 155                __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
 156
 157                v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
 158                if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
 159                        v |= MXC_H1_OC_POL_BIT;
 160                else
 161                        v &= ~MXC_H1_OC_POL_BIT;
 162                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
 163                        v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
 164                else
 165                        v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
 166                __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
 167
 168                break;
 169        case 2: /* Host 2 ULPI */
 170                v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
 171#ifdef CONFIG_MX51
 172                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
 173                        v &= ~MXC_H2_UCTRL_H2PM_BIT; /* H2 power mask unused */
 174                else
 175                        v |= MXC_H2_UCTRL_H2PM_BIT; /* H2 power mask used */
 176#endif
 177#ifdef CONFIG_MX53
 178                if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
 179                        v |= MXC_H2_UCTRL_H2_OC_POL_BIT;
 180                else
 181                        v &= ~MXC_H2_UCTRL_H2_OC_POL_BIT;
 182                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
 183                        v &= ~MXC_H2_UCTRL_H2_OC_DIS_BIT; /* OC is used */
 184                else
 185                        v |= MXC_H2_UCTRL_H2_OC_DIS_BIT; /* OC is not used */
 186                if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
 187                        v |= MXC_H2_UCTRL_H2_PWR_POL_BIT;
 188                else
 189                        v &= ~MXC_H2_UCTRL_H2_PWR_POL_BIT;
 190#endif
 191                __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
 192                break;
 193#ifdef CONFIG_MX53
 194        case 3: /* Host 3 ULPI */
 195                v = __raw_readl(usbother_base + MXC_USBH3CTRL_OFFSET);
 196                if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
 197                        v |= MXC_H3_UCTRL_H3_OC_POL_BIT;
 198                else
 199                        v &= ~MXC_H3_UCTRL_H3_OC_POL_BIT;
 200                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
 201                        v &= ~MXC_H3_UCTRL_H3_OC_DIS_BIT; /* OC is used */
 202                else
 203                        v |= MXC_H3_UCTRL_H3_OC_DIS_BIT; /* OC is not used */
 204                if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
 205                        v |= MXC_H3_UCTRL_H3_PWR_POL_BIT;
 206                else
 207                        v &= ~MXC_H3_UCTRL_H3_PWR_POL_BIT;
 208                __raw_writel(v, usbother_base + MXC_USBH3CTRL_OFFSET);
 209                break;
 210#endif
 211        }
 212
 213        return ret;
 214}
 215
 216int __weak board_ehci_hcd_init(int port)
 217{
 218        return 0;
 219}
 220
 221void __weak board_ehci_hcd_postinit(struct usb_ehci *ehci, int port)
 222{
 223}
 224
 225__weak void mx5_ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
 226                                   uint32_t *reg)
 227{
 228        mdelay(50);
 229}
 230
 231struct ehci_mx5_priv_data {
 232        struct ehci_ctrl ctrl;
 233        struct usb_ehci *ehci;
 234        struct udevice *vbus_supply;
 235        enum usb_init_type init_type;
 236        int portnr;
 237};
 238
 239static const struct ehci_ops mx5_ehci_ops = {
 240        .powerup_fixup          = mx5_ehci_powerup_fixup,
 241};
 242
 243static int ehci_usb_of_to_plat(struct udevice *dev)
 244{
 245        struct usb_plat *plat = dev_get_plat(dev);
 246        const char *mode;
 247
 248        mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "dr_mode", NULL);
 249        if (mode) {
 250                if (strcmp(mode, "peripheral") == 0)
 251                        plat->init_type = USB_INIT_DEVICE;
 252                else if (strcmp(mode, "host") == 0)
 253                        plat->init_type = USB_INIT_HOST;
 254                else
 255                        return -EINVAL;
 256        }
 257
 258        return 0;
 259}
 260
 261static int ehci_usb_probe(struct udevice *dev)
 262{
 263        struct usb_plat *plat = dev_get_plat(dev);
 264        struct usb_ehci *ehci = dev_read_addr_ptr(dev);
 265        struct ehci_mx5_priv_data *priv = dev_get_priv(dev);
 266        enum usb_init_type type = plat->init_type;
 267        struct ehci_hccr *hccr;
 268        struct ehci_hcor *hcor;
 269        int ret;
 270
 271        set_usboh3_clk();
 272        enable_usboh3_clk(true);
 273        set_usb_phy_clk();
 274        enable_usb_phy1_clk(true);
 275        enable_usb_phy2_clk(true);
 276        mdelay(1);
 277
 278        priv->ehci = ehci;
 279        priv->portnr = dev_seq(dev);
 280        priv->init_type = type;
 281
 282        ret = device_get_supply_regulator(dev, "vbus-supply",
 283                                          &priv->vbus_supply);
 284        if (ret)
 285                debug("%s: No vbus supply\n", dev->name);
 286
 287        if (!ret && priv->vbus_supply) {
 288                ret = regulator_set_enable(priv->vbus_supply,
 289                                           (type == USB_INIT_DEVICE) ?
 290                                           false : true);
 291                if (ret) {
 292                        puts("Error enabling VBUS supply\n");
 293                        return ret;
 294                }
 295        }
 296
 297        hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
 298        hcor = (struct ehci_hcor *)((uint32_t)hccr +
 299                        HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
 300        setbits_le32(&ehci->usbmode, CM_HOST);
 301
 302        __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
 303        setbits_le32(&ehci->portsc, USB_EN);
 304
 305        mxc_set_usbcontrol(priv->portnr, CONFIG_MXC_USB_FLAGS);
 306        mdelay(10);
 307
 308        return ehci_register(dev, hccr, hcor, &mx5_ehci_ops, 0,
 309                             priv->init_type);
 310}
 311
 312static const struct udevice_id mx5_usb_ids[] = {
 313        { .compatible = "fsl,imx53-usb" },
 314        { }
 315};
 316
 317U_BOOT_DRIVER(usb_mx5) = {
 318        .name   = "ehci_mx5",
 319        .id     = UCLASS_USB,
 320        .of_match = mx5_usb_ids,
 321        .of_to_plat = ehci_usb_of_to_plat,
 322        .probe  = ehci_usb_probe,
 323        .remove = ehci_deregister,
 324        .ops    = &ehci_usb_ops,
 325        .plat_auto      = sizeof(struct usb_plat),
 326        .priv_auto      = sizeof(struct ehci_mx5_priv_data),
 327        .flags  = DM_FLAG_ALLOC_PRIV_DMA,
 328};
 329