cregit-Linux how code gets into the kernel

Release 4.9 drivers/net/ethernet/qualcomm/emac/emac-sgmii.c

/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/* Qualcomm Technologies, Inc. EMAC SGMII Controller driver.
 */

#include <linux/iopoll.h>
#include <linux/acpi.h>
#include <linux/of_device.h>
#include "emac.h"
#include "emac-mac.h"
#include "emac-sgmii.h"

/* EMAC_QSERDES register offsets */

#define EMAC_QSERDES_COM_SYS_CLK_CTRL		0x000000

#define EMAC_QSERDES_COM_PLL_CNTRL		0x000014

#define EMAC_QSERDES_COM_PLL_IP_SETI		0x000018

#define EMAC_QSERDES_COM_PLL_CP_SETI		0x000024

#define EMAC_QSERDES_COM_PLL_IP_SETP		0x000028

#define EMAC_QSERDES_COM_PLL_CP_SETP		0x00002c

#define EMAC_QSERDES_COM_SYSCLK_EN_SEL		0x000038

#define EMAC_QSERDES_COM_RESETSM_CNTRL		0x000040

#define EMAC_QSERDES_COM_PLLLOCK_CMP1		0x000044

#define EMAC_QSERDES_COM_PLLLOCK_CMP2		0x000048

#define EMAC_QSERDES_COM_PLLLOCK_CMP3		0x00004c

#define EMAC_QSERDES_COM_PLLLOCK_CMP_EN		0x000050

#define EMAC_QSERDES_COM_DEC_START1		0x000064

#define EMAC_QSERDES_COM_DIV_FRAC_START1	0x000098

#define EMAC_QSERDES_COM_DIV_FRAC_START2	0x00009c

#define EMAC_QSERDES_COM_DIV_FRAC_START3	0x0000a0

#define EMAC_QSERDES_COM_DEC_START2		0x0000a4

#define EMAC_QSERDES_COM_PLL_CRCTRL		0x0000ac

#define EMAC_QSERDES_COM_RESET_SM		0x0000bc

#define EMAC_QSERDES_TX_BIST_MODE_LANENO	0x000100

#define EMAC_QSERDES_TX_TX_EMP_POST1_LVL	0x000108

#define EMAC_QSERDES_TX_TX_DRV_LVL		0x00010c

#define EMAC_QSERDES_TX_LANE_MODE		0x000150

#define EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN	0x000170

#define EMAC_QSERDES_RX_CDR_CONTROL		0x000200

#define EMAC_QSERDES_RX_CDR_CONTROL2		0x000210

#define EMAC_QSERDES_RX_RX_EQ_GAIN12		0x000230

/* EMAC_SGMII register offsets */

#define EMAC_SGMII_PHY_SERDES_START		0x000000

#define EMAC_SGMII_PHY_CMN_PWR_CTRL		0x000004

#define EMAC_SGMII_PHY_RX_PWR_CTRL		0x000008

#define EMAC_SGMII_PHY_TX_PWR_CTRL		0x00000C

#define EMAC_SGMII_PHY_LANE_CTRL1		0x000018

#define EMAC_SGMII_PHY_AUTONEG_CFG2		0x000048

#define EMAC_SGMII_PHY_CDR_CTRL0		0x000058

#define EMAC_SGMII_PHY_SPEED_CFG1		0x000074

#define EMAC_SGMII_PHY_POW_DWN_CTRL0		0x000080

#define EMAC_SGMII_PHY_RESET_CTRL		0x0000a8

#define EMAC_SGMII_PHY_IRQ_CMD			0x0000ac

#define EMAC_SGMII_PHY_INTERRUPT_CLEAR		0x0000b0

#define EMAC_SGMII_PHY_INTERRUPT_MASK		0x0000b4

#define EMAC_SGMII_PHY_INTERRUPT_STATUS		0x0000b8

#define EMAC_SGMII_PHY_RX_CHK_STATUS		0x0000d4

#define EMAC_SGMII_PHY_AUTONEG0_STATUS		0x0000e0

#define EMAC_SGMII_PHY_AUTONEG1_STATUS		0x0000e4

/* EMAC_QSERDES_COM_PLL_IP_SETI */

#define PLL_IPSETI(x)				((x) & 0x3f)

/* EMAC_QSERDES_COM_PLL_CP_SETI */

#define PLL_CPSETI(x)				((x) & 0xff)

/* EMAC_QSERDES_COM_PLL_IP_SETP */

#define PLL_IPSETP(x)				((x) & 0x3f)

/* EMAC_QSERDES_COM_PLL_CP_SETP */

#define PLL_CPSETP(x)				((x) & 0x1f)

