Merge tag 'phy-for-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy
[linux-2.6-microblaze.git] / drivers / phy / qualcomm / phy-qcom-snps-femto-v2.c
index a7af775..eb0b0f6 100644 (file)
@@ -109,11 +109,13 @@ struct phy_override_seq {
 /**
  * struct qcom_snps_hsphy - snps hs phy attributes
  *
+ * @dev: device structure
+ *
  * @phy: generic phy
  * @base: iomapped memory space for snps hs phy
  *
- * @cfg_ahb_clk: AHB2PHY interface clock
- * @ref_clk: phy reference clock
+ * @num_clks: number of clocks
+ * @clks: array of clocks
  * @phy_reset: phy reset control
  * @vregs: regulator supplies bulk data
  * @phy_initialized: if PHY has been initialized correctly
@@ -121,11 +123,13 @@ struct phy_override_seq {
  * @update_seq_cfg: tuning parameters for phy init
  */
 struct qcom_snps_hsphy {
+       struct device *dev;
+
        struct phy *phy;
        void __iomem *base;
 
-       struct clk *cfg_ahb_clk;
-       struct clk *ref_clk;
+       int num_clks;
+       struct clk_bulk_data *clks;
        struct reset_control *phy_reset;
        struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
 
@@ -134,6 +138,34 @@ struct qcom_snps_hsphy {
        struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS];
 };
 
+static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy)
+{
+       struct device *dev = hsphy->dev;
+
+       hsphy->num_clks = 2;
+       hsphy->clks = devm_kcalloc(dev, hsphy->num_clks, sizeof(*hsphy->clks), GFP_KERNEL);
+       if (!hsphy->clks)
+               return -ENOMEM;
+
+       /*
+        * TODO: Currently no device tree instantiation of the PHY is using the clock.
+        * This needs to be fixed in order for this code to be able to use devm_clk_bulk_get().
+        */
+       hsphy->clks[0].id = "cfg_ahb";
+       hsphy->clks[0].clk = devm_clk_get_optional(dev, "cfg_ahb");
+       if (IS_ERR(hsphy->clks[0].clk))
+               return dev_err_probe(dev, PTR_ERR(hsphy->clks[0].clk),
+                                    "failed to get cfg_ahb clk\n");
+
+       hsphy->clks[1].id = "ref";
+       hsphy->clks[1].clk = devm_clk_get(dev, "ref");
+       if (IS_ERR(hsphy->clks[1].clk))
+               return dev_err_probe(dev, PTR_ERR(hsphy->clks[1].clk),
+                                    "failed to get ref clk\n");
+
+       return 0;
+}
+
 static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
                                                u32 mask, u32 val)
 {
@@ -164,22 +196,13 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
                                           0, USB2_AUTO_RESUME);
        }
 
-       clk_disable_unprepare(hsphy->cfg_ahb_clk);
        return 0;
 }
 
 static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
 {
-       int ret;
-
        dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n");
 
-       ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
-       if (ret) {
-               dev_err(&hsphy->phy->dev, "failed to enable cfg ahb clock\n");
-               return ret;
-       }
-
        return 0;
 }
 
@@ -190,8 +213,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev)
        if (!hsphy->phy_initialized)
                return 0;
 
-       qcom_snps_hsphy_suspend(hsphy);
-       return 0;
+       return qcom_snps_hsphy_suspend(hsphy);
 }
 
 static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
@@ -201,8 +223,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
        if (!hsphy->phy_initialized)
                return 0;
 
-       qcom_snps_hsphy_resume(hsphy);
-       return 0;
+       return qcom_snps_hsphy_resume(hsphy);
 }
 
 static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
@@ -373,16 +394,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
        if (ret)
                return ret;
 
-       ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
+       ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks);
        if (ret) {
-               dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
+               dev_err(&phy->dev, "failed to enable clocks, %d\n", ret);
                goto poweroff_phy;
        }
 
        ret = reset_control_assert(hsphy->phy_reset);
        if (ret) {
                dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
-               goto disable_ahb_clk;
+               goto disable_clks;
        }
 
        usleep_range(100, 150);
@@ -390,7 +411,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
        ret = reset_control_deassert(hsphy->phy_reset);
        if (ret) {
                dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
-               goto disable_ahb_clk;
+               goto disable_clks;
        }
 
        qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
@@ -447,8 +468,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
 
        return 0;
 
-disable_ahb_clk:
-       clk_disable_unprepare(hsphy->cfg_ahb_clk);
+disable_clks:
+       clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
 poweroff_phy:
        regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
 
@@ -460,7 +481,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
        struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
 
        reset_control_assert(hsphy->phy_reset);
-       clk_disable_unprepare(hsphy->cfg_ahb_clk);
+       clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
        regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
        hsphy->phy_initialized = false;
 
@@ -553,14 +574,15 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
        if (!hsphy)
                return -ENOMEM;
 
+       hsphy->dev = dev;
+
        hsphy->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(hsphy->base))
                return PTR_ERR(hsphy->base);
 
-       hsphy->ref_clk = devm_clk_get(dev, "ref");
-       if (IS_ERR(hsphy->ref_clk))
-               return dev_err_probe(dev, PTR_ERR(hsphy->ref_clk),
-                                    "failed to get ref clk\n");
+       ret = qcom_snps_hsphy_clk_init(hsphy);
+       if (ret)
+               return dev_err_probe(dev, ret, "failed to initialize clocks\n");
 
        hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
        if (IS_ERR(hsphy->phy_reset)) {