162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright 2021 NXP 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci#include <linux/pcs/pcs-xpcs.h> 562306a36Sopenharmony_ci#include "pcs-xpcs.h" 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci/* LANE_DRIVER1_0 register */ 862306a36Sopenharmony_ci#define SJA1110_LANE_DRIVER1_0 0x8038 962306a36Sopenharmony_ci#define SJA1110_TXDRV(x) (((x) << 12) & GENMASK(14, 12)) 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* LANE_DRIVER2_0 register */ 1262306a36Sopenharmony_ci#define SJA1110_LANE_DRIVER2_0 0x803a 1362306a36Sopenharmony_ci#define SJA1110_TXDRVTRIM_LSB(x) ((x) & GENMASK_ULL(15, 0)) 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* LANE_DRIVER2_1 register */ 1662306a36Sopenharmony_ci#define SJA1110_LANE_DRIVER2_1 0x803b 1762306a36Sopenharmony_ci#define SJA1110_LANE_DRIVER2_1_RSV BIT(9) 1862306a36Sopenharmony_ci#define SJA1110_TXDRVTRIM_MSB(x) (((x) & GENMASK_ULL(23, 16)) >> 16) 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* LANE_TRIM register */ 2162306a36Sopenharmony_ci#define SJA1110_LANE_TRIM 0x8040 2262306a36Sopenharmony_ci#define SJA1110_TXTEN BIT(11) 2362306a36Sopenharmony_ci#define SJA1110_TXRTRIM(x) (((x) << 8) & GENMASK(10, 8)) 2462306a36Sopenharmony_ci#define SJA1110_TXPLL_BWSEL BIT(7) 2562306a36Sopenharmony_ci#define SJA1110_RXTEN BIT(6) 2662306a36Sopenharmony_ci#define SJA1110_RXRTRIM(x) (((x) << 3) & GENMASK(5, 3)) 2762306a36Sopenharmony_ci#define SJA1110_CDR_GAIN BIT(2) 2862306a36Sopenharmony_ci#define SJA1110_ACCOUPLE_RXVCM_EN BIT(0) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* LANE_DATAPATH_1 register */ 3162306a36Sopenharmony_ci#define SJA1110_LANE_DATAPATH_1 0x8037 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* POWERDOWN_ENABLE register */ 3462306a36Sopenharmony_ci#define SJA1110_POWERDOWN_ENABLE 0x8041 3562306a36Sopenharmony_ci#define SJA1110_TXPLL_PD BIT(12) 3662306a36Sopenharmony_ci#define SJA1110_TXPD BIT(11) 3762306a36Sopenharmony_ci#define SJA1110_RXPKDETEN BIT(10) 3862306a36Sopenharmony_ci#define SJA1110_RXCH_PD BIT(9) 3962306a36Sopenharmony_ci#define SJA1110_RXBIAS_PD BIT(8) 4062306a36Sopenharmony_ci#define SJA1110_RESET_SER_EN BIT(7) 4162306a36Sopenharmony_ci#define SJA1110_RESET_SER BIT(6) 4262306a36Sopenharmony_ci#define SJA1110_RESET_DES BIT(5) 4362306a36Sopenharmony_ci#define SJA1110_RCVEN BIT(4) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* RXPLL_CTRL0 register */ 4662306a36Sopenharmony_ci#define SJA1110_RXPLL_CTRL0 0x8065 4762306a36Sopenharmony_ci#define SJA1110_RXPLL_FBDIV(x) (((x) << 2) & GENMASK(9, 2)) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* RXPLL_CTRL1 register */ 5062306a36Sopenharmony_ci#define SJA1110_RXPLL_CTRL1 0x8066 5162306a36Sopenharmony_ci#define SJA1110_RXPLL_REFDIV(x) ((x) & GENMASK(4, 0)) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* TXPLL_CTRL0 register */ 5462306a36Sopenharmony_ci#define SJA1110_TXPLL_CTRL0 0x806d 5562306a36Sopenharmony_ci#define SJA1110_TXPLL_FBDIV(x) ((x) & GENMASK(11, 0)) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* TXPLL_CTRL1 register */ 5862306a36Sopenharmony_ci#define SJA1110_TXPLL_CTRL1 0x806e 5962306a36Sopenharmony_ci#define SJA1110_TXPLL_REFDIV(x) ((x) & GENMASK(5, 0)) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* RX_DATA_DETECT register */ 6262306a36Sopenharmony_ci#define SJA1110_RX_DATA_DETECT 0x8045 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* RX_CDR_CTLE register */ 6562306a36Sopenharmony_ci#define SJA1110_RX_CDR_CTLE 0x8042 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* In NXP SJA1105, the PCS is integrated with a PMA that has the TX lane 6862306a36Sopenharmony_ci * polarity inverted by default (PLUS is MINUS, MINUS is PLUS). To obtain 6962306a36Sopenharmony_ci * normal non-inverted behavior, the TX lane polarity must be inverted in the 7062306a36Sopenharmony_ci * PCS, via the DIGITAL_CONTROL_2 register. 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_ciint nxp_sja1105_sgmii_pma_config(struct dw_xpcs *xpcs) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL2, 7562306a36Sopenharmony_ci DW_VR_MII_DIG_CTRL2_TX_POL_INV); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic int nxp_sja1110_pma_config(struct dw_xpcs *xpcs, 7962306a36Sopenharmony_ci u16 txpll_fbdiv, u16 txpll_refdiv, 8062306a36Sopenharmony_ci u16 rxpll_fbdiv, u16 rxpll_refdiv, 8162306a36Sopenharmony_ci u16 rx_cdr_ctle) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci u16 val; 8462306a36Sopenharmony_ci int ret; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* Program TX PLL feedback divider and reference divider settings for 8762306a36Sopenharmony_ci * correct oscillation frequency. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_TXPLL_CTRL0, 9062306a36Sopenharmony_ci SJA1110_TXPLL_FBDIV(txpll_fbdiv)); 9162306a36Sopenharmony_ci if (ret < 0) 9262306a36Sopenharmony_ci return ret; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_TXPLL_CTRL1, 9562306a36Sopenharmony_ci SJA1110_TXPLL_REFDIV(txpll_refdiv)); 9662306a36Sopenharmony_ci if (ret < 0) 9762306a36Sopenharmony_ci return ret; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* Program transmitter amplitude and disable amplitude trimming */ 10062306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DRIVER1_0, 10162306a36Sopenharmony_ci SJA1110_TXDRV(0x5)); 10262306a36Sopenharmony_ci if (ret < 0) 10362306a36Sopenharmony_ci return ret; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci val = SJA1110_TXDRVTRIM_LSB(0xffffffull); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DRIVER2_0, val); 10862306a36Sopenharmony_ci if (ret < 0) 10962306a36Sopenharmony_ci return ret; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci val = SJA1110_TXDRVTRIM_MSB(0xffffffull) | SJA1110_LANE_DRIVER2_1_RSV; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DRIVER2_1, val); 11462306a36Sopenharmony_ci if (ret < 0) 11562306a36Sopenharmony_ci return ret; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* Enable input and output resistor terminations for low BER. */ 11862306a36Sopenharmony_ci val = SJA1110_ACCOUPLE_RXVCM_EN | SJA1110_CDR_GAIN | 11962306a36Sopenharmony_ci SJA1110_RXRTRIM(4) | SJA1110_RXTEN | SJA1110_TXPLL_BWSEL | 12062306a36Sopenharmony_ci SJA1110_TXRTRIM(3) | SJA1110_TXTEN; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_TRIM, val); 12362306a36Sopenharmony_ci if (ret < 0) 12462306a36Sopenharmony_ci return ret; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* Select PCS as transmitter data source. */ 12762306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_LANE_DATAPATH_1, 0); 12862306a36Sopenharmony_ci if (ret < 0) 12962306a36Sopenharmony_ci return ret; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* Program RX PLL feedback divider and reference divider for correct 13262306a36Sopenharmony_ci * oscillation frequency. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RXPLL_CTRL0, 13562306a36Sopenharmony_ci SJA1110_RXPLL_FBDIV(rxpll_fbdiv)); 13662306a36Sopenharmony_ci if (ret < 0) 13762306a36Sopenharmony_ci return ret; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RXPLL_CTRL1, 14062306a36Sopenharmony_ci SJA1110_RXPLL_REFDIV(rxpll_refdiv)); 14162306a36Sopenharmony_ci if (ret < 0) 14262306a36Sopenharmony_ci return ret; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci /* Program threshold for receiver signal detector. 14562306a36Sopenharmony_ci * Enable control of RXPLL by receiver signal detector to disable RXPLL 14662306a36Sopenharmony_ci * when an input signal is not present. 14762306a36Sopenharmony_ci */ 14862306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_DATA_DETECT, 0x0005); 14962306a36Sopenharmony_ci if (ret < 0) 15062306a36Sopenharmony_ci return ret; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci /* Enable TX and RX PLLs and circuits. 15362306a36Sopenharmony_ci * Release reset of PMA to enable data flow to/from PCS. 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci ret = xpcs_read(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE); 15662306a36Sopenharmony_ci if (ret < 0) 15762306a36Sopenharmony_ci return ret; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci val = ret & ~(SJA1110_TXPLL_PD | SJA1110_TXPD | SJA1110_RXCH_PD | 16062306a36Sopenharmony_ci SJA1110_RXBIAS_PD | SJA1110_RESET_SER_EN | 16162306a36Sopenharmony_ci SJA1110_RESET_SER | SJA1110_RESET_DES); 16262306a36Sopenharmony_ci val |= SJA1110_RXPKDETEN | SJA1110_RCVEN; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_POWERDOWN_ENABLE, val); 16562306a36Sopenharmony_ci if (ret < 0) 16662306a36Sopenharmony_ci return ret; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* Program continuous-time linear equalizer (CTLE) settings. */ 16962306a36Sopenharmony_ci ret = xpcs_write(xpcs, MDIO_MMD_VEND2, SJA1110_RX_CDR_CTLE, 17062306a36Sopenharmony_ci rx_cdr_ctle); 17162306a36Sopenharmony_ci if (ret < 0) 17262306a36Sopenharmony_ci return ret; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci return 0; 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ciint nxp_sja1110_sgmii_pma_config(struct dw_xpcs *xpcs) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci return nxp_sja1110_pma_config(xpcs, 0x19, 0x1, 0x19, 0x1, 0x212a); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ciint nxp_sja1110_2500basex_pma_config(struct dw_xpcs *xpcs) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci return nxp_sja1110_pma_config(xpcs, 0x7d, 0x2, 0x7d, 0x2, 0x732a); 18562306a36Sopenharmony_ci} 186