/* EMAC_QSERDES_COM_PLL_CRCTRL */

#define PLL_RCTRL(x)				(((x) & 0xf) << 4)

#define PLL_CCTRL(x)				((x) & 0xf)

/* SGMII v2 PHY registers per lane */

#define EMAC_SGMII_PHY_LN_OFFSET		0x0400

/* SGMII v2 digital lane registers */

#define EMAC_SGMII_LN_DRVR_CTRL0		0x00C

#define EMAC_SGMII_LN_DRVR_TAP_EN		0x018

#define EMAC_SGMII_LN_TX_MARGINING		0x01C

#define EMAC_SGMII_LN_TX_PRE			0x020

#define EMAC_SGMII_LN_TX_POST			0x024

#define EMAC_SGMII_LN_TX_BAND_MODE		0x060

#define EMAC_SGMII_LN_LANE_MODE			0x064

#define EMAC_SGMII_LN_PARALLEL_RATE		0x078

#define EMAC_SGMII_LN_CML_CTRL_MODE0		0x0B8

#define EMAC_SGMII_LN_MIXER_CTRL_MODE0		0x0D0

#define EMAC_SGMII_LN_VGA_INITVAL		0x134

#define EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0	0x17C

#define EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0	0x188

#define EMAC_SGMII_LN_UCDR_SO_CONFIG		0x194

#define EMAC_SGMII_LN_RX_BAND			0x19C

#define EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0	0x1B8

#define EMAC_SGMII_LN_RSM_CONFIG		0x1F0

#define EMAC_SGMII_LN_SIGDET_ENABLES		0x224

#define EMAC_SGMII_LN_SIGDET_CNTRL		0x228

#define EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL	0x22C

#define EMAC_SGMII_LN_RX_EN_SIGNAL		0x2A0

#define EMAC_SGMII_LN_RX_MISC_CNTRL0		0x2AC

#define EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV		0x2BC

/* SGMII v2 digital lane register values */

#define UCDR_STEP_BY_TWO_MODE0			BIT(7)

#define UCDR_xO_GAIN_MODE(x)			((x) & 0x7f)

#define UCDR_ENABLE				BIT(6)

#define UCDR_SO_SATURATION(x)			((x) & 0x3f)

#define SIGDET_LP_BYP_PS4			BIT(7)

#define SIGDET_EN_PS0_TO_PS2			BIT(6)

#define EN_ACCOUPLEVCM_SW_MUX			BIT(5)

#define EN_ACCOUPLEVCM_SW			BIT(4)

#define RX_SYNC_EN				BIT(3)

#define RXTERM_HIGHZ_PS5			BIT(2)

#define SIGDET_EN_PS3				BIT(1)

#define EN_ACCOUPLE_VCM_PS3			BIT(0)

#define UFS_MODE				BIT(5)

#define TXVAL_VALID_INIT			BIT(4)

#define TXVAL_VALID_MUX				BIT(3)

#define TXVAL_VALID				BIT(2)

#define USB3P1_MODE				BIT(1)

#define KR_PCIGEN3_MODE				BIT(0)

#define PRE_EN					BIT(3)

#define POST_EN					BIT(2)

#define MAIN_EN_MUX				BIT(1)

#define MAIN_EN					BIT(0)

#define TX_MARGINING_MUX			BIT(6)

#define TX_MARGINING(x)				((x) & 0x3f)

#define TX_PRE_MUX				BIT(6)

#define TX_PRE(x)				((x) & 0x3f)

#define TX_POST_MUX				BIT(6)

#define TX_POST(x)				((x) & 0x3f)

#define CML_GEAR_MODE(x)			(((x) & 7) << 3)

#define CML2CMOS_IBOOST_MODE(x)			((x) & 7)

#define MIXER_LOADB_MODE(x)			(((x) & 0xf) << 2)

#define MIXER_DATARATE_MODE(x)			((x) & 3)

#define VGA_THRESH_DFE(x)			((x) & 0x3f)

#define SIGDET_LP_BYP_PS0_TO_PS2		BIT(5)

#define SIGDET_LP_BYP_MUX			BIT(4)

#define SIGDET_LP_BYP				BIT(3)

#define SIGDET_EN_MUX				BIT(2)

#define SIGDET_EN				BIT(1)

#define SIGDET_FLT_BYP				BIT(0)

#define SIGDET_LVL(x)				(((x) & 0xf) << 4)

#define SIGDET_BW_CTRL(x)			((x) & 0xf)

#define SIGDET_DEGLITCH_CTRL(x)			(((x) & 0xf) << 1)

#define SIGDET_DEGLITCH_BYP			BIT(0)

#define INVERT_PCS_RX_CLK			BIT(7)

#define PWM_EN					BIT(6)

#define RXBIAS_SEL(x)				(((x) & 0x3) << 4)

#define EBDAC_SIGN				BIT(3)

#define EDAC_SIGN				BIT(2)

#define EN_AUXTAP1SIGN_INVERT			BIT(1)

#define EN_DAC_CHOPPING				BIT(0)

#define DRVR_LOGIC_CLK_EN			BIT(4)

#define DRVR_LOGIC_CLK_DIV(x)			((x) & 0xf)

#define PARALLEL_RATE_MODE2(x)			(((x) & 0x3) << 4)

#define PARALLEL_RATE_MODE1(x)			(((x) & 0x3) << 2)

#define PARALLEL_RATE_MODE0(x)			((x) & 0x3)

#define BAND_MODE2(x)				(((x) & 0x3) << 4)

#define BAND_MODE1(x)				(((x) & 0x3) << 2)

#define BAND_MODE0(x)				((x) & 0x3)

#define LANE_SYNC_MODE				BIT(5)

#define LANE_MODE(x)				((x) & 0x1f)

#define CDR_PD_SEL_MODE0(x)			(((x) & 0x3) << 5)

#define EN_DLL_MODE0				BIT(4)

#define EN_IQ_DCC_MODE0				BIT(3)

#define EN_IQCAL_MODE0				BIT(2)

#define EN_QPATH_MODE0				BIT(1)

#define EN_EPATH_MODE0				BIT(0)

#define FORCE_TSYNC_ACK				BIT(7)

#define FORCE_CMN_ACK				BIT(6)

#define FORCE_CMN_READY				BIT(5)

#define EN_RCLK_DEGLITCH			BIT(4)

#define BYPASS_RSM_CDR_RESET			BIT(3)

#define BYPASS_RSM_TSYNC			BIT(2)

#define BYPASS_RSM_SAMP_CAL			BIT(1)

#define BYPASS_RSM_DLL_CAL			BIT(0)

/* EMAC_QSERDES_COM_SYS_CLK_CTRL */

#define SYSCLK_CM				BIT(4)

#define SYSCLK_AC_COUPLE			BIT(3)

/* EMAC_QSERDES_COM_PLL_CNTRL */

#define OCP_EN					BIT(5)

#define PLL_DIV_FFEN				BIT(2)

#define PLL_DIV_ORD				BIT(1)

/* EMAC_QSERDES_COM_SYSCLK_EN_SEL */

#define SYSCLK_SEL_CMOS				BIT(3)

/* EMAC_QSERDES_COM_RESETSM_CNTRL */

#define FRQ_TUNE_MODE				BIT(4)

/* EMAC_QSERDES_COM_PLLLOCK_CMP_EN */

#define PLLLOCK_CMP_EN				BIT(0)

/* EMAC_QSERDES_COM_DEC_START1 */

#define DEC_START1_MUX				BIT(7)

#define DEC_START1(x)				((x) & 0x7f)

/* EMAC_QSERDES_COM_DIV_FRAC_START1 * EMAC_QSERDES_COM_DIV_FRAC_START2 */

#define DIV_FRAC_START_MUX			BIT(7)

#define DIV_FRAC_START(x)			((x) & 0x7f)

/* EMAC_QSERDES_COM_DIV_FRAC_START3 */

#define DIV_FRAC_START3_MUX			BIT(4)

#define DIV_FRAC_START3(x)			((x) & 0xf)

/* EMAC_QSERDES_COM_DEC_START2 */

#define DEC_START2_MUX				BIT(1)

#define DEC_START2				BIT(0)

/* EMAC_QSERDES_COM_RESET_SM */

#define READY					BIT(5)

/* EMAC_QSERDES_TX_TX_EMP_POST1_LVL */

#define TX_EMP_POST1_LVL_MUX			BIT(5)

#define TX_EMP_POST1_LVL(x)			((x) & 0x1f)

#define TX_EMP_POST1_LVL_BMSK			0x1f

#define TX_EMP_POST1_LVL_SHFT			0

/* EMAC_QSERDES_TX_TX_DRV_LVL */

#define TX_DRV_LVL_MUX				BIT(4)

#define TX_DRV_LVL(x)				((x) & 0xf)

/* EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN */

#define EMP_EN_MUX				BIT(1)

#define EMP_EN					BIT(0)

/* EMAC_QSERDES_RX_CDR_CONTROL & EMAC_QSERDES_RX_CDR_CONTROL2 */

#define HBW_PD_EN				BIT(7)

#define SECONDORDERENABLE			BIT(6)

#define FIRSTORDER_THRESH(x)			(((x) & 0x7) << 3)

#define SECONDORDERGAIN(x)			((x) & 0x7)

/* EMAC_QSERDES_RX_RX_EQ_GAIN12 */

#define RX_EQ_GAIN2(x)				(((x) & 0xf) << 4)

#define RX_EQ_GAIN1(x)				((x) & 0xf)

/* EMAC_SGMII_PHY_SERDES_START */

#define SERDES_START				BIT(0)

/* EMAC_SGMII_PHY_CMN_PWR_CTRL */

#define BIAS_EN					BIT(6)

#define PLL_EN					BIT(5)

#define SYSCLK_EN				BIT(4)

#define CLKBUF_L_EN				BIT(3)

#define PLL_TXCLK_EN				BIT(1)

#define PLL_RXCLK_EN				BIT(0)

/* EMAC_SGMII_PHY_RX_PWR_CTRL */

#define L0_RX_SIGDET_EN				BIT(7)

#define L0_RX_TERM_MODE(x)			(((x) & 3) << 4)

#define L0_RX_I_EN				BIT(1)

/* EMAC_SGMII_PHY_TX_PWR_CTRL */

#define L0_TX_EN				BIT(5)

#define L0_CLKBUF_EN				BIT(4)

#define L0_TRAN_BIAS_EN				BIT(1)

/* EMAC_SGMII_PHY_LANE_CTRL1 */

#define L0_RX_EQUALIZE_ENABLE			BIT(6)

#define L0_RESET_TSYNC_EN			BIT(4)

#define L0_DRV_LVL(x)				((x) & 0xf)

/* EMAC_SGMII_PHY_AUTONEG_CFG2 */

#define FORCE_AN_TX_CFG				BIT(5)

#define FORCE_AN_RX_CFG				BIT(4)

#define AN_ENABLE				BIT(0)

/* EMAC_SGMII_PHY_SPEED_CFG1 */

#define DUPLEX_MODE				BIT(4)

#define SPDMODE_1000				BIT(1)

#define SPDMODE_100				BIT(0)

#define SPDMODE_10				0

#define SPDMODE_BMSK				3

#define SPDMODE_SHFT				0

/* EMAC_SGMII_PHY_POW_DWN_CTRL0 */

#define PWRDN_B					BIT(0)

#define CDR_MAX_CNT(x)				((x) & 0xff)

/* EMAC_QSERDES_TX_BIST_MODE_LANENO */

#define BIST_LANE_NUMBER(x)			(((x) & 3) << 5)

#define BISTMODE(x)				((x) & 0x1f)

/* EMAC_QSERDES_COM_PLLLOCK_CMPx */

#define PLLLOCK_CMP(x)				((x) & 0xff)

/* EMAC_SGMII_PHY_RESET_CTRL */

#define PHY_SW_RESET				BIT(0)

/* EMAC_SGMII_PHY_IRQ_CMD */

#define IRQ_GLOBAL_CLEAR			BIT(0)

/* EMAC_SGMII_PHY_INTERRUPT_MASK */

#define DECODE_CODE_ERR				BIT(7)

#define DECODE_DISP_ERR				BIT(6)

#define PLL_UNLOCK				BIT(5)

#define AN_ILLEGAL_TERM				BIT(4)

#define SYNC_FAIL				BIT(3)

#define AN_START				BIT(2)

#define AN_END					BIT(1)

#define AN_REQUEST				BIT(0)


#define SGMII_PHY_IRQ_CLR_WAIT_TIME		10


#define SGMII_PHY_INTERRUPT_ERR (\
        DECODE_CODE_ERR         |\
        DECODE_DISP_ERR)


#define SGMII_ISR_AN_MASK       (\
        AN_REQUEST              |\
        AN_START                |\
        AN_END                  |\
        AN_ILLEGAL_TERM         |\
        PLL_UNLOCK              |\
        SYNC_FAIL)


#define SGMII_ISR_MASK          (\
        SGMII_PHY_INTERRUPT_ERR |\
        SGMII_ISR_AN_MASK)

/* SGMII TX_CONFIG */

#define TXCFG_LINK				0x8000

#define TXCFG_MODE_BMSK				0x1c00

#define TXCFG_1000_FULL				0x1800

#define TXCFG_100_FULL				0x1400

#define TXCFG_100_HALF				0x0400

#define TXCFG_10_FULL				0x1000

#define TXCFG_10_HALF				0x0000


#define SERDES_START_WAIT_TIMES			100


struct emac_reg_write {
	
unsigned int offset;
	
u32 val;
};


static void emac_reg_write_all(void __iomem *base, const struct emac_reg_write *itr, size_t size) { size_t i; for (i = 0; i < size; ++itr, ++i) writel(itr->val, base + itr->offset); }

Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi52100.00%1100.00%
Total52100.00%1100.00%

