Commit 53c8621b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'phy-fixes-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy

Pull phy fixes from Vinod Koul:

 - Out of bound fix for hisilicon phy

 - Qualcomm synopsis femto phy for keeping clock enabled during suspend
   and enabling ref clocks

 - Mediatek driver fixes for upper limit test and error code

* tag 'phy-fixes-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy:
  phy: hisilicon: Fix an out of bounds check in hisi_inno_phy_probe()
  phy: qcom-snps-femto-v2: use qcom_snps_hsphy_suspend/resume error code
  phy: qcom-snps-femto-v2: properly enable ref clock
  phy: qcom-snps-femto-v2: keep cfg_ahb_clk enabled during runtime suspend
  phy: mediatek: hdmi: mt8195: fix prediv bad upper limit test
  phy: phy-mtk-dp: Fix an error code in probe()
parents 64de76ce 13c088cf
...@@ -184,7 +184,7 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) ...@@ -184,7 +184,7 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
phy_set_drvdata(phy, &priv->ports[i]); phy_set_drvdata(phy, &priv->ports[i]);
i++; i++;
if (i > INNO_PHY_PORT_NUM) { if (i >= INNO_PHY_PORT_NUM) {
dev_warn(dev, "Support %d ports in maximum\n", i); dev_warn(dev, "Support %d ports in maximum\n", i);
of_node_put(child); of_node_put(child);
break; break;
......
...@@ -169,7 +169,7 @@ static int mtk_dp_phy_probe(struct platform_device *pdev) ...@@ -169,7 +169,7 @@ static int mtk_dp_phy_probe(struct platform_device *pdev)
regs = *(struct regmap **)dev->platform_data; regs = *(struct regmap **)dev->platform_data;
if (!regs) if (!regs)
return dev_err_probe(dev, EINVAL, return dev_err_probe(dev, -EINVAL,
"No data passed, requires struct regmap**\n"); "No data passed, requires struct regmap**\n");
dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL); dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
......
...@@ -253,7 +253,7 @@ static int mtk_hdmi_pll_calc(struct mtk_hdmi_phy *hdmi_phy, struct clk_hw *hw, ...@@ -253,7 +253,7 @@ static int mtk_hdmi_pll_calc(struct mtk_hdmi_phy *hdmi_phy, struct clk_hw *hw,
for (i = 0; i < ARRAY_SIZE(txpredivs); i++) { for (i = 0; i < ARRAY_SIZE(txpredivs); i++) {
ns_hdmipll_ck = 5 * tmds_clk * txposdiv * txpredivs[i]; ns_hdmipll_ck = 5 * tmds_clk * txposdiv * txpredivs[i];
if (ns_hdmipll_ck >= 5 * GIGA && if (ns_hdmipll_ck >= 5 * GIGA &&
ns_hdmipll_ck <= 1 * GIGA) ns_hdmipll_ck <= 12 * GIGA)
break; break;
} }
if (i == (ARRAY_SIZE(txpredivs) - 1) && if (i == (ARRAY_SIZE(txpredivs) - 1) &&
......
...@@ -110,11 +110,13 @@ struct phy_override_seq { ...@@ -110,11 +110,13 @@ struct phy_override_seq {
/** /**
* struct qcom_snps_hsphy - snps hs phy attributes * struct qcom_snps_hsphy - snps hs phy attributes
* *
* @dev: device structure
*
* @phy: generic phy * @phy: generic phy
* @base: iomapped memory space for snps hs phy * @base: iomapped memory space for snps hs phy
* *
* @cfg_ahb_clk: AHB2PHY interface clock * @num_clks: number of clocks
* @ref_clk: phy reference clock * @clks: array of clocks
* @phy_reset: phy reset control * @phy_reset: phy reset control
* @vregs: regulator supplies bulk data * @vregs: regulator supplies bulk data
* @phy_initialized: if PHY has been initialized correctly * @phy_initialized: if PHY has been initialized correctly
...@@ -122,11 +124,13 @@ struct phy_override_seq { ...@@ -122,11 +124,13 @@ struct phy_override_seq {
* @update_seq_cfg: tuning parameters for phy init * @update_seq_cfg: tuning parameters for phy init
*/ */
struct qcom_snps_hsphy { struct qcom_snps_hsphy {
struct device *dev;
struct phy *phy; struct phy *phy;
void __iomem *base; void __iomem *base;
struct clk *cfg_ahb_clk; int num_clks;
struct clk *ref_clk; struct clk_bulk_data *clks;
struct reset_control *phy_reset; struct reset_control *phy_reset;
struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS]; struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
...@@ -135,6 +139,34 @@ struct qcom_snps_hsphy { ...@@ -135,6 +139,34 @@ struct qcom_snps_hsphy {
struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS]; 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, static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
u32 mask, u32 val) u32 mask, u32 val)
{ {
...@@ -165,22 +197,13 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy) ...@@ -165,22 +197,13 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
0, USB2_AUTO_RESUME); 0, USB2_AUTO_RESUME);
} }
clk_disable_unprepare(hsphy->cfg_ahb_clk);
return 0; return 0;
} }
static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy) static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
{ {
int ret;
dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n"); 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; return 0;
} }
...@@ -191,8 +214,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev) ...@@ -191,8 +214,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev)
if (!hsphy->phy_initialized) if (!hsphy->phy_initialized)
return 0; return 0;
qcom_snps_hsphy_suspend(hsphy); return qcom_snps_hsphy_suspend(hsphy);
return 0;
} }
static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev) static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
...@@ -202,8 +224,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev) ...@@ -202,8 +224,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
if (!hsphy->phy_initialized) if (!hsphy->phy_initialized)
return 0; return 0;
qcom_snps_hsphy_resume(hsphy); return qcom_snps_hsphy_resume(hsphy);
return 0;
} }
static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode, static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
...@@ -374,16 +395,16 @@ static int qcom_snps_hsphy_init(struct phy *phy) ...@@ -374,16 +395,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
if (ret) if (ret)
return ret; return ret;
ret = clk_prepare_enable(hsphy->cfg_ahb_clk); ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks);
if (ret) { 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; goto poweroff_phy;
} }
ret = reset_control_assert(hsphy->phy_reset); ret = reset_control_assert(hsphy->phy_reset);
if (ret) { if (ret) {
dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret); dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
goto disable_ahb_clk; goto disable_clks;
} }
usleep_range(100, 150); usleep_range(100, 150);
...@@ -391,7 +412,7 @@ static int qcom_snps_hsphy_init(struct phy *phy) ...@@ -391,7 +412,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
ret = reset_control_deassert(hsphy->phy_reset); ret = reset_control_deassert(hsphy->phy_reset);
if (ret) { if (ret) {
dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", 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, qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
...@@ -448,8 +469,8 @@ static int qcom_snps_hsphy_init(struct phy *phy) ...@@ -448,8 +469,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
return 0; return 0;
disable_ahb_clk: disable_clks:
clk_disable_unprepare(hsphy->cfg_ahb_clk); clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
poweroff_phy: poweroff_phy:
regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs); regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
...@@ -461,7 +482,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy) ...@@ -461,7 +482,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy); struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
reset_control_assert(hsphy->phy_reset); 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); regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
hsphy->phy_initialized = false; hsphy->phy_initialized = false;
...@@ -554,14 +575,15 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev) ...@@ -554,14 +575,15 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
if (!hsphy) if (!hsphy)
return -ENOMEM; return -ENOMEM;
hsphy->dev = dev;
hsphy->base = devm_platform_ioremap_resource(pdev, 0); hsphy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hsphy->base)) if (IS_ERR(hsphy->base))
return PTR_ERR(hsphy->base); return PTR_ERR(hsphy->base);
hsphy->ref_clk = devm_clk_get(dev, "ref"); ret = qcom_snps_hsphy_clk_init(hsphy);
if (IS_ERR(hsphy->ref_clk)) if (ret)
return dev_err_probe(dev, PTR_ERR(hsphy->ref_clk), return dev_err_probe(dev, ret, "failed to initialize clocks\n");
"failed to get ref clk\n");
hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(hsphy->phy_reset)) { if (IS_ERR(hsphy->phy_reset)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment