aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVivek Gautam <gautam.vivek@samsung.com>2014-11-21 08:35:48 -0500
committerKishon Vijay Abraham I <kishon@ti.com>2014-11-22 03:38:09 -0500
commit9bde18c1b5d2c9a1b90fc0f3bbe1a314194f6fdf (patch)
treec8a08327bbf81276ce55e57c65637ec62ca372ca
parent08f871a3aca252b15107fc37dedcdacbac80fdb5 (diff)
phy: exynos5-usbdrd: Add pipe-clk, utmi-clk and itp-clk support
Exynos7 SoC has now separate gate control for 125MHz pipe3 phy clock, as well as 60MHz utmi phy clock. Additionally, separate gate control is available for the clock used for ITP (Isochronous Transfer Packet) generation. So get the same and control in the phy-exynos5-usbdrd driver. Suggested-by: Anton Tikhomirov <av.tikhomirov@samsung.com> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r--Documentation/devicetree/bindings/phy/samsung-phy.txt6
-rw-r--r--drivers/phy/phy-exynos5-usbdrd.c104
2 files changed, 92 insertions, 18 deletions
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index 15e0f2c7130f..d5bad920827f 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -128,6 +128,7 @@ Required properties:
128- compatible : Should be set to one of the following supported values: 128- compatible : Should be set to one of the following supported values:
129 - "samsung,exynos5250-usbdrd-phy" - for exynos5250 SoC, 129 - "samsung,exynos5250-usbdrd-phy" - for exynos5250 SoC,
130 - "samsung,exynos5420-usbdrd-phy" - for exynos5420 SoC. 130 - "samsung,exynos5420-usbdrd-phy" - for exynos5420 SoC.
131 - "samsung,exynos7-usbdrd-phy" - for exynos7 SoC.
131- reg : Register offset and length of USB DRD PHY register set; 132- reg : Register offset and length of USB DRD PHY register set;
132- clocks: Clock IDs array as required by the controller 133- clocks: Clock IDs array as required by the controller
133- clock-names: names of clocks correseponding to IDs in the clock property; 134- clock-names: names of clocks correseponding to IDs in the clock property;
@@ -138,6 +139,11 @@ Required properties:
138 PHY operations, associated by phy name. It is used to 139 PHY operations, associated by phy name. It is used to
139 determine bit values for clock settings register. 140 determine bit values for clock settings register.
140 For Exynos5420 this is given as 'sclk_usbphy30' in CMU. 141 For Exynos5420 this is given as 'sclk_usbphy30' in CMU.
142 - optional clocks: Exynos7 SoC has now following additional
143 gate clocks available:
144 - phy_pipe: for PIPE3 phy
145 - phy_utmi: for UTMI+ phy
146 - itp: for ITP generation
141- samsung,pmu-syscon: phandle for PMU system controller interface, used to 147- samsung,pmu-syscon: phandle for PMU system controller interface, used to
142 control pmu registers for power isolation. 148 control pmu registers for power isolation.
143- #phy-cells : from the generic PHY bindings, must be 1; 149- #phy-cells : from the generic PHY bindings, must be 1;
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index b3ca3bc2314f..99ba56dc63dd 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,14 @@ 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
159 */ 162 */
160struct exynos5_usbdrd_phy { 163struct exynos5_usbdrd_phy {
161 struct device *dev; 164 struct device *dev;
162 void __iomem *reg_phy; 165 void __iomem *reg_phy;
163 struct clk *clk; 166 struct clk *clk;
167 struct clk *pipeclk;
168 struct clk *utmiclk;
169 struct clk *itpclk;
164 const struct exynos5_usbdrd_phy_drvdata *drv_data; 170 const struct exynos5_usbdrd_phy_drvdata *drv_data;
165 struct phy_usb_instance { 171 struct phy_usb_instance {
166 struct phy *phy; 172 struct phy *phy;
@@ -447,6 +453,11 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy)
447 dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n"); 453 dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
448 454
449 clk_prepare_enable(phy_drd->ref_clk); 455 clk_prepare_enable(phy_drd->ref_clk);
456 if (!phy_drd->drv_data->has_common_clk_gate) {
457 clk_prepare_enable(phy_drd->pipeclk);
458 clk_prepare_enable(phy_drd->utmiclk);
459 clk_prepare_enable(phy_drd->itpclk);
460 }
450 461
451 /* Enable VBUS supply */ 462 /* Enable VBUS supply */
452 if (phy_drd->vbus) { 463 if (phy_drd->vbus) {
@@ -464,6 +475,11 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy)
464 475
465fail_vbus: 476fail_vbus:
466 clk_disable_unprepare(phy_drd->ref_clk); 477 clk_disable_unprepare(phy_drd->ref_clk);
478 if (!phy_drd->drv_data->has_common_clk_gate) {
479 clk_disable_unprepare(phy_drd->itpclk);
480 clk_disable_unprepare(phy_drd->utmiclk);
481 clk_disable_unprepare(phy_drd->pipeclk);
482 }
467 483
468 return ret; 484 return ret;
469} 485}
@@ -483,6 +499,11 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
483 regulator_disable(phy_drd->vbus); 499 regulator_disable(phy_drd->vbus);
484 500
485 clk_disable_unprepare(phy_drd->ref_clk); 501 clk_disable_unprepare(phy_drd->ref_clk);
502 if (!phy_drd->drv_data->has_common_clk_gate) {
503 clk_disable_unprepare(phy_drd->itpclk);
504 clk_disable_unprepare(phy_drd->pipeclk);
505 clk_disable_unprepare(phy_drd->utmiclk);
506 }
486 507
487 return 0; 508 return 0;
488} 509}
@@ -506,6 +527,57 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
506 .owner = THIS_MODULE, 527 .owner = THIS_MODULE,
507}; 528};
508 529
530static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
531{
532 unsigned long ref_rate;
533 int ret;
534
535 phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
536 if (IS_ERR(phy_drd->clk)) {
537 dev_err(phy_drd->dev, "Failed to get phy clock\n");
538 return PTR_ERR(phy_drd->clk);
539 }
540
541 phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
542 if (IS_ERR(phy_drd->ref_clk)) {
543 dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
544 return PTR_ERR(phy_drd->ref_clk);
545 }
546 ref_rate = clk_get_rate(phy_drd->ref_clk);
547
548 ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
549 if (ret) {
550 dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
551 ref_rate);
552 return ret;
553 }
554
555 if (!phy_drd->drv_data->has_common_clk_gate) {
556 phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
557 if (IS_ERR(phy_drd->pipeclk)) {
558 dev_info(phy_drd->dev,
559 "PIPE3 phy operational clock not specified\n");
560 phy_drd->pipeclk = NULL;
561 }
562
563 phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
564 if (IS_ERR(phy_drd->utmiclk)) {
565 dev_info(phy_drd->dev,
566 "UTMI phy operational clock not specified\n");
567 phy_drd->utmiclk = NULL;
568 }
569
570 phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
571 if (IS_ERR(phy_drd->itpclk)) {
572 dev_info(phy_drd->dev,
573 "ITP clock from main OSC not specified\n");
574 phy_drd->itpclk = NULL;
575 }
576 }
577
578 return 0;
579}
580
509static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { 581static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
510 { 582 {
511 .id = EXYNOS5_DRDPHY_UTMI, 583 .id = EXYNOS5_DRDPHY_UTMI,
@@ -525,11 +597,19 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
525 .phy_cfg = phy_cfg_exynos5, 597 .phy_cfg = phy_cfg_exynos5,
526 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 598 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
527 .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL, 599 .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
600 .has_common_clk_gate = true,
528}; 601};
529 602
530static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = { 603static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
531 .phy_cfg = phy_cfg_exynos5, 604 .phy_cfg = phy_cfg_exynos5,
532 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 605 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
606 .has_common_clk_gate = true,
607};
608
609static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
610 .phy_cfg = phy_cfg_exynos5,
611 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
612 .has_common_clk_gate = false,
533}; 613};
534 614
535static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { 615static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
@@ -539,6 +619,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
539 }, { 619 }, {
540 .compatible = "samsung,exynos5420-usbdrd-phy", 620 .compatible = "samsung,exynos5420-usbdrd-phy",
541 .data = &exynos5420_usbdrd_phy 621 .data = &exynos5420_usbdrd_phy
622 }, {
623 .compatible = "samsung,exynos7-usbdrd-phy",
624 .data = &exynos7_usbdrd_phy
542 }, 625 },
543 { }, 626 { },
544}; 627};
@@ -555,7 +638,6 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
555 const struct exynos5_usbdrd_phy_drvdata *drv_data; 638 const struct exynos5_usbdrd_phy_drvdata *drv_data;
556 struct regmap *reg_pmu; 639 struct regmap *reg_pmu;
557 u32 pmu_offset; 640 u32 pmu_offset;
558 unsigned long ref_rate;
559 int i, ret; 641 int i, ret;
560 int channel; 642 int channel;
561 643
@@ -576,23 +658,9 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
576 drv_data = match->data; 658 drv_data = match->data;
577 phy_drd->drv_data = drv_data; 659 phy_drd->drv_data = drv_data;
578 660
579 phy_drd->clk = devm_clk_get(dev, "phy"); 661 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) { 662 if (ret) {
594 dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n", 663 dev_err(dev, "Failed to initialize clocks\n");
595 ref_rate);
596 return ret; 664 return ret;
597 } 665 }
598 666