static const struct emac_reg_write physical_coding_sublayer_programming_v1[] = { {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)}, {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B}, {EMAC_SGMII_PHY_CMN_PWR_CTRL, BIAS_EN | SYSCLK_EN | CLKBUF_L_EN | PLL_TXCLK_EN | PLL_RXCLK_EN}, {EMAC_SGMII_PHY_TX_PWR_CTRL, L0_TX_EN | L0_CLKBUF_EN | L0_TRAN_BIAS_EN}, {EMAC_SGMII_PHY_RX_PWR_CTRL, L0_RX_SIGDET_EN | L0_RX_TERM_MODE(1) | L0_RX_I_EN}, {EMAC_SGMII_PHY_CMN_PWR_CTRL, BIAS_EN | PLL_EN | SYSCLK_EN | CLKBUF_L_EN | PLL_TXCLK_EN | PLL_RXCLK_EN}, {EMAC_SGMII_PHY_LANE_CTRL1, L0_RX_EQUALIZE_ENABLE | L0_RESET_TSYNC_EN | L0_DRV_LVL(15)}, }; static const struct emac_reg_write sysclk_refclk_setting[] = { {EMAC_QSERDES_COM_SYSCLK_EN_SEL, SYSCLK_SEL_CMOS}, {EMAC_QSERDES_COM_SYS_CLK_CTRL, SYSCLK_CM | SYSCLK_AC_COUPLE}, }; static const struct emac_reg_write pll_setting[] = { {EMAC_QSERDES_COM_PLL_IP_SETI, PLL_IPSETI(1)}, {EMAC_QSERDES_COM_PLL_CP_SETI, PLL_CPSETI(59)}, {EMAC_QSERDES_COM_PLL_IP_SETP, PLL_IPSETP(10)}, {EMAC_QSERDES_COM_PLL_CP_SETP, PLL_CPSETP(9)}, {EMAC_QSERDES_COM_PLL_CRCTRL, PLL_RCTRL(15) | PLL_CCTRL(11)}, {EMAC_QSERDES_COM_PLL_CNTRL, OCP_EN | PLL_DIV_FFEN | PLL_DIV_ORD}, {EMAC_QSERDES_COM_DEC_START1, DEC_START1_MUX | DEC_START1(2)}, {EMAC_QSERDES_COM_DEC_START2, DEC_START2_MUX | DEC_START2}, {EMAC_QSERDES_COM_DIV_FRAC_START1, DIV_FRAC_START_MUX | DIV_FRAC_START(85)}, {EMAC_QSERDES_COM_DIV_FRAC_START2, DIV_FRAC_START_MUX | DIV_FRAC_START(42)}, {EMAC_QSERDES_COM_DIV_FRAC_START3, DIV_FRAC_START3_MUX | DIV_FRAC_START3(3)}, {EMAC_QSERDES_COM_PLLLOCK_CMP1, PLLLOCK_CMP(43)}, {EMAC_QSERDES_COM_PLLLOCK_CMP2, PLLLOCK_CMP(104)}, {EMAC_QSERDES_COM_PLLLOCK_CMP3, PLLLOCK_CMP(0)}, {EMAC_QSERDES_COM_PLLLOCK_CMP_EN, PLLLOCK_CMP_EN}, {EMAC_QSERDES_COM_RESETSM_CNTRL, FRQ_TUNE_MODE}, }; static const struct emac_reg_write cdr_setting[] = { {EMAC_QSERDES_RX_CDR_CONTROL, SECONDORDERENABLE | FIRSTORDER_THRESH(3) | SECONDORDERGAIN(2)}, {EMAC_QSERDES_RX_CDR_CONTROL2, SECONDORDERENABLE | FIRSTORDER_THRESH(3) | SECONDORDERGAIN(4)}, }; static const struct emac_reg_write tx_rx_setting[] = { {EMAC_QSERDES_TX_BIST_MODE_LANENO, 0}, {EMAC_QSERDES_TX_TX_DRV_LVL, TX_DRV_LVL_MUX | TX_DRV_LVL(15)}, {EMAC_QSERDES_TX_TRAN_DRVR_EMP_EN, EMP_EN_MUX | EMP_EN}, {EMAC_QSERDES_TX_TX_EMP_POST1_LVL, TX_EMP_POST1_LVL_MUX | TX_EMP_POST1_LVL(1)}, {EMAC_QSERDES_RX_RX_EQ_GAIN12, RX_EQ_GAIN2(15) | RX_EQ_GAIN1(15)}, {EMAC_QSERDES_TX_LANE_MODE, LANE_MODE(8)}, }; static const struct emac_reg_write sgmii_v2_laned[] = { /* CDR Settings */ {EMAC_SGMII_LN_UCDR_FO_GAIN_MODE0, UCDR_STEP_BY_TWO_MODE0 | UCDR_xO_GAIN_MODE(10)}, {EMAC_SGMII_LN_UCDR_SO_GAIN_MODE0, UCDR_xO_GAIN_MODE(0)}, {EMAC_SGMII_LN_UCDR_SO_CONFIG, UCDR_ENABLE | UCDR_SO_SATURATION(12)}, /* TX/RX Settings */ {EMAC_SGMII_LN_RX_EN_SIGNAL, SIGDET_LP_BYP_PS4 | SIGDET_EN_PS0_TO_PS2}, {EMAC_SGMII_LN_DRVR_CTRL0, TXVAL_VALID_INIT | KR_PCIGEN3_MODE}, {EMAC_SGMII_LN_DRVR_TAP_EN, MAIN_EN}, {EMAC_SGMII_LN_TX_MARGINING, TX_MARGINING_MUX | TX_MARGINING(25)}, {EMAC_SGMII_LN_TX_PRE, TX_PRE_MUX}, {EMAC_SGMII_LN_TX_POST, TX_POST_MUX}, {EMAC_SGMII_LN_CML_CTRL_MODE0, CML_GEAR_MODE(1) | CML2CMOS_IBOOST_MODE(1)}, {EMAC_SGMII_LN_MIXER_CTRL_MODE0, MIXER_LOADB_MODE(12) | MIXER_DATARATE_MODE(1)}, {EMAC_SGMII_LN_VGA_INITVAL, VGA_THRESH_DFE(31)}, {EMAC_SGMII_LN_SIGDET_ENABLES, SIGDET_LP_BYP_PS0_TO_PS2 | SIGDET_FLT_BYP}, {EMAC_SGMII_LN_SIGDET_CNTRL, SIGDET_LVL(8)}, {EMAC_SGMII_LN_SIGDET_DEGLITCH_CNTRL, SIGDET_DEGLITCH_CTRL(4)}, {EMAC_SGMII_LN_RX_MISC_CNTRL0, 0}, {EMAC_SGMII_LN_DRVR_LOGIC_CLKDIV, DRVR_LOGIC_CLK_EN | DRVR_LOGIC_CLK_DIV(4)}, {EMAC_SGMII_LN_PARALLEL_RATE, PARALLEL_RATE_MODE0(1)}, {EMAC_SGMII_LN_TX_BAND_MODE, BAND_MODE0(2)}, {EMAC_SGMII_LN_RX_BAND, BAND_MODE0(3)}, {EMAC_SGMII_LN_LANE_MODE, LANE_MODE(26)}, {EMAC_SGMII_LN_RX_RCVR_PATH1_MODE0, CDR_PD_SEL_MODE0(3)}, {EMAC_SGMII_LN_RSM_CONFIG, BYPASS_RSM_SAMP_CAL | BYPASS_RSM_DLL_CAL}, }; static const struct emac_reg_write physical_coding_sublayer_programming_v2[] = { {EMAC_SGMII_PHY_POW_DWN_CTRL0, PWRDN_B}, {EMAC_SGMII_PHY_CDR_CTRL0, CDR_MAX_CNT(15)}, {EMAC_SGMII_PHY_TX_PWR_CTRL, 0}, {EMAC_SGMII_PHY_LANE_CTRL1, L0_RX_EQUALIZE_ENABLE}, };
static int emac_sgmii_link_init(struct emac_adapter *adpt) { struct phy_device *phydev = adpt->phydev; struct emac_phy *phy = &adpt->phy; u32 val; val = readl(phy->base + EMAC_SGMII_PHY_AUTONEG_CFG2); if (phydev->autoneg == AUTONEG_ENABLE) { val &= ~(FORCE_AN_RX_CFG | FORCE_AN_TX_CFG); val |= AN_ENABLE; writel(val, phy->base + EMAC_SGMII_PHY_AUTONEG_CFG2); } else { u32 speed_cfg; switch (phydev->speed) { case SPEED_10: speed_cfg = SPDMODE_10; break; case SPEED_100: speed_cfg = SPDMODE_100; break; case SPEED_1000: speed_cfg = SPDMODE_1000; break; default: return -EINVAL; } if (phydev->duplex == DUPLEX_FULL) speed_cfg |= DUPLEX_MODE; val &= ~AN_ENABLE; writel(speed_cfg, phy->base + EMAC_SGMII_PHY_SPEED_CFG1); writel(val, phy->base + EMAC_SGMII_PHY_AUTONEG_CFG2); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi163100.00%1100.00%
Total163100.00%1100.00%


static int emac_sgmii_irq_clear(struct emac_adapter *adpt, u32 irq_bits) { struct emac_phy *phy = &adpt->phy; u32 status; writel_relaxed(irq_bits, phy->base + EMAC_SGMII_PHY_INTERRUPT_CLEAR); writel_relaxed(IRQ_GLOBAL_CLEAR, phy->base + EMAC_SGMII_PHY_IRQ_CMD); /* Ensure interrupt clear command is written to HW */ wmb(); /* After set the IRQ_GLOBAL_CLEAR bit, the status clearing must * be confirmed before clearing the bits in other registers. * It takes a few cycles for hw to clear the interrupt status. */ if (readl_poll_timeout_atomic(phy->base + EMAC_SGMII_PHY_INTERRUPT_STATUS, status, !(status & irq_bits), 1, SGMII_PHY_IRQ_CLR_WAIT_TIME)) { netdev_err(adpt->netdev, "error: failed clear SGMII irq: status:0x%x bits:0x%x\n", status, irq_bits); return -EIO; } /* Finalize clearing procedure */ writel_relaxed(0, phy->base + EMAC_SGMII_PHY_IRQ_CMD); writel_relaxed(0, phy->base + EMAC_SGMII_PHY_INTERRUPT_CLEAR); /* Ensure that clearing procedure finalization is written to HW */ wmb(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi127100.00%1100.00%
Total127100.00%1100.00%


int emac_sgmii_init_v1(struct emac_adapter *adpt) { struct emac_phy *phy = &adpt->phy; unsigned int i; int ret; ret = emac_sgmii_link_init(adpt); if (ret) return ret; emac_reg_write_all(phy->base, physical_coding_sublayer_programming_v1, ARRAY_SIZE(physical_coding_sublayer_programming_v1)); emac_reg_write_all(phy->base, sysclk_refclk_setting, ARRAY_SIZE(sysclk_refclk_setting)); emac_reg_write_all(phy->base, pll_setting, ARRAY_SIZE(pll_setting)); emac_reg_write_all(phy->base, cdr_setting, ARRAY_SIZE(cdr_setting)); emac_reg_write_all(phy->base, tx_rx_setting, ARRAY_SIZE(tx_rx_setting)); /* Power up the Ser/Des engine */ writel(SERDES_START, phy->base + EMAC_SGMII_PHY_SERDES_START); for (i = 0; i < SERDES_START_WAIT_TIMES; i++) { if (readl(phy->base + EMAC_QSERDES_COM_RESET_SM) & READY) break; usleep_range(100, 200); } if (i == SERDES_START_WAIT_TIMES) { netdev_err(adpt->netdev, "error: ser/des failed to start\n"); return -EIO; } /* Mask out all the SGMII Interrupt */ writel(0, phy->base + EMAC_SGMII_PHY_INTERRUPT_MASK); emac_sgmii_irq_clear(adpt, SGMII_PHY_INTERRUPT_ERR); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi202100.00%1100.00%
Total202100.00%1100.00%


int emac_sgmii_init_v2(struct emac_adapter *adpt) { struct emac_phy *phy = &adpt->phy; void __iomem *phy_regs = phy->base; void __iomem *laned = phy->digital; unsigned int i; u32 lnstatus; int ret; ret = emac_sgmii_link_init(adpt); if (ret) return ret; /* PCS lane-x init */ emac_reg_write_all(phy->base, physical_coding_sublayer_programming_v2, ARRAY_SIZE(physical_coding_sublayer_programming_v2)); /* SGMII lane-x init */ emac_reg_write_all(phy->digital, sgmii_v2_laned, ARRAY_SIZE(sgmii_v2_laned)); /* Power up PCS and start reset lane state machine */ writel(0, phy_regs + EMAC_SGMII_PHY_RESET_CTRL); writel(1, laned + SGMII_LN_RSM_START); /* Wait for c_ready assertion */ for (i = 0; i < SERDES_START_WAIT_TIMES; i++) { lnstatus = readl(phy_regs + SGMII_PHY_LN_LANE_STATUS); if (lnstatus & BIT(1)) break; usleep_range(100, 200); } if (i == SERDES_START_WAIT_TIMES) { netdev_err(adpt->netdev, "SGMII failed to start\n"); return -EIO; } /* Disable digital and SERDES loopback */ writel(0, phy_regs + SGMII_PHY_LN_BIST_GEN0); writel(0, phy_regs + SGMII_PHY_LN_BIST_GEN2); writel(0, phy_regs + SGMII_PHY_LN_CDR_CTRL1); /* Mask out all the SGMII Interrupt */ writel(0, phy_regs + EMAC_SGMII_PHY_INTERRUPT_MASK); emac_sgmii_irq_clear(adpt, SGMII_PHY_INTERRUPT_ERR); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi222100.00%1100.00%
Total222100.00%1100.00%


static void emac_sgmii_reset_prepare(struct emac_adapter *adpt) { struct emac_phy *phy = &adpt->phy; u32 val; /* Reset PHY */ val = readl(phy->base + EMAC_EMAC_WRAPPER_CSR2); writel(((val & ~PHY_RESET) | PHY_RESET), phy->base + EMAC_EMAC_WRAPPER_CSR2); /* Ensure phy-reset command is written to HW before the release cmd */ msleep(50); val = readl(phy->base + EMAC_EMAC_WRAPPER_CSR2); writel((val & ~PHY_RESET), phy->base + EMAC_EMAC_WRAPPER_CSR2); /* Ensure phy-reset release command is written to HW before initializing * SGMII */ msleep(50); }

Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi95100.00%1100.00%
Total95100.00%1100.00%


void emac_sgmii_reset(struct emac_adapter *adpt) { int ret; clk_set_rate(adpt->clk[EMAC_CLK_HIGH_SPEED], 19200000); emac_sgmii_reset_prepare(adpt); ret = adpt->phy.initialize(adpt); if (ret) netdev_err(adpt->netdev, "could not reinitialize internal PHY (error=%i)\n", ret); clk_set_rate(adpt->clk[EMAC_CLK_HIGH_SPEED], 125000000); }

Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi68100.00%1100.00%
Total68100.00%1100.00%


static int emac_sgmii_acpi_match(struct device *dev, void *data) { static const struct acpi_device_id match_table[] = { { .id = "QCOM8071", .driver_data = (kernel_ulong_t)emac_sgmii_init_v2, }, {} }; const struct acpi_device_id *id = acpi_match_device(match_table, dev); emac_sgmii_initialize *initialize = data; if (id) *initialize = (emac_sgmii_initialize)id->driver_data; return !!id; }

Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi79100.00%1100.00%
Total79100.00%1100.00%

static const struct of_device_id emac_sgmii_dt_match[] = { { .compatible = "qcom,fsm9900-emac-sgmii", .data = emac_sgmii_init_v1, }, { .compatible = "qcom,qdf2432-emac-sgmii", .data = emac_sgmii_init_v2, }, {} };
int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt) { struct platform_device *sgmii_pdev = NULL; struct emac_phy *phy = &adpt->phy; struct resource *res; int ret; if (has_acpi_companion(&pdev->dev)) { struct device *dev; dev = device_find_child(&pdev->dev, &phy->initialize, emac_sgmii_acpi_match); if (!dev) { dev_err(&pdev->dev, "cannot find internal phy node\n"); return -ENODEV; } sgmii_pdev = to_platform_device(dev); } else { const struct of_device_id *match; struct device_node *np; np = of_parse_phandle(pdev->dev.of_node, "internal-phy", 0); if (!np) { dev_err(&pdev->dev, "missing internal-phy property\n"); return -ENODEV; } sgmii_pdev = of_find_device_by_node(np); if (!sgmii_pdev) { dev_err(&pdev->dev, "invalid internal-phy property\n"); return -ENODEV; } match = of_match_device(emac_sgmii_dt_match, &sgmii_pdev->dev); if (!match) { dev_err(&pdev->dev, "unrecognized internal phy node\n"); ret = -ENODEV; goto error_put_device; } phy->initialize = (emac_sgmii_initialize)match->data; } /* Base address is the first address */ res = platform_get_resource(sgmii_pdev, IORESOURCE_MEM, 0); if (!res) { ret = -EINVAL; goto error_put_device; } phy->base = ioremap(res->start, resource_size(res)); if (!phy->base) { ret = -ENOMEM; goto error_put_device; } /* v2 SGMII has a per-lane digital digital, so parse it if it exists */ res = platform_get_resource(sgmii_pdev, IORESOURCE_MEM, 1); if (res) { phy->digital = ioremap(res->start, resource_size(res)); if (!phy->digital) { ret = -ENOMEM; goto error_unmap_base; } } ret = phy->initialize(adpt); if (ret) goto error; /* We've remapped the addresses, so we don't need the device any * more. of_find_device_by_node() says we should release it. */ put_device(&sgmii_pdev->dev); return 0; error: if (phy->digital) iounmap(phy->digital); error_unmap_base: iounmap(phy->base); error_put_device: put_device(&sgmii_pdev->dev); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi38394.80%375.00%
wei yongjunwei yongjun215.20%125.00%
Total404100.00%4100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
timur tabitimur tabi319199.35%480.00%
wei yongjunwei yongjun210.65%120.00%
Total3212100.00%5100.00%