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: Roger Quadros <rogerq@kernel.org>
Link: https://lore.kernel.org/r/20220628122255.24265-7-rogerq@kernel.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Roger Quadros 2022-06-28 15:22:54 +03:00 committed by Vinod Koul
parent d5f2e7475f
commit edd473d429

View file

@ -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,