Skip to content

Commit 8a0eb8f

Browse files
athierry1vinodkoul
authored andcommitted
phy: qcom-snps-femto-v2: properly enable ref clock
The driver is not enabling the ref clock, which thus gets disabled by the clk_disable_unused() initcall. This leads to the dwc3 controller failing to initialize if probed after clk_disable_unused() is called, for instance when the driver is built as a module. To fix this, switch to the clk_bulk API to handle both cfg_ahb and ref clocks at the proper places. Note that the cfg_ahb clock is currently not used by any device tree instantiation of the PHY. Work needs to be done separately to fix this. Link: https://lore.kernel.org/linux-arm-msm/ZEqvy+khHeTkC2hf@fedora/ Fixes: 51e8114 ("phy: qcom-snps: Add SNPS USB PHY driver for QCOM based SOCs") Signed-off-by: Adrien Thierry <athierry@redhat.com> Link: https://lore.kernel.org/r/20230629144542.14906-3-athierry@redhat.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 45d89a3 commit 8a0eb8f

File tree

1 file changed

+48
-15
lines changed

1 file changed

+48
-15
lines changed

drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -110,23 +110,27 @@ struct phy_override_seq {
110110
/**
111111
* struct qcom_snps_hsphy - snps hs phy attributes
112112
*
113+
* @dev: device structure
114+
*
113115
* @phy: generic phy
114116
* @base: iomapped memory space for snps hs phy
115117
*
116-
* @cfg_ahb_clk: AHB2PHY interface clock
117-
* @ref_clk: phy reference clock
118+
* @num_clks: number of clocks
119+
* @clks: array of clocks
118120
* @phy_reset: phy reset control
119121
* @vregs: regulator supplies bulk data
120122
* @phy_initialized: if PHY has been initialized correctly
121123
* @mode: contains the current mode the PHY is in
122124
* @update_seq_cfg: tuning parameters for phy init
123125
*/
124126
struct qcom_snps_hsphy {
127+
struct device *dev;
128+
125129
struct phy *phy;
126130
void __iomem *base;
127131

128-
struct clk *cfg_ahb_clk;
129-
struct clk *ref_clk;
132+
int num_clks;
133+
struct clk_bulk_data *clks;
130134
struct reset_control *phy_reset;
131135
struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
132136

@@ -135,6 +139,34 @@ struct qcom_snps_hsphy {
135139
struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS];
136140
};
137141

142+
static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy)
143+
{
144+
struct device *dev = hsphy->dev;
145+
146+
hsphy->num_clks = 2;
147+
hsphy->clks = devm_kcalloc(dev, hsphy->num_clks, sizeof(*hsphy->clks), GFP_KERNEL);
148+
if (!hsphy->clks)
149+
return -ENOMEM;
150+
151+
/*
152+
* TODO: Currently no device tree instantiation of the PHY is using the clock.
153+
* This needs to be fixed in order for this code to be able to use devm_clk_bulk_get().
154+
*/
155+
hsphy->clks[0].id = "cfg_ahb";
156+
hsphy->clks[0].clk = devm_clk_get_optional(dev, "cfg_ahb");
157+
if (IS_ERR(hsphy->clks[0].clk))
158+
return dev_err_probe(dev, PTR_ERR(hsphy->clks[0].clk),
159+
"failed to get cfg_ahb clk\n");
160+
161+
hsphy->clks[1].id = "ref";
162+
hsphy->clks[1].clk = devm_clk_get(dev, "ref");
163+
if (IS_ERR(hsphy->clks[1].clk))
164+
return dev_err_probe(dev, PTR_ERR(hsphy->clks[1].clk),
165+
"failed to get ref clk\n");
166+
167+
return 0;
168+
}
169+
138170
static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
139171
u32 mask, u32 val)
140172
{
@@ -365,24 +397,24 @@ static int qcom_snps_hsphy_init(struct phy *phy)
365397
if (ret)
366398
return ret;
367399

368-
ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
400+
ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks);
369401
if (ret) {
370-
dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
402+
dev_err(&phy->dev, "failed to enable clocks, %d\n", ret);
371403
goto poweroff_phy;
372404
}
373405

374406
ret = reset_control_assert(hsphy->phy_reset);
375407
if (ret) {
376408
dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
377-
goto disable_ahb_clk;
409+
goto disable_clks;
378410
}
379411

380412
usleep_range(100, 150);
381413

382414
ret = reset_control_deassert(hsphy->phy_reset);
383415
if (ret) {
384416
dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
385-
goto disable_ahb_clk;
417+
goto disable_clks;
386418
}
387419

388420
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
@@ -439,8 +471,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
439471

440472
return 0;
441473

442-
disable_ahb_clk:
443-
clk_disable_unprepare(hsphy->cfg_ahb_clk);
474+
disable_clks:
475+
clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
444476
poweroff_phy:
445477
regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
446478

@@ -452,7 +484,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
452484
struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
453485

454486
reset_control_assert(hsphy->phy_reset);
455-
clk_disable_unprepare(hsphy->cfg_ahb_clk);
487+
clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
456488
regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
457489
hsphy->phy_initialized = false;
458490

@@ -545,14 +577,15 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
545577
if (!hsphy)
546578
return -ENOMEM;
547579

580+
hsphy->dev = dev;
581+
548582
hsphy->base = devm_platform_ioremap_resource(pdev, 0);
549583
if (IS_ERR(hsphy->base))
550584
return PTR_ERR(hsphy->base);
551585

552-
hsphy->ref_clk = devm_clk_get(dev, "ref");
553-
if (IS_ERR(hsphy->ref_clk))
554-
return dev_err_probe(dev, PTR_ERR(hsphy->ref_clk),
555-
"failed to get ref clk\n");
586+
ret = qcom_snps_hsphy_clk_init(hsphy);
587+
if (ret)
588+
return dev_err_probe(dev, ret, "failed to initialize clocks\n");
556589

557590
hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
558591
if (IS_ERR(hsphy->phy_reset)) {

0 commit comments

Comments
 (0)