cmn_refclk_<p/m> lines in Torrent SERDES are used for an connecting
external reference clock. cmn_refclk_<p/m> can also be configured to
output the reference clock. In order to drive the refclk out from the
SERDES (Cadence Torrent), PHY_EN_REFCLK should be set in SERDES_RST of
WIZ. Model PHY_EN_REFCLK as a clock, so that platforms like AM642 EVM
can enable it.

Based on: https://lore.kernel.org/r/[email protected]

Signed-off-by: George McCollister <[email protected]>
---

 drivers/phy/ti/phy-j721e-wiz.c | 46 ++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index eaf68d18f3a1..466e2a5d0b50 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -75,6 +75,7 @@ enum wiz_typec_master_lane {
 
 static const struct reg_field por_en = REG_FIELD(WIZ_SERDES_CTRL, 31, 31);
 static const struct reg_field phy_reset_n = REG_FIELD(WIZ_SERDES_RST, 31, 31);
+static const struct reg_field phy_en_refclk = REG_FIELD(WIZ_SERDES_RST, 30, 
30);
 static const struct reg_field pll1_refclk_mux_sel =
                                        REG_FIELD(WIZ_SERDES_RST, 29, 29);
 static const struct reg_field pll1_refclk_mux_sel_2 =
@@ -534,9 +535,43 @@ static int wiz_clk_of_xlate(struct clk *clk, struct 
ofnode_phandle_args *args)
        return 0;
 }
 
+static int wiz_phy_en_refclk_enable(struct clk *clk)
+{
+       struct udevice *dev = clk->dev;
+       struct wiz_clk *priv = dev_get_priv(dev);
+       struct wiz *wiz = priv->wiz;
+       int id;
+
+       id = clk->id >> 10;
+       if (id != TI_WIZ_PHY_EN_REFCLK)
+               return 0;
+
+       regmap_field_write(wiz->phy_en_refclk, 1);
+
+       return 0;
+}
+
+static int wiz_phy_en_refclk_disable(struct clk *clk)
+{
+       struct udevice *dev = clk->dev;
+       struct wiz_clk *priv = dev_get_priv(dev);
+       struct wiz *wiz = priv->wiz;
+       int id;
+
+       id = clk->id >> 10;
+       if (id != TI_WIZ_PHY_EN_REFCLK)
+               return 0;
+
+       regmap_field_write(wiz->phy_en_refclk, 0);
+
+       return 0;
+}
+
 static const struct clk_ops wiz_clk_ops = {
        .set_parent = wiz_clk_set_parent,
        .of_xlate = wiz_clk_of_xlate,
+       .enable = wiz_phy_en_refclk_enable,
+       .disable = wiz_phy_en_refclk_disable,
 };
 
 int wiz_clk_probe(struct udevice *dev)
@@ -818,6 +853,12 @@ static int wiz_regfield_init(struct wiz *wiz)
                return PTR_ERR(wiz->phy_reset_n);
        }
 
+       wiz->phy_en_refclk = devm_regmap_field_alloc(dev, regmap, 
phy_en_refclk);
+       if (IS_ERR(wiz->phy_en_refclk)) {
+               dev_err(dev, "PHY_EN_REFCLK reg field init failed\n");
+               return PTR_ERR(wiz->phy_en_refclk);
+       }
+
        wiz->pma_cmn_refclk_int_mode =
                devm_regmap_field_alloc(dev, regmap, pma_cmn_refclk_int_mode);
        if (IS_ERR(wiz->pma_cmn_refclk_int_mode)) {
@@ -1042,6 +1083,11 @@ static int j721e_wiz_bind_clocks(struct wiz *wiz)
                }
        }
 
+       rc = device_bind(dev, wiz_clk_drv, "phy-en-refclk",
+                        NULL, dev_ofnode(dev), NULL);
+       if (rc)
+               dev_err(dev, "cannot bind driver for clock phy-en-refclk\n");
+
        return 0;
 }
 
-- 
2.51.2

Reply via email to