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

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.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 25bba42f
Loading
Loading
Loading
Loading
+34 −14
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#define TESTI_DAT_MASK		GENMASK(13, 6)
#define TESTI_ADR_MASK		GENMASK(5, 1)
#define TESTI_WR_EN		BIT(0)
#define TESTIO_PHY_SHIFT	16

#define PCL_PHY_TEST_O		0x2004
#define TESTO_DAT_MASK		GENMASK(7, 0)
@@ -65,43 +66,57 @@ struct uniphier_pciephy_priv {

struct uniphier_pciephy_soc_data {
	bool is_legacy;
	bool is_dual_phy;
	void (*set_phymode)(struct regmap *regmap);
};

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 */
	writel(data, priv->base + PCL_PHY_TEST_I);
	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,
				       u32 reg, u32 mask, u32 param)
				       int id, u32 reg, u32 mask, u32 param)
{
	u32 val;

	/* read previous data */
	val  = FIELD_PREP(TESTI_DAT_MASK, 1);
	val |= FIELD_PREP(TESTI_ADR_MASK, reg);
	uniphier_pciephy_testio_write(priv, val);
	val = readl(priv->base + PCL_PHY_TEST_O) & TESTO_DAT_MASK;
	uniphier_pciephy_testio_write(priv, id, val);
	val = uniphier_pciephy_testio_read(priv, id);

	/* update value */
	val &= ~mask;
	val |= mask & param;
	val = FIELD_PREP(TESTI_DAT_MASK, val);
	val |= FIELD_PREP(TESTI_ADR_MASK, reg);
	uniphier_pciephy_testio_write(priv, val);
	uniphier_pciephy_testio_write(priv, val | TESTI_WR_EN);
	uniphier_pciephy_testio_write(priv, val);
	uniphier_pciephy_testio_write(priv, id, val);
	uniphier_pciephy_testio_write(priv, id, val | TESTI_WR_EN);
	uniphier_pciephy_testio_write(priv, id, val);

	/* read current data as dummy */
	val  = FIELD_PREP(TESTI_DAT_MASK, 1);
	val |= FIELD_PREP(TESTI_ADR_MASK, reg);
	uniphier_pciephy_testio_write(priv, val);
	readl(priv->base + PCL_PHY_TEST_O);
	uniphier_pciephy_testio_write(priv, id, val);
	uniphier_pciephy_testio_read(priv, id);
}

static void uniphier_pciephy_assert(struct uniphier_pciephy_priv *priv)
@@ -127,7 +142,7 @@ static int uniphier_pciephy_init(struct phy *phy)
{
	struct uniphier_pciephy_priv *priv = phy_get_drvdata(phy);
	u32 val;
	int ret;
	int ret, id;

	ret = clk_prepare_enable(priv->clk);
	if (ret)
@@ -155,14 +170,16 @@ static int uniphier_pciephy_init(struct phy *phy)
	if (priv->data->is_legacy)
		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);
	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));
	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));
	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));
	}
	usleep_range(1, 10);

	uniphier_pciephy_deassert(priv);
@@ -282,15 +299,18 @@ static const struct uniphier_pciephy_soc_data uniphier_pro5_data = {

static const struct uniphier_pciephy_soc_data uniphier_ld20_data = {
	.is_legacy = false,
	.is_dual_phy = false,
	.set_phymode = uniphier_pciephy_ld20_setmode,
};

static const struct uniphier_pciephy_soc_data uniphier_pxs3_data = {
	.is_legacy = false,
	.is_dual_phy = false,
};

static const struct uniphier_pciephy_soc_data uniphier_nx1_data = {
	.is_legacy = false,
	.is_dual_phy = true,
	.set_phymode = uniphier_pciephy_nx1_setmode,
};