1 /* 2 * Allwinner sun4i USB PHY driver 3 * 4 * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com> 5 * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com> 6 * Copyright (C) 2014 Roman Byshko <rbyshko@gmail.com> 7 * 8 * Modelled arch/arm/mach-sunxi/usb_phy.c to compatible with generic-phy. 9 * 10 * SPDX-License-Identifier: GPL-2.0+ 11 */ 12 13 #include <common.h> 14 #include <clk.h> 15 #include <dm.h> 16 #include <dm/device.h> 17 #include <generic-phy.h> 18 #include <phy-sun4i-usb.h> 19 #include <reset.h> 20 #include <asm/gpio.h> 21 #include <asm/io.h> 22 #include <asm/arch/clock.h> 23 #include <asm/arch/cpu.h> 24 25 #define REG_ISCR 0x00 26 #define REG_PHYCTL_A10 0x04 27 #define REG_PHYBIST 0x08 28 #define REG_PHYTUNE 0x0c 29 #define REG_PHYCTL_A33 0x10 30 #define REG_PHY_OTGCTL 0x20 31 #define REG_PMU_UNK1 0x10 32 33 /* Common Control Bits for Both PHYs */ 34 #define PHY_PLL_BW 0x03 35 #define PHY_RES45_CAL_EN 0x0c 36 37 /* Private Control Bits for Each PHY */ 38 #define PHY_TX_AMPLITUDE_TUNE 0x20 39 #define PHY_TX_SLEWRATE_TUNE 0x22 40 #define PHY_DISCON_TH_SEL 0x2a 41 #define PHY_SQUELCH_DETECT 0x3c 42 43 #define PHYCTL_DATA BIT(7) 44 #define OTGCTL_ROUTE_MUSB BIT(0) 45 46 #define PHY_TX_RATE BIT(4) 47 #define PHY_TX_MAGNITUDE BIT(2) 48 #define PHY_TX_AMPLITUDE_LEN 5 49 50 #define PHY_RES45_CAL_DATA BIT(0) 51 #define PHY_RES45_CAL_LEN 1 52 #define PHY_DISCON_TH_LEN 2 53 54 #define SUNXI_AHB_ICHR8_EN BIT(10) 55 #define SUNXI_AHB_INCR4_BURST_EN BIT(9) 56 #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) 57 #define SUNXI_ULPI_BYPASS_EN BIT(0) 58 59 /* A83T specific control bits for PHY0 */ 60 #define PHY_CTL_VBUSVLDEXT BIT(5) 61 #define PHY_CTL_SIDDQ BIT(3) 62 63 /* A83T specific control bits for PHY2 HSIC */ 64 #define SUNXI_EHCI_HS_FORCE BIT(20) 65 #define SUNXI_HSIC_CONNECT_INT BIT(16) 66 #define SUNXI_HSIC BIT(1) 67 68 #define MAX_PHYS 4 69 70 enum sun4i_usb_phy_type { 71 sun4i_a10_phy, 72 sun6i_a31_phy, 73 sun8i_a33_phy, 74 sun8i_a83t_phy, 75 sun8i_h3_phy, 76 sun8i_v3s_phy, 77 sun50i_a64_phy, 78 }; 79 80 struct sun4i_usb_phy_cfg { 81 int num_phys; 82 enum sun4i_usb_phy_type type; 83 u32 disc_thresh; 84 u8 phyctl_offset; 85 bool dedicated_clocks; 86 bool enable_pmu_unk1; 87 bool phy0_dual_route; 88 }; 89 90 struct sun4i_usb_phy_info { 91 const char *gpio_vbus; 92 const char *gpio_vbus_det; 93 const char *gpio_id_det; 94 } phy_info[] = { 95 { 96 .gpio_vbus = CONFIG_USB0_VBUS_PIN, 97 .gpio_vbus_det = CONFIG_USB0_VBUS_DET, 98 .gpio_id_det = CONFIG_USB0_ID_DET, 99 }, 100 { 101 .gpio_vbus = CONFIG_USB1_VBUS_PIN, 102 .gpio_vbus_det = NULL, 103 .gpio_id_det = NULL, 104 }, 105 { 106 .gpio_vbus = CONFIG_USB2_VBUS_PIN, 107 .gpio_vbus_det = NULL, 108 .gpio_id_det = NULL, 109 }, 110 { 111 .gpio_vbus = CONFIG_USB3_VBUS_PIN, 112 .gpio_vbus_det = NULL, 113 .gpio_id_det = NULL, 114 }, 115 }; 116 117 struct sun4i_usb_phy_plat { 118 void __iomem *pmu; 119 int power_on_count; 120 int gpio_vbus; 121 int gpio_vbus_det; 122 int gpio_id_det; 123 struct clk clocks; 124 struct reset_ctl resets; 125 int id; 126 }; 127 128 struct sun4i_usb_phy_data { 129 void __iomem *base; 130 const struct sun4i_usb_phy_cfg *cfg; 131 struct sun4i_usb_phy_plat *usb_phy; 132 }; 133 134 static int initial_usb_scan_delay = CONFIG_INITIAL_USB_SCAN_DELAY; 135 136 static void sun4i_usb_phy_write(struct phy *phy, u32 addr, u32 data, int len) 137 { 138 struct sun4i_usb_phy_data *phy_data = dev_get_priv(phy->dev); 139 struct sun4i_usb_phy_plat *usb_phy = &phy_data->usb_phy[phy->id]; 140 u32 temp, usbc_bit = BIT(usb_phy->id * 2); 141 void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset; 142 int i; 143 144 if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) { 145 /* SoCs newer than A33 need us to set phyctl to 0 explicitly */ 146 writel(0, phyctl); 147 } 148 149 for (i = 0; i < len; i++) { 150 temp = readl(phyctl); 151 152 /* clear the address portion */ 153 temp &= ~(0xff << 8); 154 155 /* set the address */ 156 temp |= ((addr + i) << 8); 157 writel(temp, phyctl); 158 159 /* set the data bit and clear usbc bit*/ 160 temp = readb(phyctl); 161 if (data & 0x1) 162 temp |= PHYCTL_DATA; 163 else 164 temp &= ~PHYCTL_DATA; 165 temp &= ~usbc_bit; 166 writeb(temp, phyctl); 167 168 /* pulse usbc_bit */ 169 temp = readb(phyctl); 170 temp |= usbc_bit; 171 writeb(temp, phyctl); 172 173 temp = readb(phyctl); 174 temp &= ~usbc_bit; 175 writeb(temp, phyctl); 176 177 data >>= 1; 178 } 179 } 180 181 static void sun4i_usb_phy_passby(struct phy *phy, bool enable) 182 { 183 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); 184 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; 185 u32 bits, reg_value; 186 187 if (!usb_phy->pmu) 188 return; 189 190 bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN | 191 SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN; 192 193 /* A83T USB2 is HSIC */ 194 if (data->cfg->type == sun8i_a83t_phy && usb_phy->id == 2) 195 bits |= SUNXI_EHCI_HS_FORCE | SUNXI_HSIC_CONNECT_INT | 196 SUNXI_HSIC; 197 198 reg_value = readl(usb_phy->pmu); 199 200 if (enable) 201 reg_value |= bits; 202 else 203 reg_value &= ~bits; 204 205 writel(reg_value, usb_phy->pmu); 206 } 207 208 static int sun4i_usb_phy_power_on(struct phy *phy) 209 { 210 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); 211 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; 212 213 if (initial_usb_scan_delay) { 214 mdelay(initial_usb_scan_delay); 215 initial_usb_scan_delay = 0; 216 } 217 218 usb_phy->power_on_count++; 219 if (usb_phy->power_on_count != 1) 220 return 0; 221 222 if (usb_phy->gpio_vbus >= 0) 223 gpio_set_value(usb_phy->gpio_vbus, SUNXI_GPIO_PULL_UP); 224 225 return 0; 226 } 227 228 static int sun4i_usb_phy_power_off(struct phy *phy) 229 { 230 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); 231 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; 232 233 usb_phy->power_on_count--; 234 if (usb_phy->power_on_count != 0) 235 return 0; 236 237 if (usb_phy->gpio_vbus >= 0) 238 gpio_set_value(usb_phy->gpio_vbus, SUNXI_GPIO_PULL_DISABLE); 239 240 return 0; 241 } 242 243 static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, bool id_det) 244 { 245 u32 regval; 246 247 regval = readl(data->base + REG_PHY_OTGCTL); 248 if (!id_det) { 249 /* Host mode. Route phy0 to EHCI/OHCI */ 250 regval &= ~OTGCTL_ROUTE_MUSB; 251 } else { 252 /* Peripheral mode. Route phy0 to MUSB */ 253 regval |= OTGCTL_ROUTE_MUSB; 254 } 255 writel(regval, data->base + REG_PHY_OTGCTL); 256 } 257 258 static int sun4i_usb_phy_init(struct phy *phy) 259 { 260 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); 261 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; 262 u32 val; 263 int ret; 264 265 ret = clk_enable(&usb_phy->clocks); 266 if (ret) { 267 dev_err(dev, "failed to enable usb_%ldphy clock\n", phy->id); 268 return ret; 269 } 270 271 ret = reset_deassert(&usb_phy->resets); 272 if (ret) { 273 dev_err(dev, "failed to deassert usb_%ldreset reset\n", phy->id); 274 return ret; 275 } 276 277 if (data->cfg->type == sun8i_a83t_phy) { 278 if (phy->id == 0) { 279 val = readl(data->base + data->cfg->phyctl_offset); 280 val |= PHY_CTL_VBUSVLDEXT; 281 val &= ~PHY_CTL_SIDDQ; 282 writel(val, data->base + data->cfg->phyctl_offset); 283 } 284 } else { 285 if (usb_phy->pmu && data->cfg->enable_pmu_unk1) { 286 val = readl(usb_phy->pmu + REG_PMU_UNK1); 287 writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1); 288 } 289 290 if (usb_phy->id == 0) 291 sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 292 PHY_RES45_CAL_DATA, 293 PHY_RES45_CAL_LEN); 294 295 /* Adjust PHY's magnitude and rate */ 296 sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 297 PHY_TX_MAGNITUDE | PHY_TX_RATE, 298 PHY_TX_AMPLITUDE_LEN); 299 300 /* Disconnect threshold adjustment */ 301 sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, 302 data->cfg->disc_thresh, PHY_DISCON_TH_LEN); 303 } 304 305 sun4i_usb_phy_passby(phy, true); 306 307 sun4i_usb_phy0_reroute(data, true); 308 309 return 0; 310 } 311 312 static int sun4i_usb_phy_exit(struct phy *phy) 313 { 314 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); 315 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; 316 int ret; 317 318 if (phy->id == 0) { 319 if (data->cfg->type == sun8i_a83t_phy) { 320 void __iomem *phyctl = data->base + 321 data->cfg->phyctl_offset; 322 323 writel(readl(phyctl) | PHY_CTL_SIDDQ, phyctl); 324 } 325 } 326 327 sun4i_usb_phy_passby(phy, false); 328 329 ret = clk_disable(&usb_phy->clocks); 330 if (ret) { 331 dev_err(dev, "failed to disable usb_%ldphy clock\n", phy->id); 332 return ret; 333 } 334 335 ret = reset_assert(&usb_phy->resets); 336 if (ret) { 337 dev_err(dev, "failed to assert usb_%ldreset reset\n", phy->id); 338 return ret; 339 } 340 341 return 0; 342 } 343 344 static int sun4i_usb_phy_xlate(struct phy *phy, 345 struct ofnode_phandle_args *args) 346 { 347 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); 348 349 if (args->args_count >= data->cfg->num_phys) 350 return -EINVAL; 351 352 if (args->args_count) 353 phy->id = args->args[0]; 354 else 355 phy->id = 0; 356 357 debug("%s: phy_id = %ld\n", __func__, phy->id); 358 return 0; 359 } 360 361 int sun4i_usb_phy_vbus_detect(struct phy *phy) 362 { 363 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); 364 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; 365 int err, retries = 3; 366 367 debug("%s: id_det = %d\n", __func__, usb_phy->gpio_id_det); 368 369 if (usb_phy->gpio_vbus_det < 0) 370 return usb_phy->gpio_vbus_det; 371 372 err = gpio_get_value(usb_phy->gpio_vbus_det); 373 /* 374 * Vbus may have been provided by the board and just been turned of 375 * some milliseconds ago on reset, what we're measuring then is a 376 * residual charge on Vbus, sleep a bit and try again. 377 */ 378 while (err > 0 && retries--) { 379 mdelay(100); 380 err = gpio_get_value(usb_phy->gpio_vbus_det); 381 } 382 383 return err; 384 } 385 386 int sun4i_usb_phy_id_detect(struct phy *phy) 387 { 388 struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev); 389 struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id]; 390 391 debug("%s: id_det = %d\n", __func__, usb_phy->gpio_id_det); 392 393 if (usb_phy->gpio_id_det < 0) 394 return usb_phy->gpio_id_det; 395 396 return gpio_get_value(usb_phy->gpio_id_det); 397 } 398 399 void sun4i_usb_phy_set_squelch_detect(struct phy *phy, bool enabled) 400 { 401 sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2); 402 } 403 404 static struct phy_ops sun4i_usb_phy_ops = { 405 .of_xlate = sun4i_usb_phy_xlate, 406 .init = sun4i_usb_phy_init, 407 .power_on = sun4i_usb_phy_power_on, 408 .power_off = sun4i_usb_phy_power_off, 409 .exit = sun4i_usb_phy_exit, 410 }; 411 412 static int sun4i_usb_phy_probe(struct udevice *dev) 413 { 414 struct sun4i_usb_phy_plat *plat = dev_get_platdata(dev); 415 struct sun4i_usb_phy_data *data = dev_get_priv(dev); 416 int i, ret; 417 418 data->cfg = (const struct sun4i_usb_phy_cfg *)dev_get_driver_data(dev); 419 if (!data->cfg) 420 return -EINVAL; 421 422 data->base = (void __iomem *)devfdt_get_addr_name(dev, "phy_ctrl"); 423 if (IS_ERR(data->base)) 424 return PTR_ERR(data->base); 425 426 data->usb_phy = plat; 427 for (i = 0; i < data->cfg->num_phys; i++) { 428 struct sun4i_usb_phy_plat *phy = &plat[i]; 429 struct sun4i_usb_phy_info *info = &phy_info[i]; 430 char name[16]; 431 432 phy->gpio_vbus = sunxi_name_to_gpio(info->gpio_vbus); 433 if (phy->gpio_vbus >= 0) { 434 ret = gpio_request(phy->gpio_vbus, "usb_vbus"); 435 if (ret) 436 return ret; 437 ret = gpio_direction_output(phy->gpio_vbus, 0); 438 if (ret) 439 return ret; 440 } 441 442 phy->gpio_vbus_det = sunxi_name_to_gpio(info->gpio_vbus_det); 443 if (phy->gpio_vbus_det >= 0) { 444 ret = gpio_request(phy->gpio_vbus_det, "usb_vbus_det"); 445 if (ret) 446 return ret; 447 ret = gpio_direction_input(phy->gpio_vbus_det); 448 if (ret) 449 return ret; 450 } 451 452 phy->gpio_id_det = sunxi_name_to_gpio(info->gpio_id_det); 453 if (phy->gpio_id_det >= 0) { 454 ret = gpio_request(phy->gpio_id_det, "usb_id_det"); 455 if (ret) 456 return ret; 457 ret = gpio_direction_input(phy->gpio_id_det); 458 if (ret) 459 return ret; 460 sunxi_gpio_set_pull(phy->gpio_id_det, SUNXI_GPIO_PULL_UP); 461 } 462 463 if (data->cfg->dedicated_clocks) 464 snprintf(name, sizeof(name), "usb%d_phy", i); 465 else 466 strlcpy(name, "usb_phy", sizeof(name)); 467 468 ret = clk_get_by_name(dev, name, &phy->clocks); 469 if (ret) { 470 dev_err(dev, "failed to get usb%d_phy clock phandle\n", i); 471 return ret; 472 } 473 474 snprintf(name, sizeof(name), "usb%d_reset", i); 475 ret = reset_get_by_name(dev, name, &phy->resets); 476 if (ret) { 477 dev_err(dev, "failed to get usb%d_reset reset phandle\n", i); 478 return ret; 479 } 480 481 if (i || data->cfg->phy0_dual_route) { 482 snprintf(name, sizeof(name), "pmu%d", i); 483 phy->pmu = (void __iomem *)devfdt_get_addr_name(dev, name); 484 if (IS_ERR(phy->pmu)) 485 return PTR_ERR(phy->pmu); 486 } 487 488 phy->id = i; 489 }; 490 491 debug("Allwinner Sun4I USB PHY driver loaded\n"); 492 return 0; 493 } 494 495 static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { 496 .num_phys = 3, 497 .type = sun4i_a10_phy, 498 .disc_thresh = 3, 499 .phyctl_offset = REG_PHYCTL_A10, 500 .dedicated_clocks = false, 501 .enable_pmu_unk1 = false, 502 }; 503 504 static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { 505 .num_phys = 2, 506 .type = sun4i_a10_phy, 507 .disc_thresh = 2, 508 .phyctl_offset = REG_PHYCTL_A10, 509 .dedicated_clocks = false, 510 .enable_pmu_unk1 = false, 511 }; 512 513 static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { 514 .num_phys = 3, 515 .type = sun6i_a31_phy, 516 .disc_thresh = 3, 517 .phyctl_offset = REG_PHYCTL_A10, 518 .dedicated_clocks = true, 519 .enable_pmu_unk1 = false, 520 }; 521 522 static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { 523 .num_phys = 3, 524 .type = sun4i_a10_phy, 525 .disc_thresh = 2, 526 .phyctl_offset = REG_PHYCTL_A10, 527 .dedicated_clocks = false, 528 .enable_pmu_unk1 = false, 529 }; 530 531 static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { 532 .num_phys = 2, 533 .type = sun4i_a10_phy, 534 .disc_thresh = 3, 535 .phyctl_offset = REG_PHYCTL_A10, 536 .dedicated_clocks = true, 537 .enable_pmu_unk1 = false, 538 }; 539 540 static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { 541 .num_phys = 2, 542 .type = sun8i_a33_phy, 543 .disc_thresh = 3, 544 .phyctl_offset = REG_PHYCTL_A33, 545 .dedicated_clocks = true, 546 .enable_pmu_unk1 = false, 547 }; 548 549 static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = { 550 .num_phys = 3, 551 .type = sun8i_a83t_phy, 552 .phyctl_offset = REG_PHYCTL_A33, 553 .dedicated_clocks = true, 554 }; 555 556 static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { 557 .num_phys = 4, 558 .type = sun8i_h3_phy, 559 .disc_thresh = 3, 560 .phyctl_offset = REG_PHYCTL_A33, 561 .dedicated_clocks = true, 562 .enable_pmu_unk1 = true, 563 .phy0_dual_route = true, 564 }; 565 566 static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { 567 .num_phys = 1, 568 .type = sun8i_v3s_phy, 569 .disc_thresh = 3, 570 .phyctl_offset = REG_PHYCTL_A33, 571 .dedicated_clocks = true, 572 .enable_pmu_unk1 = true, 573 .phy0_dual_route = true, 574 }; 575 576 static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { 577 .num_phys = 2, 578 .type = sun50i_a64_phy, 579 .disc_thresh = 3, 580 .phyctl_offset = REG_PHYCTL_A33, 581 .dedicated_clocks = true, 582 .enable_pmu_unk1 = true, 583 .phy0_dual_route = true, 584 }; 585 586 static const struct udevice_id sun4i_usb_phy_ids[] = { 587 { .compatible = "allwinner,sun4i-a10-usb-phy", .data = (ulong)&sun4i_a10_cfg }, 588 { .compatible = "allwinner,sun5i-a13-usb-phy", .data = (ulong)&sun5i_a13_cfg }, 589 { .compatible = "allwinner,sun6i-a31-usb-phy", .data = (ulong)&sun6i_a31_cfg }, 590 { .compatible = "allwinner,sun7i-a20-usb-phy", .data = (ulong)&sun7i_a20_cfg }, 591 { .compatible = "allwinner,sun8i-a23-usb-phy", .data = (ulong)&sun8i_a23_cfg }, 592 { .compatible = "allwinner,sun8i-a33-usb-phy", .data = (ulong)&sun8i_a33_cfg }, 593 { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = (ulong)&sun8i_a83t_cfg }, 594 { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, 595 { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg }, 596 { .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg}, 597 { } 598 }; 599 600 U_BOOT_DRIVER(sun4i_usb_phy) = { 601 .name = "sun4i_usb_phy", 602 .id = UCLASS_PHY, 603 .of_match = sun4i_usb_phy_ids, 604 .ops = &sun4i_usb_phy_ops, 605 .probe = sun4i_usb_phy_probe, 606 .platdata_auto_alloc_size = sizeof(struct sun4i_usb_phy_plat[MAX_PHYS]), 607 .priv_auto_alloc_size = sizeof(struct sun4i_usb_phy_data), 608 }; 609