1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Ingenic SoCs USB PHY driver 4 * Copyright (c) Paul Cercueil <paul@crapouillou.net> 5 * Copyright (c) 漆鹏振 (Qi Pengzhen) <aric.pzqi@ingenic.com> 6 * Copyright (c) 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com> 7 */ 8 9 #include <linux/bitfield.h> 10 #include <linux/clk.h> 11 #include <linux/delay.h> 12 #include <linux/io.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/phy/phy.h> 16 #include <linux/platform_device.h> 17 #include <linux/regulator/consumer.h> 18 19 /* OTGPHY register offsets */ 20 #define REG_USBPCR_OFFSET 0x00 21 #define REG_USBRDT_OFFSET 0x04 22 #define REG_USBVBFIL_OFFSET 0x08 23 #define REG_USBPCR1_OFFSET 0x0c 24 25 /* bits within the USBPCR register */ 26 #define USBPCR_USB_MODE BIT(31) 27 #define USBPCR_AVLD_REG BIT(30) 28 #define USBPCR_COMMONONN BIT(25) 29 #define USBPCR_VBUSVLDEXT BIT(24) 30 #define USBPCR_VBUSVLDEXTSEL BIT(23) 31 #define USBPCR_POR BIT(22) 32 #define USBPCR_SIDDQ BIT(21) 33 #define USBPCR_OTG_DISABLE BIT(20) 34 #define USBPCR_TXPREEMPHTUNE BIT(6) 35 36 #define USBPCR_IDPULLUP_MASK GENMASK(29, 28) 37 #define USBPCR_IDPULLUP_ALWAYS 0x2 38 #define USBPCR_IDPULLUP_SUSPEND 0x1 39 #define USBPCR_IDPULLUP_OTG 0x0 40 41 #define USBPCR_COMPDISTUNE_MASK GENMASK(19, 17) 42 #define USBPCR_COMPDISTUNE_DFT 0x4 43 44 #define USBPCR_OTGTUNE_MASK GENMASK(16, 14) 45 #define USBPCR_OTGTUNE_DFT 0x4 46 47 #define USBPCR_SQRXTUNE_MASK GENMASK(13, 11) 48 #define USBPCR_SQRXTUNE_DCR_20PCT 0x7 49 #define USBPCR_SQRXTUNE_DFT 0x3 50 51 #define USBPCR_TXFSLSTUNE_MASK GENMASK(10, 7) 52 #define USBPCR_TXFSLSTUNE_DCR_50PPT 0xf 53 #define USBPCR_TXFSLSTUNE_DCR_25PPT 0x7 54 #define USBPCR_TXFSLSTUNE_DFT 0x3 55 #define USBPCR_TXFSLSTUNE_INC_25PPT 0x1 56 #define USBPCR_TXFSLSTUNE_INC_50PPT 0x0 57 58 #define USBPCR_TXHSXVTUNE_MASK GENMASK(5, 4) 59 #define USBPCR_TXHSXVTUNE_DFT 0x3 60 #define USBPCR_TXHSXVTUNE_DCR_15MV 0x1 61 62 #define USBPCR_TXRISETUNE_MASK GENMASK(5, 4) 63 #define USBPCR_TXRISETUNE_DFT 0x3 64 65 #define USBPCR_TXVREFTUNE_MASK GENMASK(3, 0) 66 #define USBPCR_TXVREFTUNE_INC_75PPT 0xb 67 #define USBPCR_TXVREFTUNE_INC_25PPT 0x7 68 #define USBPCR_TXVREFTUNE_DFT 0x5 69 70 /* bits within the USBRDTR register */ 71 #define USBRDT_UTMI_RST BIT(27) 72 #define USBRDT_HB_MASK BIT(26) 73 #define USBRDT_VBFIL_LD_EN BIT(25) 74 #define USBRDT_IDDIG_EN BIT(24) 75 #define USBRDT_IDDIG_REG BIT(23) 76 #define USBRDT_VBFIL_EN BIT(2) 77 78 /* bits within the USBPCR1 register */ 79 #define USBPCR1_BVLD_REG BIT(31) 80 #define USBPCR1_DPPD BIT(29) 81 #define USBPCR1_DMPD BIT(28) 82 #define USBPCR1_USB_SEL BIT(28) 83 #define USBPCR1_PORT_RST BIT(21) 84 #define USBPCR1_WORD_IF_16BIT BIT(19) 85 86 struct ingenic_soc_info { 87 void (*usb_phy_init)(struct phy *phy); 88 }; 89 90 struct ingenic_usb_phy { 91 const struct ingenic_soc_info *soc_info; 92 93 struct phy *phy; 94 void __iomem *base; 95 struct clk *clk; 96 struct regulator *vcc_supply; 97 }; 98 99 static int ingenic_usb_phy_init(struct phy *phy) 100 { 101 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 102 int err; 103 u32 reg; 104 105 err = clk_prepare_enable(priv->clk); 106 if (err) { 107 dev_err(&phy->dev, "Unable to start clock: %d\n", err); 108 return err; 109 } 110 111 priv->soc_info->usb_phy_init(phy); 112 113 /* Wait for PHY to reset */ 114 usleep_range(30, 300); 115 reg = readl(priv->base + REG_USBPCR_OFFSET); 116 writel(reg & ~USBPCR_POR, priv->base + REG_USBPCR_OFFSET); 117 usleep_range(300, 1000); 118 119 return 0; 120 } 121 122 static int ingenic_usb_phy_exit(struct phy *phy) 123 { 124 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 125 126 clk_disable_unprepare(priv->clk); 127 regulator_disable(priv->vcc_supply); 128 129 return 0; 130 } 131 132 static int ingenic_usb_phy_power_on(struct phy *phy) 133 { 134 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 135 int err; 136 137 err = regulator_enable(priv->vcc_supply); 138 if (err) { 139 dev_err(&phy->dev, "Unable to enable VCC: %d\n", err); 140 return err; 141 } 142 143 return 0; 144 } 145 146 static int ingenic_usb_phy_power_off(struct phy *phy) 147 { 148 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 149 150 regulator_disable(priv->vcc_supply); 151 152 return 0; 153 } 154 155 static int ingenic_usb_phy_set_mode(struct phy *phy, 156 enum phy_mode mode, int submode) 157 { 158 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 159 u32 reg; 160 161 switch (mode) { 162 case PHY_MODE_USB_HOST: 163 reg = readl(priv->base + REG_USBPCR_OFFSET); 164 u32p_replace_bits(®, 1, USBPCR_USB_MODE); 165 u32p_replace_bits(®, 0, USBPCR_VBUSVLDEXT); 166 u32p_replace_bits(®, 0, USBPCR_VBUSVLDEXTSEL); 167 u32p_replace_bits(®, 0, USBPCR_OTG_DISABLE); 168 writel(reg, priv->base + REG_USBPCR_OFFSET); 169 170 break; 171 case PHY_MODE_USB_DEVICE: 172 reg = readl(priv->base + REG_USBPCR_OFFSET); 173 u32p_replace_bits(®, 0, USBPCR_USB_MODE); 174 u32p_replace_bits(®, 1, USBPCR_VBUSVLDEXT); 175 u32p_replace_bits(®, 1, USBPCR_VBUSVLDEXTSEL); 176 u32p_replace_bits(®, 1, USBPCR_OTG_DISABLE); 177 writel(reg, priv->base + REG_USBPCR_OFFSET); 178 179 break; 180 case PHY_MODE_USB_OTG: 181 reg = readl(priv->base + REG_USBPCR_OFFSET); 182 u32p_replace_bits(®, 1, USBPCR_USB_MODE); 183 u32p_replace_bits(®, 1, USBPCR_VBUSVLDEXT); 184 u32p_replace_bits(®, 1, USBPCR_VBUSVLDEXTSEL); 185 u32p_replace_bits(®, 0, USBPCR_OTG_DISABLE); 186 writel(reg, priv->base + REG_USBPCR_OFFSET); 187 188 break; 189 default: 190 return -EINVAL; 191 } 192 193 return 0; 194 } 195 196 static const struct phy_ops ingenic_usb_phy_ops = { 197 .init = ingenic_usb_phy_init, 198 .exit = ingenic_usb_phy_exit, 199 .power_on = ingenic_usb_phy_power_on, 200 .power_off = ingenic_usb_phy_power_off, 201 .set_mode = ingenic_usb_phy_set_mode, 202 .owner = THIS_MODULE, 203 }; 204 205 static void jz4770_usb_phy_init(struct phy *phy) 206 { 207 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 208 u32 reg; 209 210 reg = USBPCR_AVLD_REG | USBPCR_COMMONONN | USBPCR_POR | 211 FIELD_PREP(USBPCR_IDPULLUP_MASK, USBPCR_IDPULLUP_ALWAYS) | 212 FIELD_PREP(USBPCR_COMPDISTUNE_MASK, USBPCR_COMPDISTUNE_DFT) | 213 FIELD_PREP(USBPCR_OTGTUNE_MASK, USBPCR_OTGTUNE_DFT) | 214 FIELD_PREP(USBPCR_SQRXTUNE_MASK, USBPCR_SQRXTUNE_DFT) | 215 FIELD_PREP(USBPCR_TXFSLSTUNE_MASK, USBPCR_TXFSLSTUNE_DFT) | 216 FIELD_PREP(USBPCR_TXRISETUNE_MASK, USBPCR_TXRISETUNE_DFT) | 217 FIELD_PREP(USBPCR_TXVREFTUNE_MASK, USBPCR_TXVREFTUNE_DFT); 218 writel(reg, priv->base + REG_USBPCR_OFFSET); 219 } 220 221 static void jz4775_usb_phy_init(struct phy *phy) 222 { 223 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 224 u32 reg; 225 226 reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_USB_SEL | 227 USBPCR1_WORD_IF_16BIT; 228 writel(reg, priv->base + REG_USBPCR1_OFFSET); 229 230 reg = USBPCR_COMMONONN | USBPCR_POR | 231 FIELD_PREP(USBPCR_TXVREFTUNE_MASK, USBPCR_TXVREFTUNE_INC_75PPT); 232 writel(reg, priv->base + REG_USBPCR_OFFSET); 233 } 234 235 static void jz4780_usb_phy_init(struct phy *phy) 236 { 237 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 238 u32 reg; 239 240 reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_USB_SEL | 241 USBPCR1_WORD_IF_16BIT; 242 writel(reg, priv->base + REG_USBPCR1_OFFSET); 243 244 reg = USBPCR_TXPREEMPHTUNE | USBPCR_COMMONONN | USBPCR_POR; 245 writel(reg, priv->base + REG_USBPCR_OFFSET); 246 } 247 248 static void x1000_usb_phy_init(struct phy *phy) 249 { 250 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 251 u32 reg; 252 253 reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_WORD_IF_16BIT; 254 writel(reg, priv->base + REG_USBPCR1_OFFSET); 255 256 reg = USBPCR_TXPREEMPHTUNE | USBPCR_COMMONONN | USBPCR_POR | 257 FIELD_PREP(USBPCR_SQRXTUNE_MASK, USBPCR_SQRXTUNE_DCR_20PCT) | 258 FIELD_PREP(USBPCR_TXHSXVTUNE_MASK, USBPCR_TXHSXVTUNE_DCR_15MV) | 259 FIELD_PREP(USBPCR_TXVREFTUNE_MASK, USBPCR_TXVREFTUNE_INC_25PPT); 260 writel(reg, priv->base + REG_USBPCR_OFFSET); 261 } 262 263 static void x1830_usb_phy_init(struct phy *phy) 264 { 265 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 266 u32 reg; 267 268 /* rdt */ 269 writel(USBRDT_VBFIL_EN | USBRDT_UTMI_RST, priv->base + REG_USBRDT_OFFSET); 270 271 reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_WORD_IF_16BIT | 272 USBPCR1_DMPD | USBPCR1_DPPD; 273 writel(reg, priv->base + REG_USBPCR1_OFFSET); 274 275 reg = USBPCR_VBUSVLDEXT | USBPCR_TXPREEMPHTUNE | USBPCR_COMMONONN | USBPCR_POR | 276 FIELD_PREP(USBPCR_IDPULLUP_MASK, USBPCR_IDPULLUP_OTG); 277 writel(reg, priv->base + REG_USBPCR_OFFSET); 278 } 279 280 static void x2000_usb_phy_init(struct phy *phy) 281 { 282 struct ingenic_usb_phy *priv = phy_get_drvdata(phy); 283 u32 reg; 284 285 reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_DPPD | USBPCR1_DMPD; 286 writel(reg & ~USBPCR1_PORT_RST, priv->base + REG_USBPCR1_OFFSET); 287 288 reg = USBPCR_POR | FIELD_PREP(USBPCR_IDPULLUP_MASK, USBPCR_IDPULLUP_OTG); 289 writel(reg, priv->base + REG_USBPCR_OFFSET); 290 } 291 292 static const struct ingenic_soc_info jz4770_soc_info = { 293 .usb_phy_init = jz4770_usb_phy_init, 294 }; 295 296 static const struct ingenic_soc_info jz4775_soc_info = { 297 .usb_phy_init = jz4775_usb_phy_init, 298 }; 299 300 static const struct ingenic_soc_info jz4780_soc_info = { 301 .usb_phy_init = jz4780_usb_phy_init, 302 }; 303 304 static const struct ingenic_soc_info x1000_soc_info = { 305 .usb_phy_init = x1000_usb_phy_init, 306 }; 307 308 static const struct ingenic_soc_info x1830_soc_info = { 309 .usb_phy_init = x1830_usb_phy_init, 310 }; 311 312 static const struct ingenic_soc_info x2000_soc_info = { 313 .usb_phy_init = x2000_usb_phy_init, 314 }; 315 316 static int ingenic_usb_phy_probe(struct platform_device *pdev) 317 { 318 struct ingenic_usb_phy *priv; 319 struct phy_provider *provider; 320 struct device *dev = &pdev->dev; 321 int err; 322 323 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 324 if (!priv) 325 return -ENOMEM; 326 327 priv->soc_info = device_get_match_data(dev); 328 if (!priv->soc_info) { 329 dev_err(dev, "Error: No device match found\n"); 330 return -ENODEV; 331 } 332 333 priv->base = devm_platform_ioremap_resource(pdev, 0); 334 if (IS_ERR(priv->base)) { 335 dev_err(dev, "Failed to map registers\n"); 336 return PTR_ERR(priv->base); 337 } 338 339 priv->clk = devm_clk_get(dev, NULL); 340 if (IS_ERR(priv->clk)) { 341 err = PTR_ERR(priv->clk); 342 if (err != -EPROBE_DEFER) 343 dev_err(dev, "Failed to get clock\n"); 344 return err; 345 } 346 347 priv->vcc_supply = devm_regulator_get(dev, "vcc"); 348 if (IS_ERR(priv->vcc_supply)) { 349 err = PTR_ERR(priv->vcc_supply); 350 if (err != -EPROBE_DEFER) 351 dev_err(dev, "Failed to get regulator\n"); 352 return err; 353 } 354 355 priv->phy = devm_phy_create(dev, NULL, &ingenic_usb_phy_ops); 356 if (IS_ERR(priv->phy)) 357 return PTR_ERR(priv->phy); 358 359 phy_set_drvdata(priv->phy, priv); 360 361 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 362 363 return PTR_ERR_OR_ZERO(provider); 364 } 365 366 static const struct of_device_id ingenic_usb_phy_of_matches[] = { 367 { .compatible = "ingenic,jz4770-phy", .data = &jz4770_soc_info }, 368 { .compatible = "ingenic,jz4775-phy", .data = &jz4775_soc_info }, 369 { .compatible = "ingenic,jz4780-phy", .data = &jz4780_soc_info }, 370 { .compatible = "ingenic,x1000-phy", .data = &x1000_soc_info }, 371 { .compatible = "ingenic,x1830-phy", .data = &x1830_soc_info }, 372 { .compatible = "ingenic,x2000-phy", .data = &x2000_soc_info }, 373 { /* sentinel */ } 374 }; 375 MODULE_DEVICE_TABLE(of, ingenic_usb_phy_of_matches); 376 377 static struct platform_driver ingenic_usb_phy_driver = { 378 .probe = ingenic_usb_phy_probe, 379 .driver = { 380 .name = "ingenic-usb-phy", 381 .of_match_table = ingenic_usb_phy_of_matches, 382 }, 383 }; 384 module_platform_driver(ingenic_usb_phy_driver); 385 386 MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>"); 387 MODULE_AUTHOR("漆鹏振 (Qi Pengzhen) <aric.pzqi@ingenic.com>"); 388 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); 389 MODULE_DESCRIPTION("Ingenic SoCs USB PHY driver"); 390 MODULE_LICENSE("GPL"); 391