aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy/phy-exynos5-usbdrd.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 17:57:16 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 17:57:16 -0500
commite7cf773d431a63a2417902696fcc9e0ebdc83bbe (patch)
tree86dbdceb7d91226507a3af0d57e03b0ca664b22e /drivers/phy/phy-exynos5-usbdrd.c
parent7a02d089695a1217992434f03a78aa32bad85b5c (diff)
parent81e1dadfb5b2d47aa513ad60b1c9cf0ea17b6514 (diff)
Merge tag 'usb-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH: "Here's the big set of USB and PHY patches for 3.19-rc1. The normal churn in the USB gadget area is in here, as well as xhci and other individual USB driver updates. The PHY tree is also in here, as there were dependancies on the USB tree. All of these have been in linux-next" * tag 'usb-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (351 commits) arm: omap3: twl: remove usb phy init data usbip: fix error handling in stub_probe() usb: gadget: udc: missing curly braces USB: mos7720: delete some unneeded code wusb: replace memset by memzero_explicit usbip: remove unneeded structure usb: xhci: fix comment for PORT_DEV_REMOVE xhci: don't use the same variable for stopped and halted rings current TD xhci: clear extra bits from slot context when setting max exit latency xhci: cleanup finish_td function USB: adutux: NULL dereferences on disconnect usb: chipidea: fix platform_no_drv_owner.cocci warnings usb: chipidea: Fixed a few typos in comments Documentation: bindings: add doc for the USB2 ChipIdea USB driver usb: chipidea: add a usb2 driver for ci13xxx usb: chipidea: fix phy handling usb: chipidea: remove duplicate dev_set_drvdata for host_start usb: chipidea: parameter 'mode' isn't needed for hw_device_reset usb: chipidea: add controller reset API usb: chipidea: remove flag CI_HDRC_REQUIRE_TRANSCEIVER ...
Diffstat (limited to 'drivers/phy/phy-exynos5-usbdrd.c')
-rw-r--r--drivers/phy/phy-exynos5-usbdrd.c139
1 files changed, 117 insertions, 22 deletions
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index f756aca871db..04374018425f 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -141,6 +141,7 @@ struct exynos5_usbdrd_phy_drvdata {
141 const struct exynos5_usbdrd_phy_config *phy_cfg; 141 const struct exynos5_usbdrd_phy_config *phy_cfg;
142 u32 pmu_offset_usbdrd0_phy; 142 u32 pmu_offset_usbdrd0_phy;
143 u32 pmu_offset_usbdrd1_phy; 143 u32 pmu_offset_usbdrd1_phy;
144 bool has_common_clk_gate;
144}; 145};
145 146
146/** 147/**
@@ -148,6 +149,9 @@ struct exynos5_usbdrd_phy_drvdata {
148 * @dev: pointer to device instance of this platform device 149 * @dev: pointer to device instance of this platform device
149 * @reg_phy: usb phy controller register memory base 150 * @reg_phy: usb phy controller register memory base
150 * @clk: phy clock for register access 151 * @clk: phy clock for register access
152 * @pipeclk: clock for pipe3 phy
153 * @utmiclk: clock for utmi+ phy
154 * @itpclk: clock for ITP generation
151 * @drv_data: pointer to SoC level driver data structure 155 * @drv_data: pointer to SoC level driver data structure
152 * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY 156 * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
153 * instances each with its 'phy' and 'phy_cfg'. 157 * instances each with its 'phy' and 'phy_cfg'.
@@ -155,12 +159,16 @@ struct exynos5_usbdrd_phy_drvdata {
155 * reference clocks' for SS and HS operations 159 * reference clocks' for SS and HS operations
156 * @ref_clk: reference clock to PHY block from which PHY's 160 * @ref_clk: reference clock to PHY block from which PHY's
157 * operational clocks are derived 161 * operational clocks are derived
158 * @ref_rate: rate of above reference clock 162 * vbus: VBUS regulator for phy
163 * vbus_boost: Boost regulator for VBUS present on few Exynos boards
159 */ 164 */
160struct exynos5_usbdrd_phy { 165struct exynos5_usbdrd_phy {
161 struct device *dev; 166 struct device *dev;
162 void __iomem *reg_phy; 167 void __iomem *reg_phy;
163 struct clk *clk; 168 struct clk *clk;
169 struct clk *pipeclk;
170 struct clk *utmiclk;
171 struct clk *itpclk;
164 const struct exynos5_usbdrd_phy_drvdata *drv_data; 172 const struct exynos5_usbdrd_phy_drvdata *drv_data;
165 struct phy_usb_instance { 173 struct phy_usb_instance {
166 struct phy *phy; 174 struct phy *phy;
@@ -172,6 +180,7 @@ struct exynos5_usbdrd_phy {
172 u32 extrefclk; 180 u32 extrefclk;
173 struct clk *ref_clk; 181 struct clk *ref_clk;
174 struct regulator *vbus; 182 struct regulator *vbus;
183 struct regulator *vbus_boost;
175}; 184};
176 185
177static inline 186static inline
@@ -447,13 +456,27 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy)
447 dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n"); 456 dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
448 457
449 clk_prepare_enable(phy_drd->ref_clk); 458 clk_prepare_enable(phy_drd->ref_clk);
459 if (!phy_drd->drv_data->has_common_clk_gate) {
460 clk_prepare_enable(phy_drd->pipeclk);
461 clk_prepare_enable(phy_drd->utmiclk);
462 clk_prepare_enable(phy_drd->itpclk);
463 }
450 464
451 /* Enable VBUS supply */ 465 /* Enable VBUS supply */
466 if (phy_drd->vbus_boost) {
467 ret = regulator_enable(phy_drd->vbus_boost);
468 if (ret) {
469 dev_err(phy_drd->dev,
470 "Failed to enable VBUS boost supply\n");
471 goto fail_vbus;
472 }
473 }
474
452 if (phy_drd->vbus) { 475 if (phy_drd->vbus) {
453 ret = regulator_enable(phy_drd->vbus); 476 ret = regulator_enable(phy_drd->vbus);
454 if (ret) { 477 if (ret) {
455 dev_err(phy_drd->dev, "Failed to enable VBUS supply\n"); 478 dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
456 goto fail_vbus; 479 goto fail_vbus_boost;
457 } 480 }
458 } 481 }
459 482
@@ -462,8 +485,17 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy)
462 485
463 return 0; 486 return 0;
464 487
488fail_vbus_boost:
489 if (phy_drd->vbus_boost)
490 regulator_disable(phy_drd->vbus_boost);
491
465fail_vbus: 492fail_vbus:
466 clk_disable_unprepare(phy_drd->ref_clk); 493 clk_disable_unprepare(phy_drd->ref_clk);
494 if (!phy_drd->drv_data->has_common_clk_gate) {
495 clk_disable_unprepare(phy_drd->itpclk);
496 clk_disable_unprepare(phy_drd->utmiclk);
497 clk_disable_unprepare(phy_drd->pipeclk);
498 }
467 499
468 return ret; 500 return ret;
469} 501}
@@ -481,8 +513,15 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
481 /* Disable VBUS supply */ 513 /* Disable VBUS supply */
482 if (phy_drd->vbus) 514 if (phy_drd->vbus)
483 regulator_disable(phy_drd->vbus); 515 regulator_disable(phy_drd->vbus);
516 if (phy_drd->vbus_boost)
517 regulator_disable(phy_drd->vbus_boost);
484 518
485 clk_disable_unprepare(phy_drd->ref_clk); 519 clk_disable_unprepare(phy_drd->ref_clk);
520 if (!phy_drd->drv_data->has_common_clk_gate) {
521 clk_disable_unprepare(phy_drd->itpclk);
522 clk_disable_unprepare(phy_drd->pipeclk);
523 clk_disable_unprepare(phy_drd->utmiclk);
524 }
486 525
487 return 0; 526 return 0;
488} 527}
@@ -506,6 +545,57 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
506 .owner = THIS_MODULE, 545 .owner = THIS_MODULE,
507}; 546};
508 547
548static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
549{
550 unsigned long ref_rate;
551 int ret;
552
553 phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
554 if (IS_ERR(phy_drd->clk)) {
555 dev_err(phy_drd->dev, "Failed to get phy clock\n");
556 return PTR_ERR(phy_drd->clk);
557 }
558
559 phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
560 if (IS_ERR(phy_drd->ref_clk)) {
561 dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
562 return PTR_ERR(phy_drd->ref_clk);
563 }
564 ref_rate = clk_get_rate(phy_drd->ref_clk);
565
566 ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
567 if (ret) {
568 dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
569 ref_rate);
570 return ret;
571 }
572
573 if (!phy_drd->drv_data->has_common_clk_gate) {
574 phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
575 if (IS_ERR(phy_drd->pipeclk)) {
576 dev_info(phy_drd->dev,
577 "PIPE3 phy operational clock not specified\n");
578 phy_drd->pipeclk = NULL;
579 }
580
581 phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
582 if (IS_ERR(phy_drd->utmiclk)) {
583 dev_info(phy_drd->dev,
584 "UTMI phy operational clock not specified\n");
585 phy_drd->utmiclk = NULL;
586 }
587
588 phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
589 if (IS_ERR(phy_drd->itpclk)) {
590 dev_info(phy_drd->dev,
591 "ITP clock from main OSC not specified\n");
592 phy_drd->itpclk = NULL;
593 }
594 }
595
596 return 0;
597}
598
509static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { 599static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
510 { 600 {
511 .id = EXYNOS5_DRDPHY_UTMI, 601 .id = EXYNOS5_DRDPHY_UTMI,
@@ -525,11 +615,19 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
525 .phy_cfg = phy_cfg_exynos5, 615 .phy_cfg = phy_cfg_exynos5,
526 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 616 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
527 .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL, 617 .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
618 .has_common_clk_gate = true,
528}; 619};
529 620
530static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = { 621static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
531 .phy_cfg = phy_cfg_exynos5, 622 .phy_cfg = phy_cfg_exynos5,
532 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 623 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
624 .has_common_clk_gate = true,
625};
626
627static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
628 .phy_cfg = phy_cfg_exynos5,
629 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
630 .has_common_clk_gate = false,
533}; 631};
534 632
535static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { 633static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
@@ -539,6 +637,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
539 }, { 637 }, {
540 .compatible = "samsung,exynos5420-usbdrd-phy", 638 .compatible = "samsung,exynos5420-usbdrd-phy",
541 .data = &exynos5420_usbdrd_phy 639 .data = &exynos5420_usbdrd_phy
640 }, {
641 .compatible = "samsung,exynos7-usbdrd-phy",
642 .data = &exynos7_usbdrd_phy
542 }, 643 },
543 { }, 644 { },
544}; 645};
@@ -555,7 +656,6 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
555 const struct exynos5_usbdrd_phy_drvdata *drv_data; 656 const struct exynos5_usbdrd_phy_drvdata *drv_data;
556 struct regmap *reg_pmu; 657 struct regmap *reg_pmu;
557 u32 pmu_offset; 658 u32 pmu_offset;
558 unsigned long ref_rate;
559 int i, ret; 659 int i, ret;
560 int channel; 660 int channel;
561 661
@@ -576,23 +676,9 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
576 drv_data = match->data; 676 drv_data = match->data;
577 phy_drd->drv_data = drv_data; 677 phy_drd->drv_data = drv_data;
578 678
579 phy_drd->clk = devm_clk_get(dev, "phy"); 679 ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
580 if (IS_ERR(phy_drd->clk)) {
581 dev_err(dev, "Failed to get clock of phy controller\n");
582 return PTR_ERR(phy_drd->clk);
583 }
584
585 phy_drd->ref_clk = devm_clk_get(dev, "ref");
586 if (IS_ERR(phy_drd->ref_clk)) {
587 dev_err(dev, "Failed to get reference clock of usbdrd phy\n");
588 return PTR_ERR(phy_drd->ref_clk);
589 }
590 ref_rate = clk_get_rate(phy_drd->ref_clk);
591
592 ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
593 if (ret) { 680 if (ret) {
594 dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n", 681 dev_err(dev, "Failed to initialize clocks\n");
595 ref_rate);
596 return ret; 682 return ret;
597 } 683 }
598 684
@@ -622,7 +708,7 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
622 break; 708 break;
623 } 709 }
624 710
625 /* Get Vbus regulator */ 711 /* Get Vbus regulators */
626 phy_drd->vbus = devm_regulator_get(dev, "vbus"); 712 phy_drd->vbus = devm_regulator_get(dev, "vbus");
627 if (IS_ERR(phy_drd->vbus)) { 713 if (IS_ERR(phy_drd->vbus)) {
628 ret = PTR_ERR(phy_drd->vbus); 714 ret = PTR_ERR(phy_drd->vbus);
@@ -633,12 +719,21 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
633 phy_drd->vbus = NULL; 719 phy_drd->vbus = NULL;
634 } 720 }
635 721
722 phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
723 if (IS_ERR(phy_drd->vbus_boost)) {
724 ret = PTR_ERR(phy_drd->vbus_boost);
725 if (ret == -EPROBE_DEFER)
726 return ret;
727
728 dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
729 phy_drd->vbus_boost = NULL;
730 }
731
636 dev_vdbg(dev, "Creating usbdrd_phy phy\n"); 732 dev_vdbg(dev, "Creating usbdrd_phy phy\n");
637 733
638 for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) { 734 for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
639 struct phy *phy = devm_phy_create(dev, NULL, 735 struct phy *phy = devm_phy_create(dev, NULL,
640 &exynos5_usbdrd_phy_ops, 736 &exynos5_usbdrd_phy_ops);
641 NULL);
642 if (IS_ERR(phy)) { 737 if (IS_ERR(phy)) {
643 dev_err(dev, "Failed to create usbdrd_phy phy\n"); 738 dev_err(dev, "Failed to create usbdrd_phy phy\n");
644 return PTR_ERR(phy); 739 return PTR_ERR(phy);