In preparation for support for additional platforms, convert the phy register access clock to using the clk_bulk interfaces. Newer SoCs like Google Tensor gs101 require more clocks for register access, and converting to clk_bulk simplifies addition of those extra clocks. Given the list of phy register clocks is requested as optional, I haven't made it platform specific, as only those clocks that are actually declared (in the DT) will be retrieved and the code behaves as before this change. Nevertheless, this piece of the code is easy to change in the future if the need arises. Signed-off-by: André Draszik <andre.draszik@xxxxxxxxxx> --- drivers/phy/samsung/phy-exynos5-usbdrd.c | 45 +++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c index 88b03bb67fff..63933029ffa7 100644 --- a/drivers/phy/samsung/phy-exynos5-usbdrd.c +++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c @@ -194,7 +194,8 @@ struct exynos5_usbdrd_phy_drvdata { * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY * @dev: pointer to device instance of this platform device * @reg_phy: usb phy controller register memory base - * @clk: phy clock for register access + * @phy_clks: phy clocks for register access + * @n_phy_clks: number of phy clocks for register access * @pipeclk: clock for pipe3 phy * @utmiclk: clock for utmi+ phy * @itpclk: clock for ITP generation @@ -211,7 +212,8 @@ struct exynos5_usbdrd_phy_drvdata { struct exynos5_usbdrd_phy { struct device *dev; void __iomem *reg_phy; - struct clk *clk; + struct clk_bulk_data *phy_clks; + size_t n_phy_clks; struct clk *pipeclk; struct clk *utmiclk; struct clk *itpclk; @@ -407,7 +409,7 @@ static int exynos5_usbdrd_phy_init(struct phy *phy) struct phy_usb_instance *inst = phy_get_drvdata(phy); struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); - ret = clk_prepare_enable(phy_drd->clk); + ret = clk_bulk_prepare_enable(phy_drd->n_phy_clks, phy_drd->phy_clks); if (ret) return ret; @@ -457,7 +459,7 @@ static int exynos5_usbdrd_phy_init(struct phy *phy) reg &= ~PHYCLKRST_PORTRESET; writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); - clk_disable_unprepare(phy_drd->clk); + clk_bulk_disable_unprepare(phy_drd->n_phy_clks, phy_drd->phy_clks); return 0; } @@ -469,7 +471,7 @@ static int exynos5_usbdrd_phy_exit(struct phy *phy) struct phy_usb_instance *inst = phy_get_drvdata(phy); struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); - ret = clk_prepare_enable(phy_drd->clk); + ret = clk_bulk_prepare_enable(phy_drd->n_phy_clks, phy_drd->phy_clks); if (ret) return ret; @@ -491,7 +493,7 @@ static int exynos5_usbdrd_phy_exit(struct phy *phy) PHYTEST_POWERDOWN_HSP; writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); - clk_disable_unprepare(phy_drd->clk); + clk_bulk_disable_unprepare(phy_drd->n_phy_clks, phy_drd->phy_clks); return 0; } @@ -826,14 +828,14 @@ static int exynos850_usbdrd_phy_init(struct phy *phy) struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); int ret; - ret = clk_prepare_enable(phy_drd->clk); + ret = clk_bulk_prepare_enable(phy_drd->n_phy_clks, phy_drd->phy_clks); if (ret) return ret; /* UTMI or PIPE3 specific init */ inst->phy_cfg->phy_init(phy_drd); - clk_disable_unprepare(phy_drd->clk); + clk_bulk_disable_unprepare(phy_drd->n_phy_clks, phy_drd->phy_clks); return 0; } @@ -846,7 +848,7 @@ static int exynos850_usbdrd_phy_exit(struct phy *phy) u32 reg; int ret; - ret = clk_prepare_enable(phy_drd->clk); + ret = clk_bulk_prepare_enable(phy_drd->n_phy_clks, phy_drd->phy_clks); if (ret) return ret; @@ -869,7 +871,7 @@ static int exynos850_usbdrd_phy_exit(struct phy *phy) reg &= ~CLKRST_LINK_SW_RST; writel(reg, regs_base + EXYNOS850_DRD_CLKRST); - clk_disable_unprepare(phy_drd->clk); + clk_bulk_disable_unprepare(phy_drd->n_phy_clks, phy_drd->phy_clks); return 0; } @@ -882,16 +884,29 @@ static const struct phy_ops exynos850_usbdrd_phy_ops = { .owner = THIS_MODULE, }; +static const char * const phy_clk_list[] = { + "phy", +}; + static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd) { unsigned long ref_rate; int ret; - phy_drd->clk = devm_clk_get(phy_drd->dev, "phy"); - if (IS_ERR(phy_drd->clk)) { - dev_err(phy_drd->dev, "Failed to get phy clock\n"); - return PTR_ERR(phy_drd->clk); - } + phy_drd->n_phy_clks = ARRAY_SIZE(phy_clk_list); + phy_drd->phy_clks = devm_kcalloc(phy_drd->dev, phy_drd->n_phy_clks, + sizeof(*phy_drd->phy_clks), + GFP_KERNEL); + if (!phy_drd->phy_clks) + return -ENOMEM; + + for (int i = 0; i < phy_drd->n_phy_clks; ++i) + phy_drd->phy_clks[i].id = phy_clk_list[i]; + + ret = devm_clk_bulk_get_optional(phy_drd->dev, phy_drd->n_phy_clks, + phy_drd->phy_clks); + if (ret < 0) + return ret; phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref"); if (IS_ERR(phy_drd->ref_clk)) { -- 2.44.0.769.g3c40516874-goog