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

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.orgSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent d5f2e747
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mfd/syscon.h>
#include <linux/mux/consumer.h> #include <linux/mux/consumer.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
...@@ -23,6 +24,10 @@ ...@@ -23,6 +24,10 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/reset-controller.h> #include <linux/reset-controller.h>
/* SCM offsets */
#define SERDES_SUP_CTRL 0x4400
/* SERDES offsets */
#define WIZ_SERDES_CTRL 0x404 #define WIZ_SERDES_CTRL 0x404
#define WIZ_SERDES_TOP_CTRL 0x408 #define WIZ_SERDES_TOP_CTRL 0x408
#define WIZ_SERDES_RST 0x40c #define WIZ_SERDES_RST 0x40c
...@@ -85,6 +90,18 @@ static const struct reg_field pma_cmn_refclk_dig_div = ...@@ -85,6 +90,18 @@ static const struct reg_field pma_cmn_refclk_dig_div =
REG_FIELD(WIZ_SERDES_TOP_CTRL, 26, 27); REG_FIELD(WIZ_SERDES_TOP_CTRL, 26, 27);
static const struct reg_field pma_cmn_refclk1_dig_div = static const struct reg_field pma_cmn_refclk1_dig_div =
REG_FIELD(WIZ_SERDES_TOP_CTRL, 24, 25); 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[] = { static const char * const output_clk_names[] = {
[TI_WIZ_PLL0_REFCLK] = "pll0-refclk", [TI_WIZ_PLL0_REFCLK] = "pll0-refclk",
[TI_WIZ_PLL1_REFCLK] = "pll1-refclk", [TI_WIZ_PLL1_REFCLK] = "pll1-refclk",
...@@ -248,6 +265,27 @@ static const struct wiz_clk_mux_sel clk_mux_sel_10g[] = { ...@@ -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[] = { static const struct clk_div_table clk_div_table[] = {
{ .val = 0, .div = 1, }, { .val = 0, .div = 1, },
{ .val = 1, .div = 2, }, { .val = 1, .div = 2, },
...@@ -269,14 +307,18 @@ static const struct wiz_clk_div_sel clk_div_sel[] = { ...@@ -269,14 +307,18 @@ static const struct wiz_clk_div_sel clk_div_sel[] = {
enum wiz_type { enum wiz_type {
J721E_WIZ_16G, J721E_WIZ_16G,
J721E_WIZ_10G, J721E_WIZ_10G, /* Also for J7200 SR1.0 */
AM64_WIZ_10G, AM64_WIZ_10G,
J7200_WIZ_10G, /* J7200 SR2.0 */
}; };
struct wiz_data { struct wiz_data {
enum wiz_type type; 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 *refclk_dig_sel;
const struct reg_field *pma_cmn_refclk1_dig_div; 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; const struct wiz_clk_mux_sel *clk_mux_sel;
unsigned int clk_div_sel_num; unsigned int clk_div_sel_num;
}; };
...@@ -286,6 +328,7 @@ struct wiz_data { ...@@ -286,6 +328,7 @@ struct wiz_data {
struct wiz { struct wiz {
struct regmap *regmap; struct regmap *regmap;
struct regmap *scm_regmap;
enum wiz_type type; enum wiz_type type;
const struct wiz_clk_mux_sel *clk_mux_sel; const struct wiz_clk_mux_sel *clk_mux_sel;
const struct wiz_clk_div_sel *clk_div_sel; const struct wiz_clk_div_sel *clk_div_sel;
...@@ -304,12 +347,14 @@ struct wiz { ...@@ -304,12 +347,14 @@ struct wiz {
struct regmap_field *p0_rxfclk_sel[WIZ_MAX_LANES]; struct regmap_field *p0_rxfclk_sel[WIZ_MAX_LANES];
struct regmap_field *p0_refclk_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_refclk_int_mode;
struct regmap_field *pma_cmn_refclk1_int_mode;
struct regmap_field *pma_cmn_refclk_mode; struct regmap_field *pma_cmn_refclk_mode;
struct regmap_field *pma_cmn_refclk_dig_div; struct regmap_field *pma_cmn_refclk_dig_div;
struct regmap_field *pma_cmn_refclk1_dig_div; struct regmap_field *pma_cmn_refclk1_dig_div;
struct regmap_field *mux_sel_field[WIZ_MUX_NUM_CLOCKS]; struct regmap_field *mux_sel_field[WIZ_MUX_NUM_CLOCKS];
struct regmap_field *div_sel_field[WIZ_DIV_NUM_CLOCKS_16G]; struct regmap_field *div_sel_field[WIZ_DIV_NUM_CLOCKS_16G];
struct regmap_field *typec_ln10_swap; struct regmap_field *typec_ln10_swap;
struct regmap_field *sup_legacy_clk_override;
struct device *dev; struct device *dev;
u32 num_lanes; u32 num_lanes;
...@@ -448,6 +493,7 @@ static int wiz_init(struct wiz *wiz) ...@@ -448,6 +493,7 @@ static int wiz_init(struct wiz *wiz)
static int wiz_regfield_init(struct wiz *wiz) static int wiz_regfield_init(struct wiz *wiz)
{ {
struct regmap *regmap = wiz->regmap; struct regmap *regmap = wiz->regmap;
struct regmap *scm_regmap = wiz->regmap; /* updated later to scm_regmap if applicable */
int num_lanes = wiz->num_lanes; int num_lanes = wiz->num_lanes;
struct device *dev = wiz->dev; struct device *dev = wiz->dev;
const struct wiz_data *data = wiz->data; const struct wiz_data *data = wiz->data;
...@@ -497,27 +543,46 @@ static int wiz_regfield_init(struct wiz *wiz) ...@@ -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] = 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])) { if (IS_ERR(wiz->mux_sel_field[PLL0_REFCLK])) {
dev_err(dev, "PLL0_REFCLK_SEL reg field init failed\n"); dev_err(dev, "PLL0_REFCLK_SEL reg field init failed\n");
return PTR_ERR(wiz->mux_sel_field[PLL0_REFCLK]); return PTR_ERR(wiz->mux_sel_field[PLL0_REFCLK]);
} }
wiz->mux_sel_field[PLL1_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])) { if (IS_ERR(wiz->mux_sel_field[PLL1_REFCLK])) {
dev_err(dev, "PLL1_REFCLK_SEL reg field init failed\n"); dev_err(dev, "PLL1_REFCLK_SEL reg field init failed\n");
return PTR_ERR(wiz->mux_sel_field[PLL1_REFCLK]); 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); *data->refclk_dig_sel);
if (IS_ERR(wiz->mux_sel_field[REFCLK_DIG])) { if (IS_ERR(wiz->mux_sel_field[REFCLK_DIG])) {
dev_err(dev, "REFCLK_DIG_SEL reg field init failed\n"); dev_err(dev, "REFCLK_DIG_SEL reg field init failed\n");
return PTR_ERR(wiz->mux_sel_field[REFCLK_DIG]); 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++) { for (i = 0; i < num_lanes; i++) {
wiz->p_enable[i] = devm_regmap_field_alloc(dev, regmap, wiz->p_enable[i] = devm_regmap_field_alloc(dev, regmap,
p_enable[i]); p_enable[i]);
...@@ -906,9 +971,13 @@ static void wiz_clock_cleanup(struct wiz *wiz, struct device_node *node) ...@@ -906,9 +971,13 @@ static void wiz_clock_cleanup(struct wiz *wiz, struct device_node *node)
struct device_node *clk_node; struct device_node *clk_node;
int i; 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); of_clk_del_provider(dev->of_node);
return; return;
default:
break;
} }
for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++) { for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++) {
...@@ -935,9 +1004,6 @@ static int wiz_clock_register(struct wiz *wiz) ...@@ -935,9 +1004,6 @@ static int wiz_clock_register(struct wiz *wiz)
int ret; int ret;
int i; int i;
if (wiz->type != AM64_WIZ_10G)
return 0;
clk_index = TI_WIZ_PLL0_REFCLK; clk_index = TI_WIZ_PLL0_REFCLK;
for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++, clk_index++) { 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); 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) ...@@ -987,6 +1053,22 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
else else
regmap_field_write(wiz->pma_cmn_refclk_int_mode, 0x3); 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"); clk = devm_clk_get(dev, "ext_ref_clk");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(dev, "ext_ref_clk clock not found\n"); 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) ...@@ -1001,11 +1083,15 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
else else
regmap_field_write(wiz->pma_cmn_refclk_mode, 0x2); 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); ret = wiz_clock_register(wiz);
if (ret) if (ret)
dev_err(dev, "Failed to register wiz clocks\n"); dev_err(dev, "Failed to register wiz clocks\n");
return ret; return ret;
default:
break;
} }
for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++) { for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++) {
...@@ -1081,6 +1167,7 @@ static int wiz_phy_fullrt_div(struct wiz *wiz, int lane) ...@@ -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); return regmap_field_write(wiz->p0_fullrt_div[lane], 0x1);
break; break;
case J721E_WIZ_10G: case J721E_WIZ_10G:
case J7200_WIZ_10G:
if (wiz->lane_phy_type[lane] == PHY_TYPE_SGMII) if (wiz->lane_phy_type[lane] == PHY_TYPE_SGMII)
return regmap_field_write(wiz->p0_fullrt_div[lane], 0x2); return regmap_field_write(wiz->p0_fullrt_div[lane], 0x2);
break; break;
...@@ -1139,6 +1226,8 @@ static const struct regmap_config wiz_regmap_config = { ...@@ -1139,6 +1226,8 @@ static const struct regmap_config wiz_regmap_config = {
static struct wiz_data j721e_16g_data = { static struct wiz_data j721e_16g_data = {
.type = J721E_WIZ_16G, .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, .refclk_dig_sel = &refclk_dig_sel_16g,
.pma_cmn_refclk1_dig_div = &pma_cmn_refclk1_dig_div, .pma_cmn_refclk1_dig_div = &pma_cmn_refclk1_dig_div,
.clk_mux_sel = clk_mux_sel_16g, .clk_mux_sel = clk_mux_sel_16g,
...@@ -1147,6 +1236,8 @@ static struct wiz_data j721e_16g_data = { ...@@ -1147,6 +1236,8 @@ static struct wiz_data j721e_16g_data = {
static struct wiz_data j721e_10g_data = { static struct wiz_data j721e_10g_data = {
.type = J721E_WIZ_10G, .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, .refclk_dig_sel = &refclk_dig_sel_10g,
.clk_mux_sel = clk_mux_sel_10g, .clk_mux_sel = clk_mux_sel_10g,
.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G, .clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
...@@ -1154,11 +1245,23 @@ static struct wiz_data j721e_10g_data = { ...@@ -1154,11 +1245,23 @@ static struct wiz_data j721e_10g_data = {
static struct wiz_data am64_10g_data = { static struct wiz_data am64_10g_data = {
.type = AM64_WIZ_10G, .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, .refclk_dig_sel = &refclk_dig_sel_10g,
.clk_mux_sel = clk_mux_sel_10g, .clk_mux_sel = clk_mux_sel_10g,
.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_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[] = { static const struct of_device_id wiz_id_table[] = {
{ {
.compatible = "ti,j721e-wiz-16g", .data = &j721e_16g_data, .compatible = "ti,j721e-wiz-16g", .data = &j721e_16g_data,
...@@ -1169,6 +1272,9 @@ static const struct of_device_id wiz_id_table[] = { ...@@ -1169,6 +1272,9 @@ static const struct of_device_id wiz_id_table[] = {
{ {
.compatible = "ti,am64-wiz-10g", .data = &am64_10g_data, .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); MODULE_DEVICE_TABLE(of, wiz_id_table);
...@@ -1266,6 +1372,16 @@ static int wiz_probe(struct platform_device *pdev) ...@@ -1266,6 +1372,16 @@ static int wiz_probe(struct platform_device *pdev)
goto err_addr_to_resource; 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); ret = of_property_read_u32(node, "num-lanes", &num_lanes);
if (ret) { if (ret) {
dev_err(dev, "Failed to read num-lanes property\n"); dev_err(dev, "Failed to read num-lanes property\n");
...@@ -1327,6 +1443,10 @@ static int wiz_probe(struct platform_device *pdev) ...@@ -1327,6 +1443,10 @@ static int wiz_probe(struct platform_device *pdev)
goto err_addr_to_resource; 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 = &wiz->wiz_phy_reset_dev;
phy_reset_dev->dev = dev; phy_reset_dev->dev = dev;
phy_reset_dev->ops = &wiz_phy_reset_ops, phy_reset_dev->ops = &wiz_phy_reset_ops,
......
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