uboot/drivers/usb/musb-new/mt85xx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Mediatek "glue layer"
   4 *
   5 * Copyright (C) 2019-2021 by Mediatek
   6 * Based on the AllWinner SUNXI "glue layer" code.
   7 * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
   8 * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
   9 *
  10 * This file is part of the Inventra Controller Driver for Linux.
  11 */
  12#include <common.h>
  13#include <clk.h>
  14#include <dm.h>
  15#include <dm/device_compat.h>
  16#include <dm/lists.h>
  17#include <dm/root.h>
  18#include <linux/delay.h>
  19#include <linux/usb/musb.h>
  20#include <usb.h>
  21#include "linux-compat.h"
  22#include "musb_core.h"
  23#include "musb_uboot.h"
  24
  25#define DBG_I(fmt, ...) \
  26        pr_info(fmt, ##__VA_ARGS__)
  27
  28struct mtk_musb_config {
  29        struct musb_hdrc_config *config;
  30};
  31
  32struct mtk_musb_glue {
  33        struct musb_host_data mdata;
  34        struct clk usbpllclk;
  35        struct clk usbmcuclk;
  36        struct clk usbclk;
  37        struct mtk_musb_config *cfg;
  38        struct device dev;
  39};
  40
  41#define to_mtk_musb_glue(d)     container_of(d, struct mtk_musb_glue, dev)
  42
  43/******************************************************************************
  44 * phy settings
  45 ******************************************************************************/
  46#define USB20_PHY_BASE                  0x11110800
  47#define USBPHY_READ8(offset)     \
  48        readb((void *)(USB20_PHY_BASE + (offset)))
  49#define USBPHY_WRITE8(offset, value)    \
  50        writeb(value, (void *)(USB20_PHY_BASE + (offset)))
  51#define USBPHY_SET8(offset, mask)       \
  52        USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) | (mask))
  53#define USBPHY_CLR8(offset, mask)       \
  54        USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) & (~(mask)))
  55
  56static void mt_usb_phy_poweron(void)
  57{
  58        /*
  59         * switch to USB function.
  60         * (system register, force ip into usb mode).
  61         */
  62        USBPHY_CLR8(0x6b, 0x04);
  63        USBPHY_CLR8(0x6e, 0x01);
  64        USBPHY_CLR8(0x21, 0x03);
  65
  66        /* RG_USB20_BC11_SW_EN = 1'b0 */
  67        USBPHY_SET8(0x22, 0x04);
  68        USBPHY_CLR8(0x1a, 0x80);
  69
  70        /* RG_USB20_DP_100K_EN = 1'b0 */
  71        /* RG_USB20_DP_100K_EN = 1'b0 */
  72        USBPHY_CLR8(0x22, 0x03);
  73
  74        /*OTG enable*/
  75        USBPHY_SET8(0x20, 0x10);
  76        /* release force suspendm */
  77        USBPHY_CLR8(0x6a, 0x04);
  78
  79        mdelay(800);
  80
  81        /* force enter device mode */
  82        USBPHY_CLR8(0x6c, 0x10);
  83        USBPHY_SET8(0x6c, 0x2E);
  84        USBPHY_SET8(0x6d, 0x3E);
  85}
  86
  87static void mt_usb_phy_savecurrent(void)
  88{
  89        /*
  90         * switch to USB function.
  91         * (system register, force ip into usb mode).
  92         */
  93        USBPHY_CLR8(0x6b, 0x04);
  94        USBPHY_CLR8(0x6e, 0x01);
  95        USBPHY_CLR8(0x21, 0x03);
  96
  97        /* release force suspendm */
  98        USBPHY_CLR8(0x6a, 0x04);
  99        USBPHY_SET8(0x68, 0x04);
 100        /* RG_DPPULLDOWN./RG_DMPULLDOWN. */
 101        USBPHY_SET8(0x68, 0xc0);
 102        /* RG_XCVRSEL[1:0] = 2'b01 */
 103        USBPHY_CLR8(0x68, 0x30);
 104        USBPHY_SET8(0x68, 0x10);
 105        /* RG_TERMSEL = 1'b1 */
 106        USBPHY_SET8(0x68, 0x04);
 107        /* RG_DATAIN[3:0] = 4'b0000 */
 108        USBPHY_CLR8(0x69, 0x3c);
 109
 110        /*
 111         * force_dp_pulldown, force_dm_pulldown,
 112         * force_xcversel, force_termsel.
 113         */
 114        USBPHY_SET8(0x6a, 0xba);
 115
 116        /* RG_USB20_BC11_SW_EN = 1'b0 */
 117        USBPHY_CLR8(0x1a, 0x80);
 118        /* RG_USB20_OTG_VBUSSCMP_EN = 1'b0 */
 119        USBPHY_CLR8(0x1a, 0x10);
 120
 121        mdelay(800);
 122
 123        USBPHY_CLR8(0x6a, 0x04);
 124        /* rg_usb20_pll_stable = 1 */
 125        //USBPHY_SET8(0x63, 0x02);
 126
 127        mdelay(1);
 128
 129        /* force suspendm = 1 */
 130        //USBPHY_SET8(0x6a, 0x04);
 131}
 132
 133static void mt_usb_phy_recover(void)
 134{
 135        /* clean PUPD_BIST_EN */
 136        /* PUPD_BIST_EN = 1'b0 */
 137        /* PMIC will use it to detect charger type */
 138        USBPHY_CLR8(0x1d, 0x10);
 139
 140        /* force_uart_en = 1'b0 */
 141        USBPHY_CLR8(0x6b, 0x04);
 142        /* RG_UART_EN = 1'b0 */
 143        USBPHY_CLR8(0x6e, 0x01);
 144        /* force_uart_en = 1'b0 */
 145        USBPHY_CLR8(0x6a, 0x04);
 146
 147        USBPHY_CLR8(0x21, 0x03);
 148        USBPHY_CLR8(0x68, 0xf4);
 149
 150        /* RG_DATAIN[3:0] = 4'b0000 */
 151        USBPHY_CLR8(0x69, 0x3c);
 152
 153        USBPHY_CLR8(0x6a, 0xba);
 154
 155        /* RG_USB20_BC11_SW_EN = 1'b0 */
 156        USBPHY_CLR8(0x1a, 0x80);
 157        /* RG_USB20_OTG_VBUSSCMP_EN = 1'b1 */
 158        USBPHY_SET8(0x1a, 0x10);
 159
 160        //HQA adjustment
 161        USBPHY_CLR8(0x18, 0x08);
 162        USBPHY_SET8(0x18, 0x06);
 163        mdelay(800);
 164
 165        /* force enter device mode */
 166        //USBPHY_CLR8(0x6c, 0x10);
 167        //USBPHY_SET8(0x6c, 0x2E);
 168        //USBPHY_SET8(0x6d, 0x3E);
 169
 170        /* enable VRT internal R architecture */
 171        /* RG_USB20_INTR_EN = 1'b1 */
 172        USBPHY_SET8(0x00, 0x20);
 173}
 174
 175/******************************************************************************
 176 * MUSB Glue code
 177 ******************************************************************************/
 178
 179static irqreturn_t mtk_musb_interrupt(int irq, void *__hci)
 180{
 181        struct musb             *musb = __hci;
 182        irqreturn_t             retval = IRQ_NONE;
 183
 184        /* read and flush interrupts */
 185        musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
 186//      last_int_usb = musb->int_usb;
 187        if (musb->int_usb)
 188                musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb);
 189        musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
 190        if (musb->int_tx)
 191                musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx);
 192        musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
 193        if (musb->int_rx)
 194                musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx);
 195
 196        if (musb->int_usb || musb->int_tx || musb->int_rx)
 197                retval |= musb_interrupt(musb);
 198
 199        return retval;
 200}
 201
 202/* musb_core does not call enable / disable in a balanced manner <sigh> */
 203static bool enabled;
 204
 205static int mtk_musb_enable(struct musb *musb)
 206{
 207        struct mtk_musb_glue *glue = to_mtk_musb_glue(musb->controller);
 208
 209        DBG_I("%s():\n", __func__);
 210
 211        musb_ep_select(musb->mregs, 0);
 212        musb_writeb(musb->mregs, MUSB_FADDR, 0);
 213
 214        if (enabled)
 215                return 0;
 216
 217        mt_usb_phy_recover();
 218
 219        enabled = true;
 220
 221        return 0;
 222}
 223
 224static void mtk_musb_disable(struct musb *musb)
 225{
 226        struct mtk_musb_glue *glue = to_mtk_musb_glue(musb->controller);
 227        int ret;
 228
 229        DBG_I("%s():\n", __func__);
 230
 231        if (!enabled)
 232                return;
 233
 234        mt_usb_phy_savecurrent();
 235
 236        enabled = false;
 237}
 238
 239static int mtk_musb_init(struct musb *musb)
 240{
 241        struct mtk_musb_glue *glue = to_mtk_musb_glue(musb->controller);
 242        int ret;
 243
 244        DBG_I("%s():\n", __func__);
 245
 246        ret = clk_enable(&glue->usbpllclk);
 247        if (ret) {
 248                dev_err(musb->controller, "failed to enable usbpll clock\n");
 249                return ret;
 250        }
 251        ret = clk_enable(&glue->usbmcuclk);
 252        if (ret) {
 253                dev_err(musb->controller, "failed to enable usbmcu clock\n");
 254                return ret;
 255        }
 256        ret = clk_enable(&glue->usbclk);
 257        if (ret) {
 258                dev_err(musb->controller, "failed to enable usb clock\n");
 259                return ret;
 260        }
 261
 262        musb->isr = mtk_musb_interrupt;
 263
 264        return 0;
 265}
 266
 267static int mtk_musb_exit(struct musb *musb)
 268{
 269        struct mtk_musb_glue *glue = to_mtk_musb_glue(musb->controller);
 270
 271        clk_disable(&glue->usbclk);
 272        clk_disable(&glue->usbmcuclk);
 273        clk_disable(&glue->usbpllclk);
 274
 275        return 0;
 276}
 277
 278static const struct musb_platform_ops mtk_musb_ops = {
 279        .init           = mtk_musb_init,
 280        .exit           = mtk_musb_exit,
 281        .enable         = mtk_musb_enable,
 282        .disable        = mtk_musb_disable,
 283};
 284
 285/* MTK OTG supports up to 7 endpoints */
 286#define MTK_MUSB_MAX_EP_NUM             8
 287#define MTK_MUSB_RAM_BITS               16
 288
 289static struct musb_fifo_cfg mtk_musb_mode_cfg[] = {
 290        MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
 291        MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
 292        MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
 293        MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
 294        MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
 295        MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
 296        MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
 297        MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
 298        MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512),
 299        MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512),
 300        MUSB_EP_FIFO_SINGLE(6, FIFO_TX, 512),
 301        MUSB_EP_FIFO_SINGLE(6, FIFO_RX, 512),
 302        MUSB_EP_FIFO_SINGLE(7, FIFO_TX, 512),
 303        MUSB_EP_FIFO_SINGLE(7, FIFO_RX, 512),
 304};
 305
 306static struct musb_hdrc_config musb_config = {
 307        .fifo_cfg       = mtk_musb_mode_cfg,
 308        .fifo_cfg_size  = ARRAY_SIZE(mtk_musb_mode_cfg),
 309        .multipoint     = true,
 310        .dyn_fifo       = true,
 311        .num_eps        = MTK_MUSB_MAX_EP_NUM,
 312        .ram_bits       = MTK_MUSB_RAM_BITS,
 313};
 314
 315static int musb_usb_probe(struct udevice *dev)
 316{
 317        struct mtk_musb_glue *glue = dev_get_priv(dev);
 318        struct musb_host_data *host = &glue->mdata;
 319        struct musb_hdrc_platform_data pdata;
 320        void *base = dev_read_addr_ptr(dev);
 321        int ret;
 322
 323        DBG_I("%s():\n", __func__);
 324
 325#ifdef CONFIG_USB_MUSB_HOST
 326        struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
 327#endif
 328
 329        if (!base)
 330                return -EINVAL;
 331
 332        glue->cfg = (struct mtk_musb_config *)dev_get_driver_data(dev);
 333        if (!glue->cfg)
 334                return -EINVAL;
 335
 336        ret = clk_get_by_name(dev, "usbpll", &glue->usbpllclk);
 337        if (ret) {
 338                dev_err(dev, "failed to get usbpll clock\n");
 339                return ret;
 340        }
 341        ret = clk_get_by_name(dev, "usbmcu", &glue->usbmcuclk);
 342        if (ret) {
 343                dev_err(dev, "failed to get usbmcu clock\n");
 344                return ret;
 345        }
 346        ret = clk_get_by_name(dev, "usb", &glue->usbclk);
 347        if (ret) {
 348                dev_err(dev, "failed to get usb clock\n");
 349                return ret;
 350        }
 351
 352        memset(&pdata, 0, sizeof(pdata));
 353        pdata.power = (u8)400;
 354        pdata.platform_ops = &mtk_musb_ops;
 355        pdata.config = glue->cfg->config;
 356
 357#ifdef CONFIG_USB_MUSB_HOST
 358        priv->desc_before_addr = true;
 359
 360        pdata.mode = MUSB_HOST;
 361        host->host = musb_init_controller(&pdata, &glue->dev, base);
 362        if (!host->host)
 363                return -EIO;
 364
 365        ret = musb_lowlevel_init(host);
 366        if (!ret)
 367                printf("MTK MUSB OTG (Host)\n");
 368#else
 369        pdata.mode = MUSB_PERIPHERAL;
 370        host->host = musb_register(&pdata, &glue->dev, base);
 371        if (!host->host)
 372                return -EIO;
 373
 374        printf("MTK MUSB OTG (Peripheral)\n");
 375#endif
 376
 377        mt_usb_phy_poweron();
 378
 379        return ret;
 380}
 381
 382static int musb_usb_remove(struct udevice *dev)
 383{
 384        struct mtk_musb_glue *glue = dev_get_priv(dev);
 385        struct musb_host_data *host = &glue->mdata;
 386
 387        musb_stop(host->host);
 388        free(host->host);
 389        host->host = NULL;
 390
 391        return 0;
 392}
 393
 394static const struct mtk_musb_config mt8518_cfg = {
 395        .config = &musb_config,
 396};
 397
 398static const struct udevice_id mtk_musb_ids[] = {
 399        { .compatible = "mediatek,mt8518-musb",
 400          .data = (ulong)&mt8518_cfg },
 401        { }
 402};
 403
 404U_BOOT_DRIVER(mtk_musb) = {
 405        .name           = "mtk_musb",
 406#ifdef CONFIG_USB_MUSB_HOST
 407        .id             = UCLASS_USB,
 408#else
 409        .id             = UCLASS_USB_GADGET_GENERIC,
 410#endif
 411        .of_match       = mtk_musb_ids,
 412        .probe          = musb_usb_probe,
 413        .remove         = musb_usb_remove,
 414#ifdef CONFIG_USB_MUSB_HOST
 415        .ops            = &musb_usb_ops,
 416#endif
 417        .plat_auto      = sizeof(struct usb_plat),
 418        .priv_auto      = sizeof(struct mtk_musb_glue),
 419};
 420