Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Mar 24-27, 2025, special US time zones
Register
Loading...
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright 2021 NXP
  3 */
  4#include <linux/pcs/pcs-xpcs.h>
  5#include "pcs-xpcs.h"
  6
  7/* LANE_DRIVER1_0 register */
  8#define SJA1110_LANE_DRIVER1_0		0x8038
  9#define SJA1110_TXDRV(x)		(((x) << 12) & GENMASK(14, 12))
 10
 11/* LANE_DRIVER2_0 register */
 12#define SJA1110_LANE_DRIVER2_0		0x803a
 13#define SJA1110_TXDRVTRIM_LSB(x)	((x) & GENMASK_ULL(15, 0))
 14
 15/* LANE_DRIVER2_1 register */
 16#define SJA1110_LANE_DRIVER2_1		0x803b
 17#define SJA1110_LANE_DRIVER2_1_RSV	BIT(9)
 18#define SJA1110_TXDRVTRIM_MSB(x)	(((x) & GENMASK_ULL(23, 16)) >> 16)
 19
 20/* LANE_TRIM register */
 21#define SJA1110_LANE_TRIM		0x8040
 22#define SJA1110_TXTEN			BIT(11)
 23#define SJA1110_TXRTRIM(x)		(((x) << 8) & GENMASK(10, 8))
 24#define SJA1110_TXPLL_BWSEL		BIT(7)
 25#define SJA1110_RXTEN			BIT(6)
 26#define SJA1110_RXRTRIM(x)		(((x) << 3) & GENMASK(5, 3))
 27#define SJA1110_CDR_GAIN		BIT(2)
 28#define SJA1110_ACCOUPLE_RXVCM_EN	BIT(0)
 29
 30/* LANE_DATAPATH_1 register */
 31#define SJA1110_LANE_DATAPATH_1		0x8037
 32
 33/* POWERDOWN_ENABLE register */
 34#define SJA1110_POWERDOWN_ENABLE	0x8041
 35#define SJA1110_TXPLL_PD		BIT(12)
 36#define SJA1110_TXPD			BIT(11)
 37#define SJA1110_RXPKDETEN		BIT(10)
 38#define SJA1110_RXCH_PD			BIT(9)
 39#define SJA1110_RXBIAS_PD		BIT(8)
 40#define SJA1110_RESET_SER_EN		BIT(7)
 41#define SJA1110_RESET_SER		BIT(6)
 42#define SJA1110_RESET_DES		BIT(5)
 43#define SJA1110_RCVEN			BIT(4)
 44
 45/* RXPLL_CTRL0 register */
 46#define SJA1110_RXPLL_CTRL0		0x8065
 47#define SJA1110_RXPLL_FBDIV(x)		(((x) << 2) & GENMASK(9, 2))
 48
 49/* RXPLL_CTRL1 register */
 50#define SJA1110_RXPLL_CTRL1		0x8066
 51#define SJA1110_RXPLL_REFDIV(x)		((x) & GENMASK(4, 0))
 52
 53/* TXPLL_CTRL0 register */
 54#define SJA1110_TXPLL_CTRL0		0x806d
 55#define SJA1110_TXPLL_FBDIV(x)		((x) & GENMASK(11, 0))
 56
 57/* TXPLL_CTRL1 register */
 58#define SJA1110_TXPLL_CTRL1		0x806e
 59#define SJA1110_TXPLL_REFDIV(x)		((x) & GENMASK(5, 0))
 60
 61/* RX_DATA_DETECT register */
 62#define SJA1110_RX_DATA_DETECT		0x8045
 63
 64/* RX_CDR_CTLE register */
 65#define SJA1110_RX_CDR_CTLE		0x8042
 66
 67/* In NXP SJA1105, the PCS is integrated with a PMA that has the TX lane
 68 * polarity inverted by default (PLUS is MINUS, MINUS is PLUS). To obtain
 69 * normal non-inverted behavior, the TX lane polarity must be inverted in the
 70 * PCS, via the DIGITAL_CONTROL_2 register.
 71 */
 72int nxp_sja1105_sgmii_pma_config(struct dw_xpcs *xpcs)
 73{
 74	return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL2,
 75			  DW_VR_MII_DIG_CTRL2_TX_POL_INV);
 76}
 77
 78static int nxp_sja1110_pma_config(struct dw_xpcs *xpcs,
 79				  u16 txpll_fbdiv, u16 txpll_refdiv,
 80				  u16 rxpll_fbdiv, u16 rxpll_refdiv,
 81				  u16 rx_cdr_ctle)
 82{
 83	u16 val;
 84	int ret;
 85
 86	/* Program TX PLL feedback divider and reference divider settings for
 87	 * correct oscillation frequency.
 88	 */
 89	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_TXPLL_CTRL0,
 90			 SJA1110_TXPLL_FBDIV(txpll_fbdiv));
 91	if (ret < 0)
 92		return ret;
 93
 94	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_TXPLL_CTRL1,
 95			 SJA1110_TXPLL_REFDIV(txpll_refdiv));
 96	if (ret < 0)
 97		return ret;
 98
 99	/* Program transmitter amplitude and disable amplitude trimming */
