Commit edd473d4 authored by Roger Quadros's avatar Roger Quadros Committed by Vinod Koul
Browse files

phy: ti: phy-j721e-wiz: add support for j7200-wiz-10g



j7200-wiz-10g supports 2 reference clocks. However, the
control bits for these clocks is in a separate register that
sits in the System Control register space. Handle that register.

Signed-off-by: default avatarRoger Quadros <rogerq@kernel.org>
Link: https://lore.kernel.org/r/20220628122255.24265-7-rogerq@kernel.org


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent d5f2e747
Loading
Loading
Loading
Loading
+129 −9
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/gpio/consumer.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mfd/syscon.h>
#include <linux/mux/consumer.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
@@ -23,6 +24,10 @@
#include <linux/regmap.h>
#include <linux/reset-controller.h>

/* SCM offsets */
#define SERDES_SUP_CTRL		0x4400

/* SERDES offsets */
#define WIZ_SERDES_CTRL		0x404
#define WIZ_SERDES_TOP_CTRL	0x408
#define WIZ_SERDES_RST		0x40c
@@ -85,6 +90,18 @@ static const struct reg_field pma_cmn_refclk_dig_div =
					REG_FIELD(WIZ_SERDES_TOP_CTRL, 26, 27);
static const struct reg_field pma_cmn_refclk1_dig_div =
					REG_FIELD(WIZ_SERDES_TOP_CTRL, 24, 25);

static const struct reg_field sup_pll0_refclk_mux_sel =
					REG_FIELD(SERDES_SUP_CTRL, 0, 1);
static const struct reg_field sup_pll1_refclk_mux_sel =
					REG_FIELD(SERDES_SUP_CTRL, 2, 3);
static const struct reg_field sup_pma_cmn_refclk1_int_mode =
					REG_FIELD(SERDES_SUP_CTRL, 4, 5);
static const struct reg_field sup_refclk_dig_sel_10g =
					REG_FIELD(SERDES_SUP_CTRL, 6, 7);
static const struct reg_field sup_legacy_clk_override =
					REG_FIELD(SERDES_SUP_CTRL, 8, 8);

static const char * const output_clk_names[] = {
	[TI_WIZ_PLL0_REFCLK] = "pll0-refclk",
	[TI_WIZ_PLL1_REFCLK] = "pll1-refclk",
@@ -248,6 +265,27 @@ static const struct wiz_clk_mux_sel clk_mux_sel_10g[] = {
	},
};

static const struct wiz_clk_mux_sel clk_mux_sel_10g_2_refclk[] = {
	{
		.num_parents = 3,
		.parents = { WIZ_CORE_REFCLK, WIZ_CORE_REFCLK1, WIZ_EXT_REFCLK },
		.table = { 2, 3, 0 },
		.node_name = "pll0-refclk",
	},
	{
		.num_parents = 3,
		.parents = { WIZ_CORE_REFCLK, WIZ_CORE_REFCLK1, WIZ_EXT_REFCLK },
		.table = { 2, 3, 0 },
		.node_name = "pll1-refclk",
	},
	{
		.num_parents = 3,
		.parents = { WIZ_CORE_REFCLK, WIZ_CORE_REFCLK1, WIZ_EXT_REFCLK },
		.table = { 2, 3, 0 },
		.node_name = "refclk-dig",
	},
};

