uboot/drivers/usb/host/ehci-vf.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2015 Sanchayan Maity <sanchayan.maity@toradex.com>
   3 * Copyright (C) 2015 Toradex AG
   4 *
   5 * Based on ehci-mx6 driver
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9
  10#include <common.h>
  11#include <usb.h>
  12#include <errno.h>
  13#include <linux/compiler.h>
  14#include <asm/io.h>
  15#include <asm/arch/clock.h>
  16#include <asm/arch/imx-regs.h>
  17#include <asm/arch/crm_regs.h>
  18#include <asm/imx-common/iomux-v3.h>
  19#include <asm/imx-common/regs-usbphy.h>
  20#include <usb/ehci-fsl.h>
  21
  22#include "ehci.h"
  23
  24#define USB_NC_REG_OFFSET                               0x00000800
  25
  26#define ANADIG_PLL_CTRL_EN_USB_CLKS             (1 << 6)
  27
  28#define UCTRL_OVER_CUR_POL      (1 << 8) /* OTG Polarity of Overcurrent */
  29#define UCTRL_OVER_CUR_DIS      (1 << 7) /* Disable OTG Overcurrent Detection */
  30
  31/* USBCMD */
  32#define UCMD_RUN_STOP           (1 << 0) /* controller run/stop */
  33#define UCMD_RESET                      (1 << 1) /* controller reset */
  34
  35static const unsigned phy_bases[] = {
  36        USB_PHY0_BASE_ADDR,
  37        USB_PHY1_BASE_ADDR,
  38};
  39
  40static const unsigned nc_reg_bases[] = {
  41        USBC0_BASE_ADDR,
  42        USBC1_BASE_ADDR,
  43};
  44
  45static void usb_internal_phy_clock_gate(int index)
  46{
  47        void __iomem *phy_reg;
  48
  49        phy_reg = (void __iomem *)phy_bases[index];
  50        clrbits_le32(phy_reg + USBPHY_CTRL, USBPHY_CTRL_CLKGATE);
  51}
  52
  53static void usb_power_config(int index)
  54{
  55        struct anadig_reg __iomem *anadig =
  56                (struct anadig_reg __iomem *)ANADIG_BASE_ADDR;
  57        void __iomem *pll_ctrl;
  58
  59        switch (index) {
  60        case 0:
  61                pll_ctrl = &anadig->pll3_ctrl;
  62                clrbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_BYPASS);
  63                setbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_ENABLE
  64                         | ANADIG_PLL3_CTRL_POWERDOWN
  65                         | ANADIG_PLL_CTRL_EN_USB_CLKS);
  66                break;
  67        case 1:
  68                pll_ctrl = &anadig->pll7_ctrl;
  69                clrbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_BYPASS);
  70                setbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_ENABLE
  71                         | ANADIG_PLL7_CTRL_POWERDOWN
  72                         | ANADIG_PLL_CTRL_EN_USB_CLKS);
  73                break;
  74        default:
  75                return;
  76        }
  77}
  78
  79static void usb_phy_enable(int index, struct usb_ehci *ehci)
  80{
  81        void __iomem *phy_reg;
  82        void __iomem *phy_ctrl;
  83        void __iomem *usb_cmd;
  84
  85        phy_reg = (void __iomem *)phy_bases[index];
  86        phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
  87        usb_cmd = (void __iomem *)&ehci->usbcmd;
  88
  89        /* Stop then Reset */
  90        clrbits_le32(usb_cmd, UCMD_RUN_STOP);
  91        while (readl(usb_cmd) & UCMD_RUN_STOP)
  92                ;
  93
  94        setbits_le32(usb_cmd, UCMD_RESET);
  95        while (readl(usb_cmd) & UCMD_RESET)
  96                ;
  97
  98        /* Reset USBPHY module */
  99        setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST);
 100        udelay(10);
 101
 102        /* Remove CLKGATE and SFTRST */
 103        clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
 104        udelay(10);
 105
 106        /* Power up the PHY */
 107        writel(0, phy_reg + USBPHY_PWD);
 108
 109        /* Enable FS/LS device */
 110        setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 |
 111                 USBPHY_CTRL_ENUTMILEVEL3);
 112}
 113
 114static void usb_oc_config(int index)
 115{
 116        void __iomem *ctrl;
 117
 118        ctrl = (void __iomem *)(nc_reg_bases[index] + USB_NC_REG_OFFSET);
 119
 120        setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
 121        setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
 122}
 123
 124int __weak board_ehci_hcd_init(int port)
 125{
 126        return 0;
 127}
 128
 129int ehci_hcd_init(int index, enum usb_init_type init,
 130                struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 131{
 132        struct usb_ehci *ehci;
 133
 134        if (index >= ARRAY_SIZE(nc_reg_bases))
 135                return -EINVAL;
 136
 137        if (init == USB_INIT_DEVICE && index == 1)
 138                return -ENODEV;
 139        if (init == USB_INIT_HOST && index == 0)
 140                return -ENODEV;
 141
 142        ehci = (struct usb_ehci *)nc_reg_bases[index];
 143
 144        /* Do board specific initialisation */
 145        board_ehci_hcd_init(index);
 146
 147        usb_power_config(index);
 148        usb_oc_config(index);
 149        usb_internal_phy_clock_gate(index);
 150        usb_phy_enable(index, ehci);
 151
 152        *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
 153        *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
 154                        HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
 155
 156        if (init == USB_INIT_DEVICE) {
 157                setbits_le32(&ehci->usbmode, CM_DEVICE);
 158                writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
 159                setbits_le32(&ehci->portsc, USB_EN);
 160        } else if (init == USB_INIT_HOST) {
 161                setbits_le32(&ehci->usbmode, CM_HOST);
 162                writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
 163                setbits_le32(&ehci->portsc, USB_EN);
 164        }
 165
 166        return 0;
 167}
 168
 169int ehci_hcd_stop(int index)
 170{
 171        return 0;
 172}
 173