Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */
  3
  4#include <linux/pcs/pcs-xpcs.h>
  5#include <linux/mdio.h>
  6#include "pcs-xpcs.h"
  7
  8/* VR_XS_PMA_MMD */
  9#define TXGBE_PMA_MMD			0x8020
 10#define TXGBE_TX_GENCTL1		0x11
 11#define TXGBE_TX_GENCTL1_VBOOST_LVL	GENMASK(10, 8)
 12#define TXGBE_TX_GENCTL1_VBOOST_EN0	BIT(4)
 13#define TXGBE_TX_GEN_CTL2		0x12
 14#define TXGBE_TX_GEN_CTL2_TX0_WIDTH(v)	FIELD_PREP(GENMASK(9, 8), v)
 15#define TXGBE_TX_RATE_CTL		0x14
 16#define TXGBE_TX_RATE_CTL_TX0_RATE(v)	FIELD_PREP(GENMASK(2, 0), v)
 17#define TXGBE_RX_GEN_CTL2		0x32
 18#define TXGBE_RX_GEN_CTL2_RX0_WIDTH(v)	FIELD_PREP(GENMASK(9, 8), v)
 19#define TXGBE_RX_GEN_CTL3		0x33
 20#define TXGBE_RX_GEN_CTL3_LOS_TRSHLD0	GENMASK(2, 0)
 21#define TXGBE_RX_RATE_CTL		0x34
 22#define TXGBE_RX_RATE_CTL_RX0_RATE(v)	FIELD_PREP(GENMASK(1, 0), v)
 23#define TXGBE_RX_EQ_ATTN_CTL		0x37
 24#define TXGBE_RX_EQ_ATTN_LVL0		GENMASK(2, 0)
 25#define TXGBE_RX_EQ_CTL0		0x38
 26#define TXGBE_RX_EQ_CTL0_VGA1_GAIN(v)	FIELD_PREP(GENMASK(15, 12), v)
 27#define TXGBE_RX_EQ_CTL0_VGA2_GAIN(v)	FIELD_PREP(GENMASK(11, 8), v)
 28#define TXGBE_RX_EQ_CTL0_CTLE_POLE(v)	FIELD_PREP(GENMASK(7, 5), v)
 29#define TXGBE_RX_EQ_CTL0_CTLE_BOOST(v)	FIELD_PREP(GENMASK(4, 0), v)
 30#define TXGBE_RX_EQ_CTL4		0x3C
 31#define TXGBE_RX_EQ_CTL4_CONT_OFF_CAN0	BIT(4)
 32#define TXGBE_RX_EQ_CTL4_CONT_ADAPT0	BIT(0)
 33#define TXGBE_AFE_DFE_ENABLE		0x3D
 34#define TXGBE_DFE_EN_0			BIT(4)
 35#define TXGBE_AFE_EN_0			BIT(0)
 36#define TXGBE_DFE_TAP_CTL0		0x3E
 37#define TXGBE_MPLLA_CTL0		0x51
 38#define TXGBE_MPLLA_CTL2		0x53
 39#define TXGBE_MPLLA_CTL2_DIV16P5_CLK_EN	BIT(10)
 40#define TXGBE_MPLLA_CTL2_DIV10_CLK_EN	BIT(9)
 41#define TXGBE_MPLLA_CTL3		0x57
 42#define TXGBE_MISC_CTL0			0x70
 43#define TXGBE_MISC_CTL0_PLL		BIT(15)
 44#define TXGBE_MISC_CTL0_CR_PARA_SEL	BIT(14)
 45#define TXGBE_MISC_CTL0_RX_VREF(v)	FIELD_PREP(GENMASK(12, 8), v)
 46#define TXGBE_VCO_CAL_LD0		0x72
 47#define TXGBE_VCO_CAL_REF0		0x76
 48
 49static int txgbe_write_pma(struct dw_xpcs *xpcs, int reg, u16 val)
 50{
 51	return xpcs_write(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, val);
 52}
 53
 54static int txgbe_modify_pma(struct dw_xpcs *xpcs, int reg, u16 mask, u16 set)
 55{
 56	return xpcs_modify(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, mask,
 57			   set);
 58}
 59
 60static void txgbe_pma_config_10gbaser(struct dw_xpcs *xpcs)
 61{
 62	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x21);
 63	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0);
 64	txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1, TXGBE_TX_GENCTL1_VBOOST_LVL,
 65			 FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
 66	txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
 67			TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
 68	txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x549);
 69	txgbe_write_pma(xpcs, TXGBE_VCO_CAL_REF0, 0x29);
 70	txgbe_write_pma(xpcs, TXGBE_TX_RATE_CTL, 0);
 71	txgbe_write_pma(xpcs, TXGBE_RX_RATE_CTL, 0);
 72	txgbe_write_pma(xpcs, TXGBE_TX_GEN_CTL2, TXGBE_TX_GEN_CTL2_TX0_WIDTH(3));
 73	txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL2, TXGBE_RX_GEN_CTL2_RX0_WIDTH(3));
 74	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL2, TXGBE_MPLLA_CTL2_DIV16P5_CLK_EN |
 75			TXGBE_MPLLA_CTL2_DIV10_CLK_EN);
 76
 77	txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_CTLE_POLE(2) |
 78			TXGBE_RX_EQ_CTL0_CTLE_BOOST(5));
 79	txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
 80	txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0xBE);
 81	txgbe_modify_pma(xpcs, TXGBE_AFE_DFE_ENABLE,
 82			 TXGBE_DFE_EN_0 | TXGBE_AFE_EN_0, 0);
 83	txgbe_modify_pma(xpcs, TXGBE_RX_EQ_CTL4, TXGBE_RX_EQ_CTL4_CONT_ADAPT0,
 84			 0);
 85}
 86
 87static void txgbe_pma_config_1g(struct dw_xpcs *xpcs)
 88{
 89	txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1,
 90			 TXGBE_TX_GENCTL1_VBOOST_LVL |
 91			 TXGBE_TX_GENCTL1_VBOOST_EN0,
 92			 FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
 93	txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
 94			TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
 95
 96	txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_VGA1_GAIN(7) |
 97			TXGBE_RX_EQ_CTL0_VGA2_GAIN(7) | TXGBE_RX_EQ_CTL0_CTLE_BOOST(6));
 98	txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
 99	txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0);
100	txgbe_modify_pma(xpcs, TXGBE_RX_GEN_CTL3, TXGBE_RX_GEN_CTL3_LOS_TRSHLD0,
101			 FIELD_PREP(TXGBE_RX_GEN_CTL3_LOS_TRSHLD0, 0x4));
102
103	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x20);
104	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0x46);
105	txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x540);
106	txgbe_write_pma(xpcs, TXGBE_VCO_CAL_REF0, 0x2A);
107	txgbe_write_pma(xpcs, TXGBE_AFE_DFE_ENABLE, 0);
108	txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL4, TXGBE_RX_EQ_CTL4_CONT_OFF_CAN0);
109	txgbe_write_pma(xpcs, TXGBE_TX_RATE_CTL, TXGBE_TX_RATE_CTL_TX0_RATE(3));
110	txgbe_write_pma(xpcs, TXGBE_RX_RATE_CTL, TXGBE_RX_RATE_CTL_RX0_RATE(3));
111	txgbe_write_pma(xpcs, TXGBE_TX_GEN_CTL2, TXGBE_TX_GEN_CTL2_TX0_WIDTH(1));
112	txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL2, TXGBE_RX_GEN_CTL2_RX0_WIDTH(1));
113	txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL2, TXGBE_MPLLA_CTL2_DIV10_CLK_EN);
114}
115
116static int txgbe_pcs_poll_power_up(struct dw_xpcs *xpcs)
117{
118	int val, ret;
119
120	/* Wait xpcs power-up good */
121	ret = read_poll_timeout(xpcs_read_vpcs, val,
122				(val & DW_PSEQ_ST) == DW_PSEQ_ST_GOOD,
123				10000, 1000000, false,
124				xpcs, DW_VR_XS_PCS_DIG_STS);
125	if (ret < 0)
126		dev_err(&xpcs->mdiodev->dev, "xpcs power-up timeout\n");
127
128	return ret;
129}
130
131static int txgbe_pma_init_done(struct dw_xpcs *xpcs)
132{
133	int val, ret;
134
135	xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_VR_RST | DW_EN_VSMMD1);
136
137	/* wait pma initialization done */
138	ret = read_poll_timeout(xpcs_read_vpcs, val, !(val & DW_VR_RST),
139				100000, 10000000, false,
140				xpcs, DW_VR_XS_PCS_DIG_CTRL1);
141	if (ret < 0)
142		dev_err(&xpcs->mdiodev->dev, "xpcs pma initialization timeout\n");
143
144	return ret;
145}
146
147static bool txgbe_xpcs_mode_quirk(struct dw_xpcs *xpcs)
148{
149	int ret;
150
151	/* When txgbe do LAN reset, PCS will change to default 10GBASE-R mode */
152	ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_CTRL2);
153	ret &= MDIO_PCS_CTRL2_TYPE;
154	if ((ret == MDIO_PCS_CTRL2_10GBR &&
155	     xpcs->interface != PHY_INTERFACE_MODE_10GBASER) ||
156	    xpcs->interface == PHY_INTERFACE_MODE_SGMII)
157		return true;
158
159	return false;
160}
161
162int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
163{
164	int ret;
165
166	switch (interface) {
167	case PHY_INTERFACE_MODE_10GBASER:
168	case PHY_INTERFACE_MODE_SGMII:
169	case PHY_INTERFACE_MODE_1000BASEX:
170		break;
171	default:
172		return 0;
173	}
174
175	if (xpcs->interface == interface && !txgbe_xpcs_mode_quirk(xpcs))
176		return 0;
177
178	xpcs->interface = interface;
179
180	ret = txgbe_pcs_poll_power_up(xpcs);
181	if (ret < 0)
182		return ret;
183
184	if (interface == PHY_INTERFACE_MODE_10GBASER) {
185		xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBR);
186		xpcs_modify(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1,
187			    MDIO_CTRL1_SPEED10G, MDIO_CTRL1_SPEED10G);
188		txgbe_pma_config_10gbaser(xpcs);
189	} else {
190		xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBX);
191		xpcs_write(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1, 0);
192		xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL1, 0);
193		txgbe_pma_config_1g(xpcs);
194	}
195
196	return txgbe_pma_init_done(xpcs);
197}