1 /* 2 * Meson GXL USB3 PHY driver 3 * 4 * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com> 5 * Copyright (C) 2018 BayLibre, SAS 6 * Author: Neil Armstrong <narmstron@baylibre.com> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #include <common.h> 12 #include <asm/io.h> 13 #include <bitfield.h> 14 #include <dm.h> 15 #include <errno.h> 16 #include <generic-phy.h> 17 #include <regmap.h> 18 #include <clk.h> 19 20 #include <linux/bitops.h> 21 #include <linux/compat.h> 22 #include <linux/bitfield.h> 23 24 #define USB_R0 0x00 25 #define USB_R0_P30_FSEL_MASK GENMASK(5, 0) 26 #define USB_R0_P30_PHY_RESET BIT(6) 27 #define USB_R0_P30_TEST_POWERDOWN_HSP BIT(7) 28 #define USB_R0_P30_TEST_POWERDOWN_SSP BIT(8) 29 #define USB_R0_P30_ACJT_LEVEL_MASK GENMASK(13, 9) 30 #define USB_R0_P30_TX_BOOST_LEVEL_MASK GENMASK(16, 14) 31 #define USB_R0_P30_LANE0_TX2RX_LOOPBACK BIT(17) 32 #define USB_R0_P30_LANE0_EXT_PCLK_REQ BIT(18) 33 #define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK GENMASK(28, 19) 34 #define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK GENMASK(30, 29) 35 #define USB_R0_U2D_ACT BIT(31) 36 37 #define USB_R1 0x04 38 #define USB_R1_U3H_BIGENDIAN_GS BIT(0) 39 #define USB_R1_U3H_PME_ENABLE BIT(1) 40 #define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK GENMASK(6, 2) 41 #define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK GENMASK(11, 7) 42 #define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK GENMASK(15, 12) 43 #define USB_R1_U3H_HOST_U3_PORT_DISABLE BIT(16) 44 #define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT BIT(17) 45 #define USB_R1_U3H_HOST_MSI_ENABLE BIT(18) 46 #define USB_R1_U3H_FLADJ_30MHZ_REG_MASK GENMASK(24, 19) 47 #define USB_R1_P30_PCS_TX_SWING_FULL_MASK GENMASK(31, 25) 48 49 #define USB_R2 0x08 50 #define USB_R2_P30_CR_DATA_IN_MASK GENMASK(15, 0) 51 #define USB_R2_P30_CR_READ BIT(16) 52 #define USB_R2_P30_CR_WRITE BIT(17) 53 #define USB_R2_P30_CR_CAP_ADDR BIT(18) 54 #define USB_R2_P30_CR_CAP_DATA BIT(19) 55 #define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(25, 20) 56 #define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK GENMASK(31, 26) 57 58 #define USB_R3 0x0c 59 #define USB_R3_P30_SSC_ENABLE BIT(0) 60 #define USB_R3_P30_SSC_RANGE_MASK GENMASK(3, 1) 61 #define USB_R3_P30_SSC_REF_CLK_SEL_MASK GENMASK(12, 4) 62 #define USB_R3_P30_REF_SSP_EN BIT(13) 63 #define USB_R3_P30_LOS_BIAS_MASK GENMASK(18, 16) 64 #define USB_R3_P30_LOS_LEVEL_MASK GENMASK(23, 19) 65 #define USB_R3_P30_MPLL_MULTIPLIER_MASK GENMASK(30, 24) 66 67 #define USB_R4 0x10 68 #define USB_R4_P21_PORT_RESET_0 BIT(0) 69 #define USB_R4_P21_SLEEP_M0 BIT(1) 70 #define USB_R4_MEM_PD_MASK GENMASK(3, 2) 71 #define USB_R4_P21_ONLY BIT(4) 72 73 #define USB_R5 0x14 74 #define USB_R5_ID_DIG_SYNC BIT(0) 75 #define USB_R5_ID_DIG_REG BIT(1) 76 #define USB_R5_ID_DIG_CFG_MASK GENMASK(3, 2) 77 #define USB_R5_ID_DIG_EN_0 BIT(4) 78 #define USB_R5_ID_DIG_EN_1 BIT(5) 79 #define USB_R5_ID_DIG_CURR BIT(6) 80 #define USB_R5_ID_DIG_IRQ BIT(7) 81 #define USB_R5_ID_DIG_TH_MASK GENMASK(15, 8) 82 #define USB_R5_ID_DIG_CNT_MASK GENMASK(23, 16) 83 84 /* read-only register */ 85 #define USB_R6 0x18 86 #define USB_R6_P30_CR_DATA_OUT_MASK GENMASK(15, 0) 87 #define USB_R6_P30_CR_ACK BIT(16) 88 89 struct phy_meson_gxl_usb3_priv { 90 struct regmap *regmap; 91 #if CONFIG_IS_ENABLED(CLK) 92 struct clk clk; 93 #endif 94 }; 95 96 static int 97 phy_meson_gxl_usb3_set_host_mode(struct phy_meson_gxl_usb3_priv *priv) 98 { 99 uint val; 100 101 regmap_read(priv->regmap, USB_R0, &val); 102 val &= ~USB_R0_U2D_ACT; 103 regmap_write(priv->regmap, USB_R0, val); 104 105 regmap_read(priv->regmap, USB_R4, &val); 106 val &= ~USB_R4_P21_SLEEP_M0; 107 regmap_write(priv->regmap, USB_R4, val); 108 109 return 0; 110 } 111 112 static int phy_meson_gxl_usb3_power_on(struct phy *phy) 113 { 114 struct udevice *dev = phy->dev; 115 struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); 116 uint val; 117 118 regmap_read(priv->regmap, USB_R5, &val); 119 val |= USB_R5_ID_DIG_EN_0; 120 val |= USB_R5_ID_DIG_EN_1; 121 val &= ~USB_R5_ID_DIG_TH_MASK; 122 val |= FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff); 123 regmap_write(priv->regmap, USB_R5, val); 124 125 return phy_meson_gxl_usb3_set_host_mode(priv); 126 } 127 128 static int phy_meson_gxl_usb3_power_off(struct phy *phy) 129 { 130 struct udevice *dev = phy->dev; 131 struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); 132 uint val; 133 134 regmap_read(priv->regmap, USB_R5, &val); 135 val &= ~USB_R5_ID_DIG_EN_0; 136 val &= ~USB_R5_ID_DIG_EN_1; 137 regmap_write(priv->regmap, USB_R5, val); 138 139 return 0; 140 } 141 142 static int phy_meson_gxl_usb3_init(struct phy *phy) 143 { 144 struct udevice *dev = phy->dev; 145 struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); 146 uint val; 147 148 regmap_read(priv->regmap, USB_R1, &val); 149 val &= ~USB_R1_U3H_FLADJ_30MHZ_REG_MASK; 150 val |= FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20); 151 regmap_write(priv->regmap, USB_R1, val); 152 153 return 0; 154 } 155 156 struct phy_ops meson_gxl_usb3_phy_ops = { 157 .init = phy_meson_gxl_usb3_init, 158 .power_on = phy_meson_gxl_usb3_power_on, 159 .power_off = phy_meson_gxl_usb3_power_off, 160 }; 161 162 int meson_gxl_usb3_phy_probe(struct udevice *dev) 163 { 164 struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); 165 int ret; 166 167 ret = regmap_init_mem(dev, &priv->regmap); 168 if (ret) 169 return ret; 170 171 #if CONFIG_IS_ENABLED(CLK) 172 ret = clk_get_by_index(dev, 0, &priv->clk); 173 if (ret < 0) 174 return ret; 175 176 ret = clk_enable(&priv->clk); 177 if (ret && ret != -ENOSYS && ret != -ENOTSUPP) { 178 pr_err("failed to enable PHY clock\n"); 179 clk_free(&priv->clk); 180 return ret; 181 } 182 #endif 183 184 return 0; 185 } 186 187 static const struct udevice_id meson_gxl_usb3_phy_ids[] = { 188 { .compatible = "amlogic,meson-gxl-usb3-phy" }, 189 { } 190 }; 191 192 U_BOOT_DRIVER(meson_gxl_usb3_phy) = { 193 .name = "meson_gxl_usb3_phy", 194 .id = UCLASS_PHY, 195 .of_match = meson_gxl_usb3_phy_ids, 196 .probe = meson_gxl_usb3_phy_probe, 197 .ops = &meson_gxl_usb3_phy_ops, 198 .priv_auto_alloc_size = sizeof(struct phy_meson_gxl_usb3_priv), 199 }; 200