Commit 7f1abed4 authored by Kunihiko Hayashi's avatar Kunihiko Hayashi Committed by Vinod Koul

phy: uniphier-pcie: Add dual-phy support for NX1 SoC

NX1 SoC supports 2 lanes and has dual-phy. Should set appropriate
configuration values to both PHY registers.
Signed-off-by: default avatarKunihiko Hayashi <hayashi.kunihiko@socionext.com>
Link: https://lore.kernel.org/r/1635503947-18250-7-git-send-email-hayashi.kunihiko@socionext.comSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 25bba42f
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define TESTI_DAT_MASK GENMASK(13, 6) #define TESTI_DAT_MASK GENMASK(13, 6)
#define TESTI_ADR_MASK GENMASK(5, 1) #define TESTI_ADR_MASK GENMASK(5, 1)
#define TESTI_WR_EN BIT(0) #define TESTI_WR_EN BIT(0)
#define TESTIO_PHY_SHIFT 16
#define PCL_PHY_TEST_O 0x2004 #define PCL_PHY_TEST_O 0x2004
#define TESTO_DAT_MASK GENMASK(7, 0) #define TESTO_DAT_MASK GENMASK(7, 0)
...@@ -65,43 +66,57 @@ struct uniphier_pciephy_priv { ...@@ -65,43 +66,57 @@ struct uniphier_pciephy_priv {
struct uniphier_pciephy_soc_data { struct uniphier_pciephy_soc_data {
bool is_legacy; bool is_legacy;
bool is_dual_phy;
void (*set_phymode)(struct regmap *regmap); void (*set_phymode)(struct regmap *regmap);
}; };
static void uniphier_pciephy_testio_write(struct uniphier_pciephy_priv *priv, static void uniphier_pciephy_testio_write(struct uniphier_pciephy_priv *priv,
u32 data) int id, u32 data)
{ {
if (id)
data <<= TESTIO_PHY_SHIFT;
/* need to read TESTO twice after accessing TESTI */ /* need to read TESTO twice after accessing TESTI */
writel(data, priv->base + PCL_PHY_TEST_I); writel(data, priv->base + PCL_PHY_TEST_I);
readl(priv->base + PCL_PHY_TEST_O); readl(priv->base + PCL_PHY_TEST_O);
readl(priv->base + PCL_PHY_TEST_O); readl(priv->base + PCL_PHY_TEST_O);
} }
static u32 uniphier_pciephy_testio_read(struct uniphier_pciephy_priv *priv, int id)
{
u32 val = readl(priv->base + PCL_PHY_TEST_O);
if (id)
val >>= TESTIO_PHY_SHIFT;
return val & TESTO_DAT_MASK;
}
static void uniphier_pciephy_set_param(struct uniphier_pciephy_priv *priv, static void uniphier_pciephy_set_param(struct uniphier_pciephy_priv *priv,
u32 reg, u32 mask, u32 param) int id, u32 reg, u32 mask, u32 param)
{ {
u32 val; u32 val;
/* read previous data */ /* read previous data */
val = FIELD_PREP(TESTI_DAT_MASK, 1); val = FIELD_PREP(TESTI_DAT_MASK, 1);
val |= FIELD_PREP(TESTI_ADR_MASK, reg); val |= FIELD_PREP(TESTI_ADR_MASK, reg);
uniphier_pciephy_testio_write(priv, val); uniphier_pciephy_testio_write(priv, id, val);
val = readl(priv->base + PCL_PHY_TEST_O) & TESTO_DAT_MASK; val = uniphier_pciephy_testio_read(priv, id);
/* update value */ /* update value */
val &= ~mask; val &= ~mask;
val |= mask & param; val |= mask & param;
val = FIELD_PREP(TESTI_DAT_MASK, val); val = FIELD_PREP(TESTI_DAT_MASK, val);
val |= FIELD_PREP(TESTI_ADR_MASK, reg); val |= FIELD_PREP(TESTI_ADR_MASK, reg);
uniphier_pciephy_testio_write(priv, val); uniphier_pciephy_testio_write(priv, id, val);
uniphier_pciephy_testio_write(priv, val | TESTI_WR_EN); uniphier_pciephy_testio_write(priv, id, val | TESTI_WR_EN);
uniphier_pciephy_testio_write(priv, val); uniphier_pciephy_testio_write(priv, id, val);
/* read current data as dummy */ /* read current data as dummy */
val = FIELD_PREP(TESTI_DAT_MASK, 1); val = FIELD_PREP(TESTI_DAT_MASK, 1);
val |= FIELD_PREP(TESTI_ADR_MASK, reg); val |= FIELD_PREP(TESTI_ADR_MASK, reg);
uniphier_pciephy_testio_write(priv, val); uniphier_pciephy_testio_write(priv, id, val);
readl(priv->base + PCL_PHY_TEST_O); uniphier_pciephy_testio_read(priv, id);
} }
static void uniphier_pciephy_assert(struct uniphier_pciephy_priv *priv) static void uniphier_pciephy_assert(struct uniphier_pciephy_priv *priv)
...@@ -127,7 +142,7 @@ static int uniphier_pciephy_init(struct phy *phy) ...@@ -127,7 +142,7 @@ static int uniphier_pciephy_init(struct phy *phy)
{ {
struct uniphier_pciephy_priv *priv = phy_get_drvdata(phy); struct uniphier_pciephy_priv *priv = phy_get_drvdata(phy);
u32 val; u32 val;
int ret; int ret, id;
ret = clk_prepare_enable(priv->clk); ret = clk_prepare_enable(priv->clk);
if (ret) if (ret)
...@@ -155,14 +170,16 @@ static int uniphier_pciephy_init(struct phy *phy) ...@@ -155,14 +170,16 @@ static int uniphier_pciephy_init(struct phy *phy)
if (priv->data->is_legacy) if (priv->data->is_legacy)
return 0; return 0;
uniphier_pciephy_set_param(priv, PCL_PHY_R00, for (id = 0; id < (priv->data->is_dual_phy ? 2 : 1); id++) {
uniphier_pciephy_set_param(priv, id, PCL_PHY_R00,
RX_EQ_ADJ_EN, RX_EQ_ADJ_EN); RX_EQ_ADJ_EN, RX_EQ_ADJ_EN);
uniphier_pciephy_set_param(priv, PCL_PHY_R06, RX_EQ_ADJ, uniphier_pciephy_set_param(priv, id, PCL_PHY_R06, RX_EQ_ADJ,
FIELD_PREP(RX_EQ_ADJ, RX_EQ_ADJ_VAL)); FIELD_PREP(RX_EQ_ADJ, RX_EQ_ADJ_VAL));
uniphier_pciephy_set_param(priv, PCL_PHY_R26, VCO_CTRL, uniphier_pciephy_set_param(priv, id, PCL_PHY_R26, VCO_CTRL,
FIELD_PREP(VCO_CTRL, VCO_CTRL_INIT_VAL)); FIELD_PREP(VCO_CTRL, VCO_CTRL_INIT_VAL));
uniphier_pciephy_set_param(priv, PCL_PHY_R28, VCOPLL_CLMP, uniphier_pciephy_set_param(priv, id, PCL_PHY_R28, VCOPLL_CLMP,
FIELD_PREP(VCOPLL_CLMP, VCOPLL_CLMP_VAL)); FIELD_PREP(VCOPLL_CLMP, VCOPLL_CLMP_VAL));
}
usleep_range(1, 10); usleep_range(1, 10);
uniphier_pciephy_deassert(priv); uniphier_pciephy_deassert(priv);
...@@ -282,15 +299,18 @@ static const struct uniphier_pciephy_soc_data uniphier_pro5_data = { ...@@ -282,15 +299,18 @@ static const struct uniphier_pciephy_soc_data uniphier_pro5_data = {
static const struct uniphier_pciephy_soc_data uniphier_ld20_data = { static const struct uniphier_pciephy_soc_data uniphier_ld20_data = {
.is_legacy = false, .is_legacy = false,
.is_dual_phy = false,
.set_phymode = uniphier_pciephy_ld20_setmode, .set_phymode = uniphier_pciephy_ld20_setmode,
}; };
static const struct uniphier_pciephy_soc_data uniphier_pxs3_data = { static const struct uniphier_pciephy_soc_data uniphier_pxs3_data = {
.is_legacy = false, .is_legacy = false,
.is_dual_phy = false,
}; };
static const struct uniphier_pciephy_soc_data uniphier_nx1_data = { static const struct uniphier_pciephy_soc_data uniphier_nx1_data = {
.is_legacy = false, .is_legacy = false,
.is_dual_phy = true,
.set_phymode = uniphier_pciephy_nx1_setmode, .set_phymode = uniphier_pciephy_nx1_setmode,
}; };
......
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