uboot/drivers/phy/mt76x8-usb-phy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2019 Stefan Roese <sr@denx.de>
   4 *
   5 * Derived from linux/drivers/phy/ralink/phy-ralink-usb.c
   6 *     Copyright (C) 2017 John Crispin <john@phrozen.org>
   7 */
   8
   9#include <common.h>
  10#include <dm.h>
  11#include <generic-phy.h>
  12#include <regmap.h>
  13#include <reset-uclass.h>
  14#include <syscon.h>
  15#include <asm/io.h>
  16
  17#define RT_SYSC_REG_SYSCFG1             0x014
  18#define RT_SYSC_REG_CLKCFG1             0x030
  19#define RT_SYSC_REG_USB_PHY_CFG         0x05c
  20
  21#define OFS_U2_PHY_AC0                  0x800
  22#define OFS_U2_PHY_AC1                  0x804
  23#define OFS_U2_PHY_AC2                  0x808
  24#define OFS_U2_PHY_ACR0                 0x810
  25#define OFS_U2_PHY_ACR1                 0x814
  26#define OFS_U2_PHY_ACR2                 0x818
  27#define OFS_U2_PHY_ACR3                 0x81C
  28#define OFS_U2_PHY_ACR4                 0x820
  29#define OFS_U2_PHY_AMON0                0x824
  30#define OFS_U2_PHY_DCR0                 0x860
  31#define OFS_U2_PHY_DCR1                 0x864
  32#define OFS_U2_PHY_DTM0                 0x868
  33#define OFS_U2_PHY_DTM1                 0x86C
  34
  35#define RT_RSTCTRL_UDEV                 BIT(25)
  36#define RT_RSTCTRL_UHST                 BIT(22)
  37#define RT_SYSCFG1_USB0_HOST_MODE       BIT(10)
  38
  39#define MT7620_CLKCFG1_UPHY0_CLK_EN     BIT(25)
  40#define MT7620_CLKCFG1_UPHY1_CLK_EN     BIT(22)
  41#define RT_CLKCFG1_UPHY1_CLK_EN         BIT(20)
  42#define RT_CLKCFG1_UPHY0_CLK_EN         BIT(18)
  43
  44#define USB_PHY_UTMI_8B60M              BIT(1)
  45#define UDEV_WAKEUP                     BIT(0)
  46
  47struct mt76x8_usb_phy {
  48        u32                     clk;
  49        void __iomem            *base;
  50        struct regmap           *sysctl;
  51};
  52
  53static void u2_phy_w32(struct mt76x8_usb_phy *phy, u32 val, u32 reg)
  54{
  55        writel(val, phy->base + reg);
  56}
  57
  58static u32 u2_phy_r32(struct mt76x8_usb_phy *phy, u32 reg)
  59{
  60        return readl(phy->base + reg);
  61}
  62
  63static void mt76x8_usb_phy_init(struct mt76x8_usb_phy *phy)
  64{
  65        u2_phy_r32(phy, OFS_U2_PHY_AC2);
  66        u2_phy_r32(phy, OFS_U2_PHY_ACR0);
  67        u2_phy_r32(phy, OFS_U2_PHY_DCR0);
  68
  69        u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0);
  70        u2_phy_r32(phy, OFS_U2_PHY_DCR0);
  71        u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0);
  72        u2_phy_r32(phy, OFS_U2_PHY_DCR0);
  73        u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0);
  74        u2_phy_r32(phy, OFS_U2_PHY_DCR0);
  75        u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0);
  76        u2_phy_r32(phy, OFS_U2_PHY_DCR0);
  77        u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0);
  78        u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1);
  79        u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3);
  80        u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0);
  81}
  82
  83static int mt76x8_usb_phy_power_on(struct phy *_phy)
  84{
  85        struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev);
  86        u32 t;
  87
  88        /* enable the phy */
  89        regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
  90                           phy->clk, phy->clk);
  91
  92        /* setup host mode */
  93        regmap_update_bits(phy->sysctl, RT_SYSC_REG_SYSCFG1,
  94                           RT_SYSCFG1_USB0_HOST_MODE,
  95                           RT_SYSCFG1_USB0_HOST_MODE);
  96
  97        /*
  98         * The SDK kernel had a delay of 100ms. however on device
  99         * testing showed that 10ms is enough
 100         */
 101        mdelay(10);
 102
 103        if (phy->base)
 104                mt76x8_usb_phy_init(phy);
 105
 106        /* print some status info */
 107        regmap_read(phy->sysctl, RT_SYSC_REG_USB_PHY_CFG, &t);
 108        printf("remote usb device wakeup %s\n",
 109               (t & UDEV_WAKEUP) ? "enabled" : "disabled");
 110        if (t & USB_PHY_UTMI_8B60M)
 111                printf("UTMI 8bit 60MHz\n");
 112        else
 113                printf("UTMI 16bit 30MHz\n");
 114
 115        return 0;
 116}
 117
 118static int mt76x8_usb_phy_power_off(struct phy *_phy)
 119{
 120        struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev);
 121
 122        /* disable the phy */
 123        regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
 124                           phy->clk, 0);
 125
 126        return 0;
 127}
 128
 129static int mt76x8_usb_phy_probe(struct udevice *dev)
 130{
 131        struct mt76x8_usb_phy *phy = dev_get_priv(dev);
 132
 133        phy->sysctl = syscon_regmap_lookup_by_phandle(dev, "ralink,sysctl");
 134        if (IS_ERR(phy->sysctl))
 135                return PTR_ERR(phy->sysctl);
 136
 137        phy->base = dev_read_addr_ptr(dev);
 138        if (!phy->base)
 139                return -EINVAL;
 140
 141        return 0;
 142}
 143
 144static struct phy_ops mt76x8_usb_phy_ops = {
 145        .power_on = mt76x8_usb_phy_power_on,
 146        .power_off = mt76x8_usb_phy_power_off,
 147};
 148
 149static const struct udevice_id mt76x8_usb_phy_ids[] = {
 150        { .compatible = "mediatek,mt7628-usbphy" },
 151        { }
 152};
 153
 154U_BOOT_DRIVER(mt76x8_usb_phy) = {
 155        .name           = "mt76x8_usb_phy",
 156        .id             = UCLASS_PHY,
 157        .of_match       = mt76x8_usb_phy_ids,
 158        .ops            = &mt76x8_usb_phy_ops,
 159        .probe          = mt76x8_usb_phy_probe,
 160        .priv_auto_alloc_size = sizeof(struct mt76x8_usb_phy),
 161};
 162