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