static const struct clk_div_table clk_div_table[] = {
	{ .val = 0, .div = 1, },
	{ .val = 1, .div = 2, },
@@ -269,14 +307,18 @@ static const struct wiz_clk_div_sel clk_div_sel[] = {

enum wiz_type {
	J721E_WIZ_16G,
	J721E_WIZ_10G,
	J721E_WIZ_10G,	/* Also for J7200 SR1.0 */
	AM64_WIZ_10G,
	J7200_WIZ_10G,  /* J7200 SR2.0 */
};

struct wiz_data {
	enum wiz_type type;
	const struct reg_field *pll0_refclk_mux_sel;
	const struct reg_field *pll1_refclk_mux_sel;
	const struct reg_field *refclk_dig_sel;
	const struct reg_field *pma_cmn_refclk1_dig_div;
	const struct reg_field *pma_cmn_refclk1_int_mode;
	const struct wiz_clk_mux_sel *clk_mux_sel;
	unsigned int clk_div_sel_num;
};
@@ -286,6 +328,7 @@ struct wiz_data {

struct wiz {
	struct regmap		*regmap;
	struct regmap		*scm_regmap;
	enum wiz_type		type;
	const struct wiz_clk_mux_sel *clk_mux_sel;
	const struct wiz_clk_div_sel *clk_div_sel;
@@ -304,12 +347,14 @@ struct wiz {
	struct regmap_field	*p0_rxfclk_sel[WIZ_MAX_LANES];
	struct regmap_field	*p0_refclk_sel[WIZ_MAX_LANES];
	struct regmap_field	*pma_cmn_refclk_int_mode;
	struct regmap_field	*pma_cmn_refclk1_int_mode;
	struct regmap_field	*pma_cmn_refclk_mode;
	struct regmap_field	*pma_cmn_refclk_dig_div;
	struct regmap_field	*pma_cmn_refclk1_dig_div;
	struct regmap_field	*mux_sel_field[WIZ_MUX_NUM_CLOCKS];
	struct regmap_field	*div_sel_field[WIZ_DIV_NUM_CLOCKS_16G];
	struct regmap_field	*typec_ln10_swap;
	struct regmap_field	*sup_legacy_clk_override;

	struct device		*dev;
	u32			num_lanes;
@@ -448,6 +493,7 @@ static int wiz_init(struct wiz *wiz)
static int wiz_regfield_init(struct wiz *wiz)
{
	struct regmap *regmap = wiz->regmap;
	struct regmap *scm_regmap = wiz->regmap; /* updated later to scm_regmap if applicable */
	int num_lanes = wiz->num_lanes;
	struct device *dev = wiz->dev;
	const struct wiz_data *data = wiz->data;
@@ -497,27 +543,46 @@ static int wiz_regfield_init(struct wiz *wiz)
		}
	}

	if (wiz->scm_regmap) {
		scm_regmap = wiz->scm_regmap;
		wiz->sup_legacy_clk_override =
			devm_regmap_field_alloc(dev, scm_regmap, sup_legacy_clk_override);
		if (IS_ERR(wiz->sup_legacy_clk_override)) {
			dev_err(dev, "SUP_LEGACY_CLK_OVERRIDE reg field init failed\n");
			return PTR_ERR(wiz->sup_legacy_clk_override);
		}
	}

	wiz->mux_sel_field[PLL0_REFCLK] =
		devm_regmap_field_alloc(dev, regmap, pll0_refclk_mux_sel);
		devm_regmap_field_alloc(dev, scm_regmap, *data->pll0_refclk_mux_sel);
	if (IS_ERR(wiz->mux_sel_field[PLL0_REFCLK])) {
		dev_err(dev, "PLL0_REFCLK_SEL reg field init failed\n");
		return PTR_ERR(wiz->mux_sel_field[PLL0_REFCLK]);
	}

	wiz->mux_sel_field[PLL1_REFCLK] =
		devm_regmap_field_alloc(dev, regmap, pll1_refclk_mux_sel);
		devm_regmap_field_alloc(dev, scm_regmap, *data->pll1_refclk_mux_sel);
	if (IS_ERR(wiz->mux_sel_field[PLL1_REFCLK])) {
		dev_err(dev, "PLL1_REFCLK_SEL reg field init failed\n");
		return PTR_ERR(wiz->mux_sel_field[PLL1_REFCLK]);
	}

	wiz->mux_sel_field[REFCLK_DIG] = devm_regmap_field_alloc(dev, regmap,
	wiz->mux_sel_field[REFCLK_DIG] = devm_regmap_field_alloc(dev, scm_regmap,
								 *data->refclk_dig_sel);
	if (IS_ERR(wiz->mux_sel_field[REFCLK_DIG])) {
		dev_err(dev, "REFCLK_DIG_SEL reg field init failed\n");
		return PTR_ERR(wiz->mux_sel_field[REFCLK_DIG]);
	}

	if (data->pma_cmn_refclk1_int_mode) {
		wiz->pma_cmn_refclk1_int_mode =
			devm_regmap_field_alloc(dev, scm_regmap, *data->pma_cmn_refclk1_int_mode);
		if (IS_ERR(wiz->pma_cmn_refclk1_int_mode)) {
			dev_err(dev, "PMA_CMN_REFCLK1_INT_MODE reg field init failed\n");
			return PTR_ERR(wiz->pma_cmn_refclk1_int_mode);
		}
	}

	for (i = 0; i < num_lanes; i++) {
		wiz->p_enable[i] = devm_regmap_field_alloc(dev, regmap,
							   p_enable[i]);
@@ -906,9 +971,13 @@ static void wiz_clock_cleanup(struct wiz *wiz, struct device_node *node)
	struct device_node *clk_node;
	int i;

	if (wiz->type == AM64_WIZ_10G) {
	switch (wiz->type) {
	case AM64_WIZ_10G:
	case J7200_WIZ_10G:
		of_clk_del_provider(dev->of_node);
		return;
	default:
		break;
	}

	for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++) {
@@ -935,9 +1004,6 @@ static int wiz_clock_register(struct wiz *wiz)
	int ret;
	int i;

	if (wiz->type != AM64_WIZ_10G)
		return 0;

	clk_index = TI_WIZ_PLL0_REFCLK;
	for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++, clk_index++) {
		ret = wiz_mux_clk_register(wiz, wiz->mux_sel_field[i], &clk_mux_sel[i], clk_index);
@@ -987,6 +1053,22 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
	else
		regmap_field_write(wiz->pma_cmn_refclk_int_mode, 0x3);

	if (wiz->data->pma_cmn_refclk1_int_mode) {
		clk = devm_clk_get(dev, "core_ref1_clk");
		if (IS_ERR(clk)) {
			dev_err(dev, "core_ref1_clk clock not found\n");
			ret = PTR_ERR(clk);
			return ret;
		}
		wiz->input_clks[WIZ_CORE_REFCLK1] = clk;

		rate = clk_get_rate(clk);
		if (rate >= 100000000)
			regmap_field_write(wiz->pma_cmn_refclk1_int_mode, 0x1);
		else
			regmap_field_write(wiz->pma_cmn_refclk1_int_mode, 0x3);
	}

	clk = devm_clk_get(dev, "ext_ref_clk");
	if (IS_ERR(clk)) {
		dev_err(dev, "ext_ref_clk clock not found\n");
@@ -1001,11 +1083,15 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
	else
		regmap_field_write(wiz->pma_cmn_refclk_mode, 0x2);

	if (wiz->type == AM64_WIZ_10G) {
	switch (wiz->type) {
	case AM64_WIZ_10G:
	case J7200_WIZ_10G:
		ret = wiz_clock_register(wiz);
		if (ret)
			dev_err(dev, "Failed to register wiz clocks\n");
		return ret;
	default:
		break;
	}

	for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++) {
@@ -1081,6 +1167,7 @@ static int wiz_phy_fullrt_div(struct wiz *wiz, int lane)
			return regmap_field_write(wiz->p0_fullrt_div[lane], 0x1);
		break;
	case J721E_WIZ_10G:
	case J7200_WIZ_10G:
		if (wiz->lane_phy_type[lane] == PHY_TYPE_SGMII)
			return regmap_field_write(wiz->p0_fullrt_div[lane], 0x2);
		break;
@@ -1139,6 +1226,8 @@ static const struct regmap_config wiz_regmap_config = {

static struct wiz_data j721e_16g_data = {
	.type = J721E_WIZ_16G,
	.pll0_refclk_mux_sel = &pll0_refclk_mux_sel,
	.pll1_refclk_mux_sel = &pll1_refclk_mux_sel,
	.refclk_dig_sel = &refclk_dig_sel_16g,
	.pma_cmn_refclk1_dig_div = &pma_cmn_refclk1_dig_div,
	.clk_mux_sel = clk_mux_sel_16g,
@@ -1147,6 +1236,8 @@ static struct wiz_data j721e_16g_data = {

static struct wiz_data j721e_10g_data = {
	.type = J721E_WIZ_10G,
	.pll0_refclk_mux_sel = &pll0_refclk_mux_sel,
	.pll1_refclk_mux_sel = &pll1_refclk_mux_sel,
	.refclk_dig_sel = &refclk_dig_sel_10g,
	.clk_mux_sel = clk_mux_sel_10g,
	.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
@@ -1154,11 +1245,23 @@ static struct wiz_data j721e_10g_data = {

static struct wiz_data am64_10g_data = {
	.type = AM64_WIZ_10G,
	.pll0_refclk_mux_sel = &pll0_refclk_mux_sel,
	.pll1_refclk_mux_sel = &pll1_refclk_mux_sel,
	.refclk_dig_sel = &refclk_dig_sel_10g,
	.clk_mux_sel = clk_mux_sel_10g,
	.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
};

static struct wiz_data j7200_pg2_10g_data = {
	.type = J7200_WIZ_10G,
	.pll0_refclk_mux_sel = &sup_pll0_refclk_mux_sel,
	.pll1_refclk_mux_sel = &sup_pll1_refclk_mux_sel,
	.refclk_dig_sel = &sup_refclk_dig_sel_10g,
	.pma_cmn_refclk1_int_mode = &sup_pma_cmn_refclk1_int_mode,
	.clk_mux_sel = clk_mux_sel_10g_2_refclk,
	.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
};

static const struct of_device_id wiz_id_table[] = {
	{
		.compatible = "ti,j721e-wiz-16g", .data = &j721e_16g_data,
@@ -1169,6 +1272,9 @@ static const struct of_device_id wiz_id_table[] = {
	{
		.compatible = "ti,am64-wiz-10g", .data = &am64_10g_data,
	},
	{
		.compatible = "ti,j7200-wiz-10g", .data = &j7200_pg2_10g_data,
	},
	{}
};
MODULE_DEVICE_TABLE(of, wiz_id_table);
@@ -1266,6 +1372,16 @@ static int wiz_probe(struct platform_device *pdev)
		goto err_addr_to_resource;
	}

	wiz->scm_regmap = syscon_regmap_lookup_by_phandle(node, "ti,scm");
	if (IS_ERR(wiz->scm_regmap)) {
		if (wiz->type == J7200_WIZ_10G) {
			dev_err(dev, "Couldn't get ti,scm regmap\n");
			return -ENODEV;
		}

		wiz->scm_regmap = NULL;
	}

	ret = of_property_read_u32(node, "num-lanes", &num_lanes);
	if (ret) {
		dev_err(dev, "Failed to read num-lanes property\n");
@@ -1327,6 +1443,10 @@ static int wiz_probe(struct platform_device *pdev)
		goto err_addr_to_resource;
	}

	/* Enable supplemental Control override if available */
	if (wiz->scm_regmap)
		regmap_field_write(wiz->sup_legacy_clk_override, 1);

	phy_reset_dev = &wiz->wiz_phy_reset_dev;
	phy_reset_dev->dev = dev;
	phy_reset_dev->ops = &wiz_phy_reset_ops,