2021-06-11 23:05:25 +03:00
// SPDX-License-Identifier: GPL-2.0
2021-09-17 14:17:35 +03:00
/* Copyright 2021 NXP
2021-06-11 23:05:25 +03:00
*/
# include <linux/pcs/pcs-xpcs.h>
# include "pcs-xpcs.h"
2021-06-11 23:05:26 +03:00
/* LANE_DRIVER1_0 register */
# define SJA1110_LANE_DRIVER1_0 0x8038
# define SJA1110_TXDRV(x) (((x) << 12) & GENMASK(14, 12))
/* LANE_DRIVER2_0 register */
# define SJA1110_LANE_DRIVER2_0 0x803a
# define SJA1110_TXDRVTRIM_LSB(x) ((x) & GENMASK_ULL(15, 0))
/* LANE_DRIVER2_1 register */
# define SJA1110_LANE_DRIVER2_1 0x803b
# define SJA1110_LANE_DRIVER2_1_RSV BIT(9)
# define SJA1110_TXDRVTRIM_MSB(x) (((x) & GENMASK_ULL(23, 16)) >> 16)
/* LANE_TRIM register */
# define SJA1110_LANE_TRIM 0x8040
# define SJA1110_TXTEN BIT(11)
# define SJA1110_TXRTRIM(x) (((x) << 8) & GENMASK(10, 8))
# define SJA1110_TXPLL_BWSEL BIT(7)
# define SJA1110_RXTEN BIT(6)
# define SJA1110_RXRTRIM(x) (((x) << 3) & GENMASK(5, 3))
# define SJA1110_CDR_GAIN BIT(2)
# define SJA1110_ACCOUPLE_RXVCM_EN BIT(0)
/* LANE_DATAPATH_1 register */
# define SJA1110_LANE_DATAPATH_1 0x8037
/* POWERDOWN_ENABLE register */
# define SJA1110_POWERDOWN_ENABLE 0x8041
# define SJA1110_TXPLL_PD BIT(12)
# define SJA1110_TXPD BIT(11)
# define SJA1110_RXPKDETEN BIT(10)
# define SJA1110_RXCH_PD BIT(9)
# define SJA1110_RXBIAS_PD BIT(8)
# define SJA1110_RESET_SER_EN BIT(7)
# define SJA1110_RESET_SER BIT(6)
# define SJA1110_RESET_DES BIT(5)
# define SJA1110_RCVEN BIT(4)
/* RXPLL_CTRL0 register */
# define SJA1110_RXPLL_CTRL0 0x8065
# define SJA1110_RXPLL_FBDIV(x) (((x) << 2) & GENMASK(9, 2))
/* RXPLL_CTRL1 register */
# define SJA1110_RXPLL_CTRL1 0x8066
# define SJA1110_RXPLL_REFDIV(x) ((x) & GENMASK(4, 0))
/* TXPLL_CTRL0 register */
# define SJA1110_TXPLL_CTRL0 0x806d
# define SJA1110_TXPLL_FBDIV(x) ((x) & GENMASK(11, 0))
/* TXPLL_CTRL1 register */
# define SJA1110_TXPLL_CTRL1 0x806e
# define SJA1110_TXPLL_REFDIV(x) ((x) & GENMASK(5, 0))
/* RX_DATA_DETECT register */
# define SJA1110_RX_DATA_DETECT 0x8045
/* RX_CDR_CTLE register */
# define SJA1110_RX_CDR_CTLE 0x8042
2021-06-11 23:05:25 +03:00
/* In NXP SJA1105, the PCS is integrated with a PMA that has the TX lane
* polarity inverted by default ( PLUS is MINUS , MINUS is PLUS ) . To obtain
* normal non - inverted behavior , the TX lane polarity must be inverted in the
* PCS , via the DIGITAL_CONTROL_2 register .
*/
int nxp_sja1105_sgmii_pma_config ( struct dw_xpcs * xpcs )
{
return xpcs_write ( xpcs , MDIO_MMD_VEND2 , DW_VR_MII_DIG_CTRL2 ,
DW_VR_MII_DIG_CTRL2_TX_POL_INV ) ;
}
2021-06-11 23:05:26 +03:00
static int nxp_sja1110_pma_config ( struct dw_xpcs * xpcs ,
u16 txpll_fbdiv , u16 txpll_refdiv ,
u16 rxpll_fbdiv , u16 rxpll_refdiv ,
u16 rx_cdr_ctle )
{
u16 val ;
int ret ;
/* Program TX PLL feedback divider and reference divider settings for
* correct oscillation frequency .
*/
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_TXPLL_CTRL0 ,
SJA1110_TXPLL_FBDIV ( txpll_fbdiv ) ) ;
if ( ret < 0 )
return ret ;
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_TXPLL_CTRL1 ,
SJA1110_TXPLL_REFDIV ( txpll_refdiv ) ) ;
if ( ret < 0 )
return ret ;
/* Program transmitter amplitude and disable amplitude trimming */
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_LANE_DRIVER1_0 ,
SJA1110_TXDRV ( 0x5 ) ) ;
if ( ret < 0 )
return ret ;
val = SJA1110_TXDRVTRIM_LSB ( 0xffffffull ) ;
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_LANE_DRIVER2_0 , val ) ;
if ( ret < 0 )
return ret ;
val = SJA1110_TXDRVTRIM_MSB ( 0xffffffull ) | SJA1110_LANE_DRIVER2_1_RSV ;
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_LANE_DRIVER2_1 , val ) ;
if ( ret < 0 )
return ret ;
/* Enable input and output resistor terminations for low BER. */
val = SJA1110_ACCOUPLE_RXVCM_EN | SJA1110_CDR_GAIN |
SJA1110_RXRTRIM ( 4 ) | SJA1110_RXTEN | SJA1110_TXPLL_BWSEL |
SJA1110_TXRTRIM ( 3 ) | SJA1110_TXTEN ;
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_LANE_TRIM , val ) ;
if ( ret < 0 )
return ret ;
/* Select PCS as transmitter data source. */
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_LANE_DATAPATH_1 , 0 ) ;
if ( ret < 0 )
return ret ;
/* Program RX PLL feedback divider and reference divider for correct
* oscillation frequency .
*/
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_RXPLL_CTRL0 ,
SJA1110_RXPLL_FBDIV ( rxpll_fbdiv ) ) ;
if ( ret < 0 )
return ret ;
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_RXPLL_CTRL1 ,
SJA1110_RXPLL_REFDIV ( rxpll_refdiv ) ) ;
if ( ret < 0 )
return ret ;
/* Program threshold for receiver signal detector.
* Enable control of RXPLL by receiver signal detector to disable RXPLL
* when an input signal is not present .
*/
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_RX_DATA_DETECT , 0x0005 ) ;
if ( ret < 0 )
return ret ;
/* Enable TX and RX PLLs and circuits.
* Release reset of PMA to enable data flow to / from PCS .
*/
2021-06-15 14:52:53 +01:00
ret = xpcs_read ( xpcs , MDIO_MMD_VEND2 , SJA1110_POWERDOWN_ENABLE ) ;
if ( ret < 0 )
return ret ;
2021-06-11 23:05:26 +03:00
2021-06-15 14:52:53 +01:00
val = ret & ~ ( SJA1110_TXPLL_PD | SJA1110_TXPD | SJA1110_RXCH_PD |
SJA1110_RXBIAS_PD | SJA1110_RESET_SER_EN |
SJA1110_RESET_SER | SJA1110_RESET_DES ) ;
2021-06-11 23:05:26 +03:00
val | = SJA1110_RXPKDETEN | SJA1110_RCVEN ;
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_POWERDOWN_ENABLE , val ) ;
if ( ret < 0 )
return ret ;
/* Program continuous-time linear equalizer (CTLE) settings. */
ret = xpcs_write ( xpcs , MDIO_MMD_VEND2 , SJA1110_RX_CDR_CTLE ,
rx_cdr_ctle ) ;
if ( ret < 0 )
return ret ;
return 0 ;
}
int nxp_sja1110_sgmii_pma_config ( struct dw_xpcs * xpcs )
{
return nxp_sja1110_pma_config ( xpcs , 0x19 , 0x1 , 0x19 , 0x1 , 0x212a ) ;
}
int nxp_sja1110_2500basex_pma_config ( struct dw_xpcs * xpcs )
{
return nxp_sja1110_pma_config ( xpcs , 0x7d , 0x2 , 0x7d , 0x2 , 0x732a ) ;
}