1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2020, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/delay.h> 8 #include <linux/err.h> 9 #include <linux/io.h> 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_device.h> 14 #include <linux/phy/phy.h> 15 #include <linux/platform_device.h> 16 #include <linux/regmap.h> 17 #include <linux/regulator/consumer.h> 18 #include <linux/reset.h> 19 #include <linux/slab.h> 20 21 #define USB2_PHY_USB_PHY_UTMI_CTRL0 (0x3c) 22 #define SLEEPM BIT(0) 23 #define OPMODE_MASK GENMASK(4, 3) 24 #define OPMODE_NORMAL (0x00) 25 #define OPMODE_NONDRIVING BIT(3) 26 #define TERMSEL BIT(5) 27 28 #define USB2_PHY_USB_PHY_UTMI_CTRL1 (0x40) 29 #define XCVRSEL BIT(0) 30 31 #define USB2_PHY_USB_PHY_UTMI_CTRL5 (0x50) 32 #define POR BIT(1) 33 34 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0 (0x54) 35 #define SIDDQ BIT(2) 36 #define RETENABLEN BIT(3) 37 #define FSEL_MASK GENMASK(6, 4) 38 #define FSEL_DEFAULT (0x3 << 4) 39 40 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1 (0x58) 41 #define VBUSVLDEXTSEL0 BIT(4) 42 #define PLLBTUNE BIT(5) 43 44 #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2 (0x5c) 45 #define VREGBYPASS BIT(0) 46 47 #define USB2_PHY_USB_PHY_HS_PHY_CTRL1 (0x60) 48 #define VBUSVLDEXT0 BIT(0) 49 50 #define USB2_PHY_USB_PHY_HS_PHY_CTRL2 (0x64) 51 #define USB2_AUTO_RESUME BIT(0) 52 #define USB2_SUSPEND_N BIT(2) 53 #define USB2_SUSPEND_N_SEL BIT(3) 54 55 #define USB2_PHY_USB_PHY_CFG0 (0x94) 56 #define UTMI_PHY_DATAPATH_CTRL_OVERRIDE_EN BIT(0) 57 #define UTMI_PHY_CMN_CTRL_OVERRIDE_EN BIT(1) 58 59 #define USB2_PHY_USB_PHY_REFCLK_CTRL (0xa0) 60 #define REFCLK_SEL_MASK GENMASK(1, 0) 61 #define REFCLK_SEL_DEFAULT (0x2 << 0) 62 63 static const char * const qcom_snps_hsphy_vreg_names[] = { 64 "vdda-pll", "vdda33", "vdda18", 65 }; 66 67 #define SNPS_HS_NUM_VREGS ARRAY_SIZE(qcom_snps_hsphy_vreg_names) 68 69 /** 70 * struct qcom_snps_hsphy - snps hs phy attributes 71 * 72 * @phy: generic phy 73 * @base: iomapped memory space for snps hs phy 74 * 75 * @cfg_ahb_clk: AHB2PHY interface clock 76 * @ref_clk: phy reference clock 77 * @iface_clk: phy interface clock 78 * @phy_reset: phy reset control 79 * @vregs: regulator supplies bulk data 80 * @phy_initialized: if PHY has been initialized correctly 81 * @mode: contains the current mode the PHY is in 82 */ 83 struct qcom_snps_hsphy { 84 struct phy *phy; 85 void __iomem *base; 86 87 struct clk *cfg_ahb_clk; 88 struct clk *ref_clk; 89 struct reset_control *phy_reset; 90 struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS]; 91 92 bool phy_initialized; 93 enum phy_mode mode; 94 }; 95 96 static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset, 97 u32 mask, u32 val) 98 { 99 u32 reg; 100 101 reg = readl_relaxed(base + offset); 102 reg &= ~mask; 103 reg |= val & mask; 104 writel_relaxed(reg, base + offset); 105 106 /* Ensure above write is completed */ 107 readl_relaxed(base + offset); 108 } 109 110 static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy) 111 { 112 dev_dbg(&hsphy->phy->dev, "Suspend QCOM SNPS PHY\n"); 113 114 if (hsphy->mode == PHY_MODE_USB_HOST) { 115 /* Enable auto-resume to meet remote wakeup timing */ 116 qcom_snps_hsphy_write_mask(hsphy->base, 117 USB2_PHY_USB_PHY_HS_PHY_CTRL2, 118 USB2_AUTO_RESUME, 119 USB2_AUTO_RESUME); 120 usleep_range(500, 1000); 121 qcom_snps_hsphy_write_mask(hsphy->base, 122 USB2_PHY_USB_PHY_HS_PHY_CTRL2, 123 0, USB2_AUTO_RESUME); 124 } 125 126 clk_disable_unprepare(hsphy->cfg_ahb_clk); 127 return 0; 128 } 129 130 static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy) 131 { 132 int ret; 133 134 dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n"); 135 136 ret = clk_prepare_enable(hsphy->cfg_ahb_clk); 137 if (ret) { 138 dev_err(&hsphy->phy->dev, "failed to enable cfg ahb clock\n"); 139 return ret; 140 } 141 142 return 0; 143 } 144 145 static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev) 146 { 147 struct qcom_snps_hsphy *hsphy = dev_get_drvdata(dev); 148 149 if (!hsphy->phy_initialized) 150 return 0; 151 152 qcom_snps_hsphy_suspend(hsphy); 153 return 0; 154 } 155 156 static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev) 157 { 158 struct qcom_snps_hsphy *hsphy = dev_get_drvdata(dev); 159 160 if (!hsphy->phy_initialized) 161 return 0; 162 163 qcom_snps_hsphy_resume(hsphy); 164 return 0; 165 } 166 167 static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode, 168 int submode) 169 { 170 struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy); 171 172 hsphy->mode = mode; 173 return 0; 174 } 175 176 static int qcom_snps_hsphy_init(struct phy *phy) 177 { 178 struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy); 179 int ret; 180 181 dev_vdbg(&phy->dev, "%s(): Initializing SNPS HS phy\n", __func__); 182 183 ret = regulator_bulk_enable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs); 184 if (ret) 185 return ret; 186 187 ret = clk_prepare_enable(hsphy->cfg_ahb_clk); 188 if (ret) { 189 dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret); 190 goto poweroff_phy; 191 } 192 193 ret = reset_control_assert(hsphy->phy_reset); 194 if (ret) { 195 dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret); 196 goto disable_ahb_clk; 197 } 198 199 usleep_range(100, 150); 200 201 ret = reset_control_deassert(hsphy->phy_reset); 202 if (ret) { 203 dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret); 204 goto disable_ahb_clk; 205 } 206 207 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0, 208 UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 209 UTMI_PHY_CMN_CTRL_OVERRIDE_EN); 210 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5, 211 POR, POR); 212 qcom_snps_hsphy_write_mask(hsphy->base, 213 USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0, 214 FSEL_MASK, 0); 215 qcom_snps_hsphy_write_mask(hsphy->base, 216 USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1, 217 PLLBTUNE, PLLBTUNE); 218 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_REFCLK_CTRL, 219 REFCLK_SEL_DEFAULT, REFCLK_SEL_MASK); 220 qcom_snps_hsphy_write_mask(hsphy->base, 221 USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1, 222 VBUSVLDEXTSEL0, VBUSVLDEXTSEL0); 223 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1, 224 VBUSVLDEXT0, VBUSVLDEXT0); 225 226 qcom_snps_hsphy_write_mask(hsphy->base, 227 USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2, 228 VREGBYPASS, VREGBYPASS); 229 230 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2, 231 USB2_SUSPEND_N_SEL | USB2_SUSPEND_N, 232 USB2_SUSPEND_N_SEL | USB2_SUSPEND_N); 233 234 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL0, 235 SLEEPM, SLEEPM); 236 237 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0, 238 SIDDQ, 0); 239 240 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5, 241 POR, 0); 242 243 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2, 244 USB2_SUSPEND_N_SEL, 0); 245 246 qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0, 247 UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 0); 248 249 hsphy->phy_initialized = true; 250 251 return 0; 252 253 disable_ahb_clk: 254 clk_disable_unprepare(hsphy->cfg_ahb_clk); 255 poweroff_phy: 256 regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs); 257 258 return ret; 259 } 260 261 static int qcom_snps_hsphy_exit(struct phy *phy) 262 { 263 struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy); 264 265 reset_control_assert(hsphy->phy_reset); 266 clk_disable_unprepare(hsphy->cfg_ahb_clk); 267 regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs); 268 hsphy->phy_initialized = false; 269 270 return 0; 271 } 272 273 static const struct phy_ops qcom_snps_hsphy_gen_ops = { 274 .init = qcom_snps_hsphy_init, 275 .exit = qcom_snps_hsphy_exit, 276 .set_mode = qcom_snps_hsphy_set_mode, 277 .owner = THIS_MODULE, 278 }; 279 280 static const struct of_device_id qcom_snps_hsphy_of_match_table[] = { 281 { .compatible = "qcom,sm8150-usb-hs-phy", }, 282 { .compatible = "qcom,usb-snps-hs-5nm-phy", }, 283 { .compatible = "qcom,usb-snps-hs-7nm-phy", }, 284 { .compatible = "qcom,usb-snps-femto-v2-phy", }, 285 { } 286 }; 287 MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_of_match_table); 288 289 static const struct dev_pm_ops qcom_snps_hsphy_pm_ops = { 290 SET_RUNTIME_PM_OPS(qcom_snps_hsphy_runtime_suspend, 291 qcom_snps_hsphy_runtime_resume, NULL) 292 }; 293 294 static int qcom_snps_hsphy_probe(struct platform_device *pdev) 295 { 296 struct device *dev = &pdev->dev; 297 struct qcom_snps_hsphy *hsphy; 298 struct phy_provider *phy_provider; 299 struct phy *generic_phy; 300 int ret, i; 301 int num; 302 303 hsphy = devm_kzalloc(dev, sizeof(*hsphy), GFP_KERNEL); 304 if (!hsphy) 305 return -ENOMEM; 306 307 hsphy->base = devm_platform_ioremap_resource(pdev, 0); 308 if (IS_ERR(hsphy->base)) 309 return PTR_ERR(hsphy->base); 310 311 hsphy->ref_clk = devm_clk_get(dev, "ref"); 312 if (IS_ERR(hsphy->ref_clk)) { 313 ret = PTR_ERR(hsphy->ref_clk); 314 if (ret != -EPROBE_DEFER) 315 dev_err(dev, "failed to get ref clk, %d\n", ret); 316 return ret; 317 } 318 319 hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); 320 if (IS_ERR(hsphy->phy_reset)) { 321 dev_err(dev, "failed to get phy core reset\n"); 322 return PTR_ERR(hsphy->phy_reset); 323 } 324 325 num = ARRAY_SIZE(hsphy->vregs); 326 for (i = 0; i < num; i++) 327 hsphy->vregs[i].supply = qcom_snps_hsphy_vreg_names[i]; 328 329 ret = devm_regulator_bulk_get(dev, num, hsphy->vregs); 330 if (ret) { 331 if (ret != -EPROBE_DEFER) 332 dev_err(dev, "failed to get regulator supplies: %d\n", 333 ret); 334 return ret; 335 } 336 337 pm_runtime_set_active(dev); 338 pm_runtime_enable(dev); 339 /* 340 * Prevent runtime pm from being ON by default. Users can enable 341 * it using power/control in sysfs. 342 */ 343 pm_runtime_forbid(dev); 344 345 generic_phy = devm_phy_create(dev, NULL, &qcom_snps_hsphy_gen_ops); 346 if (IS_ERR(generic_phy)) { 347 ret = PTR_ERR(generic_phy); 348 dev_err(dev, "failed to create phy, %d\n", ret); 349 return ret; 350 } 351 hsphy->phy = generic_phy; 352 353 dev_set_drvdata(dev, hsphy); 354 phy_set_drvdata(generic_phy, hsphy); 355 356 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 357 if (!IS_ERR(phy_provider)) 358 dev_dbg(dev, "Registered Qcom-SNPS HS phy\n"); 359 else 360 pm_runtime_disable(dev); 361 362 return PTR_ERR_OR_ZERO(phy_provider); 363 } 364 365 static struct platform_driver qcom_snps_hsphy_driver = { 366 .probe = qcom_snps_hsphy_probe, 367 .driver = { 368 .name = "qcom-snps-hs-femto-v2-phy", 369 .pm = &qcom_snps_hsphy_pm_ops, 370 .of_match_table = qcom_snps_hsphy_of_match_table, 371 }, 372 }; 373 374 module_platform_driver(qcom_snps_hsphy_driver); 375 376 MODULE_DESCRIPTION("Qualcomm SNPS FEMTO USB HS PHY V2 driver"); 377 MODULE_LICENSE("GPL v2"); 378