100	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DRIVER1_0,
101			 SJA1110_TXDRV(0x5));
102	if (ret < 0)
103		return ret;
104
105	val = SJA1110_TXDRVTRIM_LSB(0xffffffull);
106
107	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DRIVER2_0, val);
108	if (ret < 0)
109		return ret;
110
111	val = SJA1110_TXDRVTRIM_MSB(0xffffffull) | SJA1110_LANE_DRIVER2_1_RSV;
112
113	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DRIVER2_1, val);
114	if (ret < 0)
115		return ret;
116
117	/* Enable input and output resistor terminations for low BER. */
118	val = SJA1110_ACCOUPLE_RXVCM_EN | SJA1110_CDR_GAIN |
119	      SJA1110_RXRTRIM(4) | SJA1110_RXTEN | SJA1110_TXPLL_BWSEL |
120	      SJA1110_TXRTRIM(3) | SJA1110_TXTEN;
121
122	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_TRIM, val);
123	if (ret < 0)
124		return ret;
125
126	/* Select PCS as transmitter data source. */
127	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DATAPATH_1, 0);
128	if (ret < 0)
129		return ret;
130
131	/* Program RX PLL feedback divider and reference divider for correct
132	 * oscillation frequency.
133	 */
134	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RXPLL_CTRL0,
135			 SJA1110_RXPLL_FBDIV(rxpll_fbdiv));
136	if (ret < 0)
137		return ret;
138
139	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RXPLL_CTRL1,
140			 SJA1110_RXPLL_REFDIV(rxpll_refdiv));
141	if (ret < 0)
142		return ret;
143
144	/* Program threshold for receiver signal detector.
145	 * Enable control of RXPLL by receiver signal detector to disable RXPLL
146	 * when an input signal is not present.
147	 */
148	ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_DATA_DETECT, 0x0005);
149	if (ret < 0)
150		return ret;
151
152	/* Enable TX and RX PLLs and circuits.
153	 * Release reset of PMA to enable data flow to/from PCS.
154	 */
155	ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE,
156			  SJA1110_TXPLL_PD | SJA1110_TXPD | SJA1110_RXCH_PD |
157			  SJA1110_RXBIAS_PD | SJA1110_RESET_SER_EN |
158			  SJA1110_RESET_SER | SJA1110_RESET_DES |
159			  SJA1110_RXPKDETEN | SJA1110_RCVEN,
160			  SJA1110_RXPKDETEN | SJA1110_RCVEN);
161	if (ret < 0)
162		return ret;
163
164	/* Program continuous-time linear equalizer (CTLE) settings. */
165	return xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_CDR_CTLE,
166			  rx_cdr_ctle);
167}
168
169int nxp_sja1110_sgmii_pma_config(struct dw_xpcs *xpcs)
170{
171	return nxp_sja1110_pma_config(xpcs, 0x19, 0x1, 0x19, 0x1, 0x212a);
172}
173
174int nxp_sja1110_2500basex_pma_config(struct dw_xpcs *xpcs)
175{
176	return nxp_sja1110_pma_config(xpcs, 0x7d, 0x2, 0x7d, 0x2, 0x732a);
177}