uboot/drivers/usb/host/xhci-mtk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2019 MediaTek, Inc.
   4 * Authors: Chunfeng Yun <chunfeng.yun@mediatek.com>
   5 */
   6
   7#include <clk.h>
   8#include <common.h>
   9#include <dm.h>
  10#include <dm/device_compat.h>
  11#include <dm/devres.h>
  12#include <generic-phy.h>
  13#include <malloc.h>
  14#include <power/regulator.h>
  15#include <usb.h>
  16#include <usb/xhci.h>
  17#include <linux/errno.h>
  18#include <linux/compat.h>
  19#include <linux/iopoll.h>
  20
  21/* IPPC (IP Port Control) registers */
  22#define IPPC_IP_PW_CTRL0                0x00
  23#define CTRL0_IP_SW_RST                 BIT(0)
  24
  25#define IPPC_IP_PW_CTRL1                0x04
  26#define CTRL1_IP_HOST_PDN               BIT(0)
  27
  28#define IPPC_IP_PW_STS1                 0x10
  29#define STS1_IP_SLEEP_STS               BIT(30)
  30#define STS1_U3_MAC_RST                 BIT(16)
  31#define STS1_XHCI_RST                   BIT(11)
  32#define STS1_SYS125_RST                 BIT(10)
  33#define STS1_REF_RST                    BIT(8)
  34#define STS1_SYSPLL_STABLE              BIT(0)
  35
  36#define IPPC_IP_XHCI_CAP                0x24
  37#define CAP_U3_PORT_NUM(p)              ((p) & 0xff)
  38#define CAP_U2_PORT_NUM(p)              (((p) >> 8) & 0xff)
  39
  40#define IPPC_U3_CTRL_0P                 0x30
  41#define CTRL_U3_PORT_HOST_SEL           BIT(2)
  42#define CTRL_U3_PORT_PDN                BIT(1)
  43#define CTRL_U3_PORT_DIS                BIT(0)
  44
  45#define IPPC_U2_CTRL_0P                 0x50
  46#define CTRL_U2_PORT_HOST_SEL           BIT(2)
  47#define CTRL_U2_PORT_PDN                BIT(1)
  48#define CTRL_U2_PORT_DIS                BIT(0)
  49
  50#define IPPC_U3_CTRL(p) (IPPC_U3_CTRL_0P + ((p) * 0x08))
  51#define IPPC_U2_CTRL(p) (IPPC_U2_CTRL_0P + ((p) * 0x08))
  52
  53struct mtk_xhci {
  54        struct xhci_ctrl ctrl;  /* Needs to come first in this struct! */
  55        struct xhci_hccr *hcd;
  56        void __iomem *ippc;
  57        struct udevice *dev;
  58        struct udevice *vusb33_supply;
  59        struct udevice *vbus_supply;
  60        struct clk_bulk clks;
  61        struct phy_bulk phys;
  62        int num_u2ports;
  63        int num_u3ports;
  64};
  65
  66static int xhci_mtk_host_enable(struct mtk_xhci *mtk)
  67{
  68        u32 value;
  69        u32 check_val;
  70        int ret;
  71        int i;
  72
  73        /* power on host ip */
  74        clrbits_le32(mtk->ippc + IPPC_IP_PW_CTRL1, CTRL1_IP_HOST_PDN);
  75
  76        /* power on and enable all u3 ports */
  77        for (i = 0; i < mtk->num_u3ports; i++) {
  78                clrsetbits_le32(mtk->ippc + IPPC_U3_CTRL(i),
  79                                CTRL_U3_PORT_PDN | CTRL_U3_PORT_DIS,
  80                                CTRL_U3_PORT_HOST_SEL);
  81        }
  82
  83        /* power on and enable all u2 ports */
  84        for (i = 0; i < mtk->num_u2ports; i++) {
  85                clrsetbits_le32(mtk->ippc + IPPC_U2_CTRL(i),
  86                                CTRL_U2_PORT_PDN | CTRL_U2_PORT_DIS,
  87                                CTRL_U2_PORT_HOST_SEL);
  88        }
  89
  90        /*
  91         * wait for clocks to be stable, and clock domains reset to
  92         * be inactive after power on and enable ports
  93         */
  94        check_val = STS1_SYSPLL_STABLE | STS1_REF_RST |
  95                        STS1_SYS125_RST | STS1_XHCI_RST;
  96
  97        if (mtk->num_u3ports)
  98                check_val |= STS1_U3_MAC_RST;
  99
 100        ret = readl_poll_timeout(mtk->ippc + IPPC_IP_PW_STS1, value,
 101                                 (check_val == (value & check_val)), 20000);
 102        if (ret)
 103                dev_err(mtk->dev, "clocks are not stable 0x%x!\n", value);
 104
 105        return ret;
 106}
 107
 108static int xhci_mtk_host_disable(struct mtk_xhci *mtk)
 109{
 110        int i;
 111
 112        /* power down all u3 ports */
 113        for (i = 0; i < mtk->num_u3ports; i++)
 114                setbits_le32(mtk->ippc + IPPC_U3_CTRL(i), CTRL_U3_PORT_PDN);
 115
 116        /* power down all u2 ports */
 117        for (i = 0; i < mtk->num_u2ports; i++)
 118                setbits_le32(mtk->ippc + IPPC_U2_CTRL(i), CTRL_U2_PORT_PDN);
 119
 120        /* power down host ip */
 121        setbits_le32(mtk->ippc + IPPC_IP_PW_CTRL1, CTRL1_IP_HOST_PDN);
 122
 123        return 0;
 124}
 125
 126static int xhci_mtk_ssusb_init(struct mtk_xhci *mtk)
 127{
 128        u32 value;
 129
 130        /* reset whole ip */
 131        setbits_le32(mtk->ippc + IPPC_IP_PW_CTRL0, CTRL0_IP_SW_RST);
 132        udelay(1);
 133        clrbits_le32(mtk->ippc + IPPC_IP_PW_CTRL0, CTRL0_IP_SW_RST);
 134
 135        value = readl(mtk->ippc + IPPC_IP_XHCI_CAP);
 136        mtk->num_u3ports = CAP_U3_PORT_NUM(value);
 137        mtk->num_u2ports = CAP_U2_PORT_NUM(value);
 138        dev_info(mtk->dev, "u2p:%d, u3p:%d\n",
 139                 mtk->num_u2ports, mtk->num_u3ports);
 140
 141        return xhci_mtk_host_enable(mtk);
 142}
 143
 144static int xhci_mtk_ofdata_get(struct mtk_xhci *mtk)
 145{
 146        struct udevice *dev = mtk->dev;
 147        int ret = 0;
 148
 149        mtk->hcd = devfdt_remap_addr_name(dev, "mac");
 150        if (!mtk->hcd) {
 151                dev_err(dev, "failed to get xHCI base address\n");
 152                return -ENXIO;
 153        }
 154
 155        mtk->ippc = devfdt_remap_addr_name(dev, "ippc");
 156        if (!mtk->ippc) {
 157                dev_err(dev, "failed to get IPPC base address\n");
 158                return -ENXIO;
 159        }
 160
 161        dev_info(dev, "hcd: 0x%p, ippc: 0x%p\n", mtk->hcd, mtk->ippc);
 162
 163        ret = clk_get_bulk(dev, &mtk->clks);
 164        if (ret) {
 165                dev_err(dev, "failed to get clocks %d!\n", ret);
 166                return ret;
 167        }
 168
 169        ret = device_get_supply_regulator(dev, "vusb33-supply",
 170                                          &mtk->vusb33_supply);
 171        if (ret)
 172                debug("can't get vusb33 regulator %d!\n", ret);
 173
 174        ret = device_get_supply_regulator(dev, "vbus-supply",
 175                                          &mtk->vbus_supply);
 176        if (ret)
 177                debug("can't get vbus regulator %d!\n", ret);
 178
 179        return 0;
 180}
 181
 182static int xhci_mtk_ldos_enable(struct mtk_xhci *mtk)
 183{
 184        int ret;
 185
 186        ret = regulator_set_enable(mtk->vusb33_supply, true);
 187        if (ret < 0 && ret != -ENOSYS) {
 188                dev_err(mtk->dev, "failed to enable vusb33 %d!\n", ret);
 189                return ret;
 190        }
 191
 192        ret = regulator_set_enable(mtk->vbus_supply, true);
 193        if (ret < 0 && ret != -ENOSYS) {
 194                dev_err(mtk->dev, "failed to enable vbus %d!\n", ret);
 195                regulator_set_enable(mtk->vusb33_supply, false);
 196                return ret;
 197        }
 198
 199        return 0;
 200}
 201
 202static void xhci_mtk_ldos_disable(struct mtk_xhci *mtk)
 203{
 204        regulator_set_enable(mtk->vbus_supply, false);
 205        regulator_set_enable(mtk->vusb33_supply, false);
 206}
 207
 208static int xhci_mtk_phy_setup(struct mtk_xhci *mtk)
 209{
 210        struct udevice *dev = mtk->dev;
 211        struct phy_bulk *phys = &mtk->phys;
 212        int ret;
 213
 214        ret = generic_phy_get_bulk(dev, phys);
 215        if (ret)
 216                return ret;
 217
 218        ret = generic_phy_init_bulk(phys);
 219        if (ret)
 220                return ret;
 221
 222        ret = generic_phy_power_on_bulk(phys);
 223        if (ret)
 224                generic_phy_exit_bulk(phys);
 225
 226        return ret;
 227}
 228
 229static void xhci_mtk_phy_shutdown(struct mtk_xhci *mtk)
 230{
 231        generic_phy_power_off_bulk(&mtk->phys);
 232        generic_phy_exit_bulk(&mtk->phys);
 233}
 234
 235static int xhci_mtk_probe(struct udevice *dev)
 236{
 237        struct mtk_xhci *mtk = dev_get_priv(dev);
 238        struct xhci_hcor *hcor;
 239        int ret;
 240
 241        mtk->dev = dev;
 242        ret = xhci_mtk_ofdata_get(mtk);
 243        if (ret)
 244                return ret;
 245
 246        ret = xhci_mtk_ldos_enable(mtk);
 247        if (ret)
 248                goto ldos_err;
 249
 250        ret = clk_enable_bulk(&mtk->clks);
 251        if (ret)
 252                goto clks_err;
 253
 254        ret = xhci_mtk_phy_setup(mtk);
 255        if (ret)
 256                goto phys_err;
 257
 258        ret = xhci_mtk_ssusb_init(mtk);
 259        if (ret)
 260                goto ssusb_init_err;
 261
 262        mtk->ctrl.quirks = XHCI_MTK_HOST;
 263        hcor = (struct xhci_hcor *)((uintptr_t)mtk->hcd +
 264                        HC_LENGTH(xhci_readl(&mtk->hcd->cr_capbase)));
 265
 266        return xhci_register(dev, mtk->hcd, hcor);
 267
 268ssusb_init_err:
 269        xhci_mtk_phy_shutdown(mtk);
 270phys_err:
 271        clk_disable_bulk(&mtk->clks);
 272clks_err:
 273        xhci_mtk_ldos_disable(mtk);
 274ldos_err:
 275        return ret;
 276}
 277
 278static int xhci_mtk_remove(struct udevice *dev)
 279{
 280        struct mtk_xhci *mtk = dev_get_priv(dev);
 281
 282        xhci_deregister(dev);
 283        xhci_mtk_host_disable(mtk);
 284        xhci_mtk_ldos_disable(mtk);
 285        clk_disable_bulk(&mtk->clks);
 286
 287        return 0;
 288}
 289
 290static const struct udevice_id xhci_mtk_ids[] = {
 291        { .compatible = "mediatek,mtk-xhci" },
 292        { }
 293};
 294
 295U_BOOT_DRIVER(usb_xhci) = {
 296        .name = "xhci-mtk",
 297        .id = UCLASS_USB,
 298        .of_match = xhci_mtk_ids,
 299        .probe = xhci_mtk_probe,
 300        .remove = xhci_mtk_remove,
 301        .ops = &xhci_usb_ops,
 302        .bind = dm_scan_fdt_dev,
 303        .priv_auto_alloc_size = sizeof(struct mtk_xhci),
 304        .flags = DM_FLAG_ALLOC_PRIV_DMA,
 305};
 306