1 /* 2 * Rockchip usb PHY driver 3 * 4 * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com> 5 * Copyright (C) 2014 ROCKCHIP, Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #include <linux/clk.h> 18 #include <linux/clk-provider.h> 19 #include <linux/io.h> 20 #include <linux/kernel.h> 21 #include <linux/module.h> 22 #include <linux/mutex.h> 23 #include <linux/of.h> 24 #include <linux/of_address.h> 25 #include <linux/of_platform.h> 26 #include <linux/phy/phy.h> 27 #include <linux/platform_device.h> 28 #include <linux/regulator/consumer.h> 29 #include <linux/reset.h> 30 #include <linux/regmap.h> 31 #include <linux/mfd/syscon.h> 32 #include <linux/delay.h> 33 34 static int enable_usb_uart; 35 36 #define HIWORD_UPDATE(val, mask) \ 37 ((val) | (mask) << 16) 38 39 #define UOC_CON0_SIDDQ BIT(13) 40 41 struct rockchip_usb_phys { 42 int reg; 43 const char *pll_name; 44 }; 45 46 struct rockchip_usb_phy_base; 47 struct rockchip_usb_phy_pdata { 48 struct rockchip_usb_phys *phys; 49 int (*init_usb_uart)(struct regmap *grf); 50 int usb_uart_phy; 51 }; 52 53 struct rockchip_usb_phy_base { 54 struct device *dev; 55 struct regmap *reg_base; 56 const struct rockchip_usb_phy_pdata *pdata; 57 }; 58 59 struct rockchip_usb_phy { 60 struct rockchip_usb_phy_base *base; 61 struct device_node *np; 62 unsigned int reg_offset; 63 struct clk *clk; 64 struct clk *clk480m; 65 struct clk_hw clk480m_hw; 66 struct phy *phy; 67 bool uart_enabled; 68 struct reset_control *reset; 69 struct regulator *vbus; 70 }; 71 72 static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, 73 bool siddq) 74 { 75 u32 val = HIWORD_UPDATE(siddq ? UOC_CON0_SIDDQ : 0, UOC_CON0_SIDDQ); 76 77 return regmap_write(phy->base->reg_base, phy->reg_offset, val); 78 } 79 80 static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw, 81 unsigned long parent_rate) 82 { 83 return 480000000; 84 } 85 86 static void rockchip_usb_phy480m_disable(struct clk_hw *hw) 87 { 88 struct rockchip_usb_phy *phy = container_of(hw, 89 struct rockchip_usb_phy, 90 clk480m_hw); 91 92 if (phy->vbus) 93 regulator_disable(phy->vbus); 94 95 /* Power down usb phy analog blocks by set siddq 1 */ 96 rockchip_usb_phy_power(phy, 1); 97 } 98 99 static int rockchip_usb_phy480m_enable(struct clk_hw *hw) 100 { 101 struct rockchip_usb_phy *phy = container_of(hw, 102 struct rockchip_usb_phy, 103 clk480m_hw); 104 105 /* Power up usb phy analog blocks by set siddq 0 */ 106 return rockchip_usb_phy_power(phy, 0); 107 } 108 109 static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw) 110 { 111 struct rockchip_usb_phy *phy = container_of(hw, 112 struct rockchip_usb_phy, 113 clk480m_hw); 114 int ret; 115 u32 val; 116 117 ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val); 118 if (ret < 0) 119 return ret; 120 121 return (val & UOC_CON0_SIDDQ) ? 0 : 1; 122 } 123 124 static const struct clk_ops rockchip_usb_phy480m_ops = { 125 .enable = rockchip_usb_phy480m_enable, 126 .disable = rockchip_usb_phy480m_disable, 127 .is_enabled = rockchip_usb_phy480m_is_enabled, 128 .recalc_rate = rockchip_usb_phy480m_recalc_rate, 129 }; 130 131 static int rockchip_usb_phy_power_off(struct phy *_phy) 132 { 133 struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); 134 135 if (phy->uart_enabled) 136 return -EBUSY; 137 138 clk_disable_unprepare(phy->clk480m); 139 140 return 0; 141 } 142 143 static int rockchip_usb_phy_power_on(struct phy *_phy) 144 { 145 struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); 146 147 if (phy->uart_enabled) 148 return -EBUSY; 149 150 if (phy->vbus) { 151 int ret; 152 153 ret = regulator_enable(phy->vbus); 154 if (ret) 155 return ret; 156 } 157 158 return clk_prepare_enable(phy->clk480m); 159 } 160 161 static int rockchip_usb_phy_reset(struct phy *_phy) 162 { 163 struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); 164 165 if (phy->reset) { 166 reset_control_assert(phy->reset); 167 udelay(10); 168 reset_control_deassert(phy->reset); 169 } 170 171 return 0; 172 } 173 174 static const struct phy_ops ops = { 175 .power_on = rockchip_usb_phy_power_on, 176 .power_off = rockchip_usb_phy_power_off, 177 .reset = rockchip_usb_phy_reset, 178 .owner = THIS_MODULE, 179 }; 180 181 static void rockchip_usb_phy_action(void *data) 182 { 183 struct rockchip_usb_phy *rk_phy = data; 184 185 if (!rk_phy->uart_enabled) { 186 of_clk_del_provider(rk_phy->np); 187 clk_unregister(rk_phy->clk480m); 188 } 189 190 if (rk_phy->clk) 191 clk_put(rk_phy->clk); 192 } 193 194 static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base, 195 struct device_node *child) 196 { 197 struct rockchip_usb_phy *rk_phy; 198 unsigned int reg_offset; 199 const char *clk_name; 200 struct clk_init_data init; 201 int err, i; 202 203 rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL); 204 if (!rk_phy) 205 return -ENOMEM; 206 207 rk_phy->base = base; 208 rk_phy->np = child; 209 210 if (of_property_read_u32(child, "reg", ®_offset)) { 211 dev_err(base->dev, "missing reg property in node %s\n", 212 child->name); 213 return -EINVAL; 214 } 215 216 rk_phy->reset = of_reset_control_get(child, "phy-reset"); 217 if (IS_ERR(rk_phy->reset)) 218 rk_phy->reset = NULL; 219 220 rk_phy->reg_offset = reg_offset; 221 222 rk_phy->clk = of_clk_get_by_name(child, "phyclk"); 223 if (IS_ERR(rk_phy->clk)) 224 rk_phy->clk = NULL; 225 226 i = 0; 227 init.name = NULL; 228 while (base->pdata->phys[i].reg) { 229 if (base->pdata->phys[i].reg == reg_offset) { 230 init.name = base->pdata->phys[i].pll_name; 231 break; 232 } 233 i++; 234 } 235 236 if (!init.name) { 237 dev_err(base->dev, "phy data not found\n"); 238 return -EINVAL; 239 } 240 241 if (enable_usb_uart && base->pdata->usb_uart_phy == i) { 242 dev_dbg(base->dev, "phy%d used as uart output\n", i); 243 rk_phy->uart_enabled = true; 244 } else { 245 if (rk_phy->clk) { 246 clk_name = __clk_get_name(rk_phy->clk); 247 init.flags = 0; 248 init.parent_names = &clk_name; 249 init.num_parents = 1; 250 } else { 251 init.flags = 0; 252 init.parent_names = NULL; 253 init.num_parents = 0; 254 } 255 256 init.ops = &rockchip_usb_phy480m_ops; 257 rk_phy->clk480m_hw.init = &init; 258 259 rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw); 260 if (IS_ERR(rk_phy->clk480m)) { 261 err = PTR_ERR(rk_phy->clk480m); 262 goto err_clk; 263 } 264 265 err = of_clk_add_provider(child, of_clk_src_simple_get, 266 rk_phy->clk480m); 267 if (err < 0) 268 goto err_clk_prov; 269 } 270 271 err = devm_add_action_or_reset(base->dev, rockchip_usb_phy_action, 272 rk_phy); 273 if (err) 274 return err; 275 276 rk_phy->phy = devm_phy_create(base->dev, child, &ops); 277 if (IS_ERR(rk_phy->phy)) { 278 dev_err(base->dev, "failed to create PHY\n"); 279 return PTR_ERR(rk_phy->phy); 280 } 281 phy_set_drvdata(rk_phy->phy, rk_phy); 282 283 rk_phy->vbus = devm_regulator_get_optional(&rk_phy->phy->dev, "vbus"); 284 if (IS_ERR(rk_phy->vbus)) { 285 if (PTR_ERR(rk_phy->vbus) == -EPROBE_DEFER) 286 return PTR_ERR(rk_phy->vbus); 287 rk_phy->vbus = NULL; 288 } 289 290 /* 291 * When acting as uart-pipe, just keep clock on otherwise 292 * only power up usb phy when it use, so disable it when init 293 */ 294 if (rk_phy->uart_enabled) 295 return clk_prepare_enable(rk_phy->clk); 296 else 297 return rockchip_usb_phy_power(rk_phy, 1); 298 299 err_clk_prov: 300 if (!rk_phy->uart_enabled) 301 clk_unregister(rk_phy->clk480m); 302 err_clk: 303 if (rk_phy->clk) 304 clk_put(rk_phy->clk); 305 return err; 306 } 307 308 static const struct rockchip_usb_phy_pdata rk3066a_pdata = { 309 .phys = (struct rockchip_usb_phys[]){ 310 { .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" }, 311 { .reg = 0x188, .pll_name = "sclk_otgphy1_480m" }, 312 { /* sentinel */ } 313 }, 314 }; 315 316 static const struct rockchip_usb_phy_pdata rk3188_pdata = { 317 .phys = (struct rockchip_usb_phys[]){ 318 { .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" }, 319 { .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" }, 320 { /* sentinel */ } 321 }, 322 }; 323 324 #define RK3288_UOC0_CON0 0x320 325 #define RK3288_UOC0_CON0_COMMON_ON_N BIT(0) 326 #define RK3288_UOC0_CON0_DISABLE BIT(4) 327 328 #define RK3288_UOC0_CON2 0x328 329 #define RK3288_UOC0_CON2_SOFT_CON_SEL BIT(2) 330 331 #define RK3288_UOC0_CON3 0x32c 332 #define RK3288_UOC0_CON3_UTMI_SUSPENDN BIT(0) 333 #define RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING (1 << 1) 334 #define RK3288_UOC0_CON3_UTMI_OPMODE_MASK (3 << 1) 335 #define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC (1 << 3) 336 #define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK (3 << 3) 337 #define RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED BIT(5) 338 #define RK3288_UOC0_CON3_BYPASSDMEN BIT(6) 339 #define RK3288_UOC0_CON3_BYPASSSEL BIT(7) 340 341 /* 342 * Enable the bypass of uart2 data through the otg usb phy. 343 * Original description in the TRM. 344 * 1. Disable the OTG block by setting OTGDISABLE0 to 1’b1. 345 * 2. Disable the pull-up resistance on the D+ line by setting 346 * OPMODE0[1:0] to 2’b01. 347 * 3. To ensure that the XO, Bias, and PLL blocks are powered down in Suspend 348 * mode, set COMMONONN to 1’b1. 349 * 4. Place the USB PHY in Suspend mode by setting SUSPENDM0 to 1’b0. 350 * 5. Set BYPASSSEL0 to 1’b1. 351 * 6. To transmit data, controls BYPASSDMEN0, and BYPASSDMDATA0. 352 * To receive data, monitor FSVPLUS0. 353 * 354 * The actual code in the vendor kernel does some things differently. 355 */ 356 static int __init rk3288_init_usb_uart(struct regmap *grf) 357 { 358 u32 val; 359 int ret; 360 361 /* 362 * COMMON_ON and DISABLE settings are described in the TRM, 363 * but were not present in the original code. 364 * Also disable the analog phy components to save power. 365 */ 366 val = HIWORD_UPDATE(RK3288_UOC0_CON0_COMMON_ON_N 367 | RK3288_UOC0_CON0_DISABLE 368 | UOC_CON0_SIDDQ, 369 RK3288_UOC0_CON0_COMMON_ON_N 370 | RK3288_UOC0_CON0_DISABLE 371 | UOC_CON0_SIDDQ); 372 ret = regmap_write(grf, RK3288_UOC0_CON0, val); 373 if (ret) 374 return ret; 375 376 val = HIWORD_UPDATE(RK3288_UOC0_CON2_SOFT_CON_SEL, 377 RK3288_UOC0_CON2_SOFT_CON_SEL); 378 ret = regmap_write(grf, RK3288_UOC0_CON2, val); 379 if (ret) 380 return ret; 381 382 val = HIWORD_UPDATE(RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING 383 | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC 384 | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED, 385 RK3288_UOC0_CON3_UTMI_SUSPENDN 386 | RK3288_UOC0_CON3_UTMI_OPMODE_MASK 387 | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK 388 | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED); 389 ret = regmap_write(grf, RK3288_UOC0_CON3, val); 390 if (ret) 391 return ret; 392 393 val = HIWORD_UPDATE(RK3288_UOC0_CON3_BYPASSSEL 394 | RK3288_UOC0_CON3_BYPASSDMEN, 395 RK3288_UOC0_CON3_BYPASSSEL 396 | RK3288_UOC0_CON3_BYPASSDMEN); 397 ret = regmap_write(grf, RK3288_UOC0_CON3, val); 398 if (ret) 399 return ret; 400 401 return 0; 402 } 403 404 static const struct rockchip_usb_phy_pdata rk3288_pdata = { 405 .phys = (struct rockchip_usb_phys[]){ 406 { .reg = 0x320, .pll_name = "sclk_otgphy0_480m" }, 407 { .reg = 0x334, .pll_name = "sclk_otgphy1_480m" }, 408 { .reg = 0x348, .pll_name = "sclk_otgphy2_480m" }, 409 { /* sentinel */ } 410 }, 411 .init_usb_uart = rk3288_init_usb_uart, 412 .usb_uart_phy = 0, 413 }; 414 415 static int rockchip_usb_phy_probe(struct platform_device *pdev) 416 { 417 struct device *dev = &pdev->dev; 418 struct rockchip_usb_phy_base *phy_base; 419 struct phy_provider *phy_provider; 420 const struct of_device_id *match; 421 struct device_node *child; 422 int err; 423 424 phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL); 425 if (!phy_base) 426 return -ENOMEM; 427 428 match = of_match_device(dev->driver->of_match_table, dev); 429 if (!match || !match->data) { 430 dev_err(dev, "missing phy data\n"); 431 return -EINVAL; 432 } 433 434 phy_base->pdata = match->data; 435 436 phy_base->dev = dev; 437 phy_base->reg_base = ERR_PTR(-ENODEV); 438 if (dev->parent && dev->parent->of_node) 439 phy_base->reg_base = syscon_node_to_regmap( 440 dev->parent->of_node); 441 if (IS_ERR(phy_base->reg_base)) 442 phy_base->reg_base = syscon_regmap_lookup_by_phandle( 443 dev->of_node, "rockchip,grf"); 444 if (IS_ERR(phy_base->reg_base)) { 445 dev_err(&pdev->dev, "Missing rockchip,grf property\n"); 446 return PTR_ERR(phy_base->reg_base); 447 } 448 449 for_each_available_child_of_node(dev->of_node, child) { 450 err = rockchip_usb_phy_init(phy_base, child); 451 if (err) { 452 of_node_put(child); 453 return err; 454 } 455 } 456 457 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 458 return PTR_ERR_OR_ZERO(phy_provider); 459 } 460 461 static const struct of_device_id rockchip_usb_phy_dt_ids[] = { 462 { .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata }, 463 { .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata }, 464 { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata }, 465 {} 466 }; 467 468 MODULE_DEVICE_TABLE(of, rockchip_usb_phy_dt_ids); 469 470 static struct platform_driver rockchip_usb_driver = { 471 .probe = rockchip_usb_phy_probe, 472 .driver = { 473 .name = "rockchip-usb-phy", 474 .of_match_table = rockchip_usb_phy_dt_ids, 475 }, 476 }; 477 478 module_platform_driver(rockchip_usb_driver); 479 480 #ifndef MODULE 481 static int __init rockchip_init_usb_uart(void) 482 { 483 const struct of_device_id *match; 484 const struct rockchip_usb_phy_pdata *data; 485 struct device_node *np; 486 struct regmap *grf; 487 int ret; 488 489 if (!enable_usb_uart) 490 return 0; 491 492 np = of_find_matching_node_and_match(NULL, rockchip_usb_phy_dt_ids, 493 &match); 494 if (!np) { 495 pr_err("%s: failed to find usbphy node\n", __func__); 496 return -ENOTSUPP; 497 } 498 499 pr_debug("%s: using settings for %s\n", __func__, match->compatible); 500 data = match->data; 501 502 if (!data->init_usb_uart) { 503 pr_err("%s: usb-uart not available on %s\n", 504 __func__, match->compatible); 505 return -ENOTSUPP; 506 } 507 508 grf = ERR_PTR(-ENODEV); 509 if (np->parent) 510 grf = syscon_node_to_regmap(np->parent); 511 if (IS_ERR(grf)) 512 grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 513 if (IS_ERR(grf)) { 514 pr_err("%s: Missing rockchip,grf property, %lu\n", 515 __func__, PTR_ERR(grf)); 516 return PTR_ERR(grf); 517 } 518 519 ret = data->init_usb_uart(grf); 520 if (ret) { 521 pr_err("%s: could not init usb_uart, %d\n", __func__, ret); 522 enable_usb_uart = 0; 523 return ret; 524 } 525 526 return 0; 527 } 528 early_initcall(rockchip_init_usb_uart); 529 530 static int __init rockchip_usb_uart(char *buf) 531 { 532 enable_usb_uart = true; 533 return 0; 534 } 535 early_param("rockchip.usb_uart", rockchip_usb_uart); 536 #endif 537 538 MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>"); 539 MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver"); 540 MODULE_LICENSE("GPL v2"); 541