384 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Meson G12A USB2 PHY driver4 *5 * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>6 * Copyright (C) 2017 Amlogic, Inc. All rights reserved7 * Copyright (C) 2019 BayLibre, SAS8 * Author: Neil Armstrong <narmstrong@baylibre.com>9 */10 11#include <linux/bitfield.h>12#include <linux/bitops.h>13#include <linux/clk.h>14#include <linux/delay.h>15#include <linux/io.h>16#include <linux/module.h>17#include <linux/of.h>18#include <linux/regmap.h>19#include <linux/reset.h>20#include <linux/phy/phy.h>21#include <linux/platform_device.h>22 23#define PHY_CTRL_R0 0x024#define PHY_CTRL_R1 0x425#define PHY_CTRL_R2 0x826#define PHY_CTRL_R3 0xc27 #define PHY_CTRL_R3_SQUELCH_REF GENMASK(1, 0)28 #define PHY_CTRL_R3_HSDIC_REF GENMASK(3, 2)29 #define PHY_CTRL_R3_DISC_THRESH GENMASK(7, 4)30 31#define PHY_CTRL_R4 0x1032 #define PHY_CTRL_R4_CALIB_CODE_7_0 GENMASK(7, 0)33 #define PHY_CTRL_R4_CALIB_CODE_15_8 GENMASK(15, 8)34 #define PHY_CTRL_R4_CALIB_CODE_23_16 GENMASK(23, 16)35 #define PHY_CTRL_R4_I_C2L_CAL_EN BIT(24)36 #define PHY_CTRL_R4_I_C2L_CAL_RESET_N BIT(25)37 #define PHY_CTRL_R4_I_C2L_CAL_DONE BIT(26)38 #define PHY_CTRL_R4_TEST_BYPASS_MODE_EN BIT(27)39 #define PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0 GENMASK(29, 28)40 #define PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2 GENMASK(31, 30)41 42#define PHY_CTRL_R5 0x1443#define PHY_CTRL_R6 0x1844#define PHY_CTRL_R7 0x1c45#define PHY_CTRL_R8 0x2046#define PHY_CTRL_R9 0x2447#define PHY_CTRL_R10 0x2848#define PHY_CTRL_R11 0x2c49#define PHY_CTRL_R12 0x3050#define PHY_CTRL_R13 0x3451 #define PHY_CTRL_R13_CUSTOM_PATTERN_19 GENMASK(7, 0)52 #define PHY_CTRL_R13_LOAD_STAT BIT(14)53 #define PHY_CTRL_R13_UPDATE_PMA_SIGNALS BIT(15)54 #define PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET GENMASK(20, 16)55 #define PHY_CTRL_R13_CLEAR_HOLD_HS_DISCONNECT BIT(21)56 #define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_VAL BIT(22)57 #define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_EN BIT(23)58 #define PHY_CTRL_R13_I_C2L_HS_EN BIT(24)59 #define PHY_CTRL_R13_I_C2L_FS_EN BIT(25)60 #define PHY_CTRL_R13_I_C2L_LS_EN BIT(26)61 #define PHY_CTRL_R13_I_C2L_HS_OE BIT(27)62 #define PHY_CTRL_R13_I_C2L_FS_OE BIT(28)63 #define PHY_CTRL_R13_I_C2L_HS_RX_EN BIT(29)64 #define PHY_CTRL_R13_I_C2L_FSLS_RX_EN BIT(30)65 66#define PHY_CTRL_R14 0x3867 #define PHY_CTRL_R14_I_RDP_EN BIT(0)68 #define PHY_CTRL_R14_I_RPU_SW1_EN BIT(1)69 #define PHY_CTRL_R14_I_RPU_SW2_EN GENMASK(3, 2)70 #define PHY_CTRL_R14_PG_RSTN BIT(4)71 #define PHY_CTRL_R14_I_C2L_DATA_16_8 BIT(5)72 #define PHY_CTRL_R14_I_C2L_ASSERT_SINGLE_EN_ZERO BIT(6)73 #define PHY_CTRL_R14_BYPASS_CTRL_7_0 GENMASK(15, 8)74 #define PHY_CTRL_R14_BYPASS_CTRL_15_8 GENMASK(23, 16)75 76#define PHY_CTRL_R15 0x3c77#define PHY_CTRL_R16 0x4078 #define PHY_CTRL_R16_MPLL_M GENMASK(8, 0)79 #define PHY_CTRL_R16_MPLL_N GENMASK(14, 10)80 #define PHY_CTRL_R16_MPLL_TDC_MODE BIT(20)81 #define PHY_CTRL_R16_MPLL_SDM_EN BIT(21)82 #define PHY_CTRL_R16_MPLL_LOAD BIT(22)83 #define PHY_CTRL_R16_MPLL_DCO_SDM_EN BIT(23)84 #define PHY_CTRL_R16_MPLL_LOCK_LONG GENMASK(25, 24)85 #define PHY_CTRL_R16_MPLL_LOCK_F BIT(26)86 #define PHY_CTRL_R16_MPLL_FAST_LOCK BIT(27)87 #define PHY_CTRL_R16_MPLL_EN BIT(28)88 #define PHY_CTRL_R16_MPLL_RESET BIT(29)89 #define PHY_CTRL_R16_MPLL_LOCK BIT(30)90 #define PHY_CTRL_R16_MPLL_LOCK_DIG BIT(31)91 92#define PHY_CTRL_R17 0x4493 #define PHY_CTRL_R17_MPLL_FRAC_IN GENMASK(13, 0)94 #define PHY_CTRL_R17_MPLL_FIX_EN BIT(16)95 #define PHY_CTRL_R17_MPLL_LAMBDA1 GENMASK(19, 17)96 #define PHY_CTRL_R17_MPLL_LAMBDA0 GENMASK(22, 20)97 #define PHY_CTRL_R17_MPLL_FILTER_MODE BIT(23)98 #define PHY_CTRL_R17_MPLL_FILTER_PVT2 GENMASK(27, 24)99 #define PHY_CTRL_R17_MPLL_FILTER_PVT1 GENMASK(31, 28)100 101#define PHY_CTRL_R18 0x48102 #define PHY_CTRL_R18_MPLL_LKW_SEL GENMASK(1, 0)103 #define PHY_CTRL_R18_MPLL_LK_W GENMASK(5, 2)104 #define PHY_CTRL_R18_MPLL_LK_S GENMASK(11, 6)105 #define PHY_CTRL_R18_MPLL_DCO_M_EN BIT(12)106 #define PHY_CTRL_R18_MPLL_DCO_CLK_SEL BIT(13)107 #define PHY_CTRL_R18_MPLL_PFD_GAIN GENMASK(15, 14)108 #define PHY_CTRL_R18_MPLL_ROU GENMASK(18, 16)109 #define PHY_CTRL_R18_MPLL_DATA_SEL GENMASK(21, 19)110 #define PHY_CTRL_R18_MPLL_BIAS_ADJ GENMASK(23, 22)111 #define PHY_CTRL_R18_MPLL_BB_MODE GENMASK(25, 24)112 #define PHY_CTRL_R18_MPLL_ALPHA GENMASK(28, 26)113 #define PHY_CTRL_R18_MPLL_ADJ_LDO GENMASK(30, 29)114 #define PHY_CTRL_R18_MPLL_ACG_RANGE BIT(31)115 116#define PHY_CTRL_R19 0x4c117#define PHY_CTRL_R20 0x50118 #define PHY_CTRL_R20_USB2_IDDET_EN BIT(0)119 #define PHY_CTRL_R20_USB2_OTG_VBUS_TRIM_2_0 GENMASK(3, 1)120 #define PHY_CTRL_R20_USB2_OTG_VBUSDET_EN BIT(4)121 #define PHY_CTRL_R20_USB2_AMON_EN BIT(5)122 #define PHY_CTRL_R20_USB2_CAL_CODE_R5 BIT(6)123 #define PHY_CTRL_R20_BYPASS_OTG_DET BIT(7)124 #define PHY_CTRL_R20_USB2_DMON_EN BIT(8)125 #define PHY_CTRL_R20_USB2_DMON_SEL_3_0 GENMASK(12, 9)126 #define PHY_CTRL_R20_USB2_EDGE_DRV_EN BIT(13)127 #define PHY_CTRL_R20_USB2_EDGE_DRV_TRIM_1_0 GENMASK(15, 14)128 #define PHY_CTRL_R20_USB2_BGR_ADJ_4_0 GENMASK(20, 16)129 #define PHY_CTRL_R20_USB2_BGR_START BIT(21)130 #define PHY_CTRL_R20_USB2_BGR_VREF_4_0 GENMASK(28, 24)131 #define PHY_CTRL_R20_USB2_BGR_DBG_1_0 GENMASK(30, 29)132 #define PHY_CTRL_R20_BYPASS_CAL_DONE_R5 BIT(31)133 134#define PHY_CTRL_R21 0x54135 #define PHY_CTRL_R21_USB2_BGR_FORCE BIT(0)136 #define PHY_CTRL_R21_USB2_CAL_ACK_EN BIT(1)137 #define PHY_CTRL_R21_USB2_OTG_ACA_EN BIT(2)138 #define PHY_CTRL_R21_USB2_TX_STRG_PD BIT(3)139 #define PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0 GENMASK(5, 4)140 #define PHY_CTRL_R21_BYPASS_UTMI_CNTR GENMASK(15, 6)141 #define PHY_CTRL_R21_BYPASS_UTMI_REG GENMASK(25, 20)142 143#define PHY_CTRL_R22 0x58144#define PHY_CTRL_R23 0x5c145 146#define RESET_COMPLETE_TIME 1000147#define PLL_RESET_COMPLETE_TIME 100148 149enum meson_soc_id {150 MESON_SOC_G12A = 0,151 MESON_SOC_A1,152};153 154struct phy_meson_g12a_usb2_priv {155 struct device *dev;156 struct regmap *regmap;157 struct clk *clk;158 struct reset_control *reset;159 int soc_id;160};161 162static const struct regmap_config phy_meson_g12a_usb2_regmap_conf = {163 .reg_bits = 8,164 .val_bits = 32,165 .reg_stride = 4,166 .max_register = PHY_CTRL_R23,167};168 169static int phy_meson_g12a_usb2_init(struct phy *phy)170{171 struct phy_meson_g12a_usb2_priv *priv = phy_get_drvdata(phy);172 int ret;173 unsigned int value;174 175 ret = clk_prepare_enable(priv->clk);176 if (ret)177 return ret;178 179 ret = reset_control_reset(priv->reset);180 if (ret) {181 clk_disable_unprepare(priv->clk);182 return ret;183 }184 185 udelay(RESET_COMPLETE_TIME);186 187 /* usb2_otg_aca_en == 0 */188 regmap_update_bits(priv->regmap, PHY_CTRL_R21,189 PHY_CTRL_R21_USB2_OTG_ACA_EN, 0);190 191 /* PLL Setup : 24MHz * 20 / 1 = 480MHz */192 regmap_write(priv->regmap, PHY_CTRL_R16,193 FIELD_PREP(PHY_CTRL_R16_MPLL_M, 20) |194 FIELD_PREP(PHY_CTRL_R16_MPLL_N, 1) |195 PHY_CTRL_R16_MPLL_LOAD |196 FIELD_PREP(PHY_CTRL_R16_MPLL_LOCK_LONG, 1) |197 PHY_CTRL_R16_MPLL_FAST_LOCK |198 PHY_CTRL_R16_MPLL_EN |199 PHY_CTRL_R16_MPLL_RESET);200 201 regmap_write(priv->regmap, PHY_CTRL_R17,202 FIELD_PREP(PHY_CTRL_R17_MPLL_FRAC_IN, 0) |203 FIELD_PREP(PHY_CTRL_R17_MPLL_LAMBDA1, 7) |204 FIELD_PREP(PHY_CTRL_R17_MPLL_LAMBDA0, 7) |205 FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT2, 2) |206 FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT1, 9));207 208 value = FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |209 FIELD_PREP(PHY_CTRL_R18_MPLL_LK_W, 9) |210 FIELD_PREP(PHY_CTRL_R18_MPLL_LK_S, 0x27) |211 FIELD_PREP(PHY_CTRL_R18_MPLL_PFD_GAIN, 1) |212 FIELD_PREP(PHY_CTRL_R18_MPLL_ROU, 7) |213 FIELD_PREP(PHY_CTRL_R18_MPLL_DATA_SEL, 3) |214 FIELD_PREP(PHY_CTRL_R18_MPLL_BIAS_ADJ, 1) |215 FIELD_PREP(PHY_CTRL_R18_MPLL_BB_MODE, 0) |216 FIELD_PREP(PHY_CTRL_R18_MPLL_ALPHA, 3) |217 FIELD_PREP(PHY_CTRL_R18_MPLL_ADJ_LDO, 1) |218 PHY_CTRL_R18_MPLL_ACG_RANGE;219 220 if (priv->soc_id == MESON_SOC_A1)221 value |= PHY_CTRL_R18_MPLL_DCO_CLK_SEL;222 223 regmap_write(priv->regmap, PHY_CTRL_R18, value);224 225 udelay(PLL_RESET_COMPLETE_TIME);226 227 /* UnReset PLL */228 regmap_write(priv->regmap, PHY_CTRL_R16,229 FIELD_PREP(PHY_CTRL_R16_MPLL_M, 20) |230 FIELD_PREP(PHY_CTRL_R16_MPLL_N, 1) |231 PHY_CTRL_R16_MPLL_LOAD |232 FIELD_PREP(PHY_CTRL_R16_MPLL_LOCK_LONG, 1) |233 PHY_CTRL_R16_MPLL_FAST_LOCK |234 PHY_CTRL_R16_MPLL_EN);235 236 /* PHY Tuning */237 regmap_write(priv->regmap, PHY_CTRL_R20,238 FIELD_PREP(PHY_CTRL_R20_USB2_OTG_VBUS_TRIM_2_0, 4) |239 PHY_CTRL_R20_USB2_OTG_VBUSDET_EN |240 FIELD_PREP(PHY_CTRL_R20_USB2_DMON_SEL_3_0, 15) |241 PHY_CTRL_R20_USB2_EDGE_DRV_EN |242 FIELD_PREP(PHY_CTRL_R20_USB2_EDGE_DRV_TRIM_1_0, 3) |243 FIELD_PREP(PHY_CTRL_R20_USB2_BGR_ADJ_4_0, 0) |244 FIELD_PREP(PHY_CTRL_R20_USB2_BGR_VREF_4_0, 0) |245 FIELD_PREP(PHY_CTRL_R20_USB2_BGR_DBG_1_0, 0));246 247 if (priv->soc_id == MESON_SOC_G12A)248 regmap_write(priv->regmap, PHY_CTRL_R4,249 FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |250 FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |251 FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |252 PHY_CTRL_R4_TEST_BYPASS_MODE_EN |253 FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |254 FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));255 else if (priv->soc_id == MESON_SOC_A1) {256 regmap_write(priv->regmap, PHY_CTRL_R21,257 PHY_CTRL_R21_USB2_CAL_ACK_EN |258 PHY_CTRL_R21_USB2_TX_STRG_PD |259 FIELD_PREP(PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0, 2));260 261 /* Analog Settings */262 regmap_write(priv->regmap, PHY_CTRL_R13,263 FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));264 }265 266 /* Tuning Disconnect Threshold */267 regmap_write(priv->regmap, PHY_CTRL_R3,268 FIELD_PREP(PHY_CTRL_R3_SQUELCH_REF, 0) |269 FIELD_PREP(PHY_CTRL_R3_HSDIC_REF, 1) |270 FIELD_PREP(PHY_CTRL_R3_DISC_THRESH, 3));271 272 if (priv->soc_id == MESON_SOC_G12A) {273 /* Analog Settings */274 regmap_write(priv->regmap, PHY_CTRL_R14, 0);275 regmap_write(priv->regmap, PHY_CTRL_R13,276 PHY_CTRL_R13_UPDATE_PMA_SIGNALS |277 FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));278 }279 280 return 0;281}282 283static int phy_meson_g12a_usb2_exit(struct phy *phy)284{285 struct phy_meson_g12a_usb2_priv *priv = phy_get_drvdata(phy);286 int ret;287 288 ret = reset_control_reset(priv->reset);289 if (!ret)290 clk_disable_unprepare(priv->clk);291 292 return ret;293}294 295/* set_mode is not needed, mode setting is handled via the UTMI bus */296static const struct phy_ops phy_meson_g12a_usb2_ops = {297 .init = phy_meson_g12a_usb2_init,298 .exit = phy_meson_g12a_usb2_exit,299 .owner = THIS_MODULE,300};301 302static int phy_meson_g12a_usb2_probe(struct platform_device *pdev)303{304 struct device *dev = &pdev->dev;305 struct phy_provider *phy_provider;306 struct phy_meson_g12a_usb2_priv *priv;307 struct phy *phy;308 void __iomem *base;309 int ret;310 311 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);312 if (!priv)313 return -ENOMEM;314 315 priv->dev = dev;316 platform_set_drvdata(pdev, priv);317 318 base = devm_platform_ioremap_resource(pdev, 0);319 if (IS_ERR(base))320 return PTR_ERR(base);321 322 priv->soc_id = (uintptr_t)of_device_get_match_data(&pdev->dev);323 324 priv->regmap = devm_regmap_init_mmio(dev, base,325 &phy_meson_g12a_usb2_regmap_conf);326 if (IS_ERR(priv->regmap))327 return PTR_ERR(priv->regmap);328 329 priv->clk = devm_clk_get(dev, "xtal");330 if (IS_ERR(priv->clk))331 return PTR_ERR(priv->clk);332 333 priv->reset = devm_reset_control_get(dev, "phy");334 if (IS_ERR(priv->reset))335 return PTR_ERR(priv->reset);336 337 ret = reset_control_deassert(priv->reset);338 if (ret)339 return ret;340 341 phy = devm_phy_create(dev, NULL, &phy_meson_g12a_usb2_ops);342 if (IS_ERR(phy)) {343 ret = PTR_ERR(phy);344 if (ret != -EPROBE_DEFER)345 dev_err(dev, "failed to create PHY\n");346 347 return ret;348 }349 350 phy_set_bus_width(phy, 8);351 phy_set_drvdata(phy, priv);352 353 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);354 355 return PTR_ERR_OR_ZERO(phy_provider);356}357 358static const struct of_device_id phy_meson_g12a_usb2_of_match[] = {359 {360 .compatible = "amlogic,g12a-usb2-phy",361 .data = (void *)MESON_SOC_G12A,362 },363 {364 .compatible = "amlogic,a1-usb2-phy",365 .data = (void *)MESON_SOC_A1,366 },367 { /* Sentinel */ }368};369MODULE_DEVICE_TABLE(of, phy_meson_g12a_usb2_of_match);370 371static struct platform_driver phy_meson_g12a_usb2_driver = {372 .probe = phy_meson_g12a_usb2_probe,373 .driver = {374 .name = "phy-meson-g12a-usb2",375 .of_match_table = phy_meson_g12a_usb2_of_match,376 },377};378module_platform_driver(phy_meson_g12a_usb2_driver);379 380MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");381MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");382MODULE_DESCRIPTION("Meson G12A USB2 PHY driver");383MODULE_LICENSE("GPL v2");384