Commit 9e405f87 authored by Kishon Vijay Abraham I's avatar Kishon Vijay Abraham I Committed by Vinod Koul
Browse files

phy: ti: j721e-wiz: Enable reference clock output in cmn_refclk_<p/m>



cmn_refclk_<p/m> lines in Torrent SERDES is used for 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.

Signed-off-by: default avatarKishon Vijay Abraham I <kishon@ti.com>
Link: https://lore.kernel.org/r/20210310120840.16447-6-kishon@ti.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 040cbe76
Loading
Loading
Loading
Loading
+89 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ enum wiz_clock_input {

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 pll0_refclk_mux_sel =
@@ -86,6 +87,7 @@ static const char * const output_clk_names[] = {
	[TI_WIZ_PLL0_REFCLK] = "pll0-refclk",
	[TI_WIZ_PLL1_REFCLK] = "pll1-refclk",
	[TI_WIZ_REFCLK_DIG] = "refclk-dig",
	[TI_WIZ_PHY_EN_REFCLK] = "phy-en-refclk",
};

static const struct reg_field p_enable[WIZ_MAX_LANES] = {
@@ -158,6 +160,14 @@ struct wiz_clk_div_sel {
	const char		*node_name;
};

struct wiz_phy_en_refclk {
	struct clk_hw		hw;
	struct regmap_field	*phy_en_refclk;
	struct clk_init_data	clk_data;
};

#define to_wiz_phy_en_refclk(_hw) container_of(_hw, struct wiz_phy_en_refclk, hw)

static const struct wiz_clk_mux_sel clk_mux_sel_16g[] = {
	{
		/*
@@ -237,6 +247,7 @@ struct wiz {
	unsigned int		clk_div_sel_num;
	struct regmap_field	*por_en;
	struct regmap_field	*phy_reset_n;
	struct regmap_field	*phy_en_refclk;
	struct regmap_field	*p_enable[WIZ_MAX_LANES];
	struct regmap_field	*p_align[WIZ_MAX_LANES];
	struct regmap_field	*p_raw_auto_start[WIZ_MAX_LANES];
@@ -469,6 +480,76 @@ static int wiz_regfield_init(struct wiz *wiz)
		return PTR_ERR(wiz->typec_ln10_swap);
	}

	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);
	}

	return 0;
}

static int wiz_phy_en_refclk_enable(struct clk_hw *hw)
{
	struct wiz_phy_en_refclk *wiz_phy_en_refclk = to_wiz_phy_en_refclk(hw);
	struct regmap_field *phy_en_refclk = wiz_phy_en_refclk->phy_en_refclk;

	regmap_field_write(phy_en_refclk, 1);

	return 0;
}

static void wiz_phy_en_refclk_disable(struct clk_hw *hw)
{
	struct wiz_phy_en_refclk *wiz_phy_en_refclk = to_wiz_phy_en_refclk(hw);
	struct regmap_field *phy_en_refclk = wiz_phy_en_refclk->phy_en_refclk;

	regmap_field_write(phy_en_refclk, 0);
}

static int wiz_phy_en_refclk_is_enabled(struct clk_hw *hw)
{
	struct wiz_phy_en_refclk *wiz_phy_en_refclk = to_wiz_phy_en_refclk(hw);
	struct regmap_field *phy_en_refclk = wiz_phy_en_refclk->phy_en_refclk;
	int val;

	regmap_field_read(phy_en_refclk, &val);

	return !!val;
}

static const struct clk_ops wiz_phy_en_refclk_ops = {
	.enable = wiz_phy_en_refclk_enable,
	.disable = wiz_phy_en_refclk_disable,
	.is_enabled = wiz_phy_en_refclk_is_enabled,
};

static int wiz_phy_en_refclk_register(struct wiz *wiz)
{
	struct wiz_phy_en_refclk *wiz_phy_en_refclk;
	struct device *dev = wiz->dev;
	struct clk_init_data *init;
	struct clk *clk;

	wiz_phy_en_refclk = devm_kzalloc(dev, sizeof(*wiz_phy_en_refclk), GFP_KERNEL);
	if (!wiz_phy_en_refclk)
		return -ENOMEM;

	init = &wiz_phy_en_refclk->clk_data;

	init->ops = &wiz_phy_en_refclk_ops;
	init->flags = 0;
	init->name = output_clk_names[TI_WIZ_PHY_EN_REFCLK];

	wiz_phy_en_refclk->phy_en_refclk = wiz->phy_en_refclk;
	wiz_phy_en_refclk->hw.init = init;

	clk = devm_clk_register(dev, &wiz_phy_en_refclk->hw);
	if (IS_ERR(clk))
		return PTR_ERR(clk);

	wiz->output_clks[TI_WIZ_PHY_EN_REFCLK] = clk;

	return 0;
}

@@ -724,6 +805,8 @@ static void wiz_clock_cleanup(struct wiz *wiz, struct device_node *node)
		of_clk_del_provider(clk_node);
		of_node_put(clk_node);
	}

	of_clk_del_provider(wiz->dev->of_node);
}

static int wiz_clock_register(struct wiz *wiz)
@@ -747,6 +830,12 @@ static int wiz_clock_register(struct wiz *wiz)
		}
	}

	ret = wiz_phy_en_refclk_register(wiz);
	if (ret) {
		dev_err(dev, "Failed to add phy-en-refclk\n");
		return ret;
	}

	wiz->clk_data.clks = wiz->output_clks;
	wiz->clk_data.clk_num = WIZ_MAX_OUTPUT_CLOCKS;
	ret = of_clk_add_provider(node, of_clk_src_onecell_get, &wiz->clk_data);