162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2023, Linaro Limited
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/clk.h>
762306a36Sopenharmony_ci#include <linux/ethtool.h>
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/of.h>
1062306a36Sopenharmony_ci#include <linux/phy/phy.h>
1162306a36Sopenharmony_ci#include <linux/platform_device.h>
1262306a36Sopenharmony_ci#include <linux/regmap.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define QSERDES_QMP_PLL					0x0
1562306a36Sopenharmony_ci#define QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0		(QSERDES_QMP_PLL + 0x1ac)
1662306a36Sopenharmony_ci#define QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0		(QSERDES_QMP_PLL + 0x1b0)
1762306a36Sopenharmony_ci#define QSERDES_COM_BIN_VCOCAL_HSCLK_SEL		(QSERDES_QMP_PLL + 0x1bc)
1862306a36Sopenharmony_ci#define QSERDES_COM_CORE_CLK_EN				(QSERDES_QMP_PLL + 0x174)
1962306a36Sopenharmony_ci#define QSERDES_COM_CORECLK_DIV_MODE0			(QSERDES_QMP_PLL + 0x168)
2062306a36Sopenharmony_ci#define QSERDES_COM_CP_CTRL_MODE0			(QSERDES_QMP_PLL + 0x74)
2162306a36Sopenharmony_ci#define QSERDES_COM_DEC_START_MODE0			(QSERDES_QMP_PLL + 0xbc)
2262306a36Sopenharmony_ci#define QSERDES_COM_DIV_FRAC_START1_MODE0		(QSERDES_QMP_PLL + 0xcc)
2362306a36Sopenharmony_ci#define QSERDES_COM_DIV_FRAC_START2_MODE0		(QSERDES_QMP_PLL + 0xd0)
2462306a36Sopenharmony_ci#define QSERDES_COM_DIV_FRAC_START3_MODE0		(QSERDES_QMP_PLL + 0xd4)
2562306a36Sopenharmony_ci#define QSERDES_COM_HSCLK_HS_SWITCH_SEL			(QSERDES_QMP_PLL + 0x15c)
2662306a36Sopenharmony_ci#define QSERDES_COM_HSCLK_SEL				(QSERDES_QMP_PLL + 0x158)
2762306a36Sopenharmony_ci#define QSERDES_COM_LOCK_CMP1_MODE0			(QSERDES_QMP_PLL + 0xac)
2862306a36Sopenharmony_ci#define QSERDES_COM_LOCK_CMP2_MODE0			(QSERDES_QMP_PLL + 0xb0)
2962306a36Sopenharmony_ci#define QSERDES_COM_PLL_CCTRL_MODE0			(QSERDES_QMP_PLL + 0x84)
3062306a36Sopenharmony_ci#define QSERDES_COM_PLL_IVCO				(QSERDES_QMP_PLL + 0x58)
3162306a36Sopenharmony_ci#define QSERDES_COM_PLL_RCTRL_MODE0			(QSERDES_QMP_PLL + 0x7c)
3262306a36Sopenharmony_ci#define QSERDES_COM_SYSCLK_EN_SEL			(QSERDES_QMP_PLL + 0x94)
3362306a36Sopenharmony_ci#define QSERDES_COM_VCO_TUNE1_MODE0			(QSERDES_QMP_PLL + 0x110)
3462306a36Sopenharmony_ci#define QSERDES_COM_VCO_TUNE2_MODE0			(QSERDES_QMP_PLL + 0x114)
3562306a36Sopenharmony_ci#define QSERDES_COM_VCO_TUNE_INITVAL2			(QSERDES_QMP_PLL + 0x124)
3662306a36Sopenharmony_ci#define QSERDES_COM_C_READY_STATUS			(QSERDES_QMP_PLL + 0x178)
3762306a36Sopenharmony_ci#define QSERDES_COM_CMN_STATUS				(QSERDES_QMP_PLL + 0x140)
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define QSERDES_RX					0x600
4062306a36Sopenharmony_ci#define QSERDES_RX_UCDR_FO_GAIN				(QSERDES_RX + 0x8)
4162306a36Sopenharmony_ci#define QSERDES_RX_UCDR_SO_GAIN				(QSERDES_RX + 0x14)
4262306a36Sopenharmony_ci#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN		(QSERDES_RX + 0x30)
4362306a36Sopenharmony_ci#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE	(QSERDES_RX + 0x34)
4462306a36Sopenharmony_ci#define QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW		(QSERDES_RX + 0x3c)
4562306a36Sopenharmony_ci#define QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH		(QSERDES_RX + 0x40)
4662306a36Sopenharmony_ci#define QSERDES_RX_UCDR_PI_CONTROLS			(QSERDES_RX + 0x44)
4762306a36Sopenharmony_ci#define QSERDES_RX_UCDR_PI_CTRL2			(QSERDES_RX + 0x48)
4862306a36Sopenharmony_ci#define QSERDES_RX_RX_TERM_BW				(QSERDES_RX + 0x80)
4962306a36Sopenharmony_ci#define QSERDES_RX_VGA_CAL_CNTRL2			(QSERDES_RX + 0xd8)
5062306a36Sopenharmony_ci#define QSERDES_RX_GM_CAL				(QSERDES_RX + 0xdc)
5162306a36Sopenharmony_ci#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1		(QSERDES_RX + 0xe8)
5262306a36Sopenharmony_ci#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2		(QSERDES_RX + 0xec)
5362306a36Sopenharmony_ci#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3		(QSERDES_RX + 0xf0)
5462306a36Sopenharmony_ci#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4		(QSERDES_RX + 0xf4)
5562306a36Sopenharmony_ci#define QSERDES_RX_RX_IDAC_TSETTLE_LOW			(QSERDES_RX + 0xf8)
5662306a36Sopenharmony_ci#define QSERDES_RX_RX_IDAC_TSETTLE_HIGH			(QSERDES_RX + 0xfc)
5762306a36Sopenharmony_ci#define QSERDES_RX_RX_IDAC_MEASURE_TIME			(QSERDES_RX + 0x100)
5862306a36Sopenharmony_ci#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1		(QSERDES_RX + 0x110)
5962306a36Sopenharmony_ci#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2		(QSERDES_RX + 0x114)
6062306a36Sopenharmony_ci#define QSERDES_RX_SIGDET_CNTRL				(QSERDES_RX + 0x11c)
6162306a36Sopenharmony_ci#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL		(QSERDES_RX + 0x124)
6262306a36Sopenharmony_ci#define QSERDES_RX_RX_BAND				(QSERDES_RX + 0x128)
6362306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_00_LOW			(QSERDES_RX + 0x15c)
6462306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_00_HIGH			(QSERDES_RX + 0x160)
6562306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_00_HIGH2			(QSERDES_RX + 0x164)
6662306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_00_HIGH3			(QSERDES_RX + 0x168)
6762306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_00_HIGH4			(QSERDES_RX + 0x16c)
6862306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_01_LOW			(QSERDES_RX + 0x170)
6962306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_01_HIGH			(QSERDES_RX + 0x174)
7062306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_01_HIGH2			(QSERDES_RX + 0x178)
7162306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_01_HIGH3			(QSERDES_RX + 0x17c)
7262306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_01_HIGH4			(QSERDES_RX + 0x180)
7362306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_10_LOW			(QSERDES_RX + 0x184)
7462306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_10_HIGH			(QSERDES_RX + 0x188)
7562306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_10_HIGH2			(QSERDES_RX + 0x18c)
7662306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_10_HIGH3			(QSERDES_RX + 0x190)
7762306a36Sopenharmony_ci#define QSERDES_RX_RX_MODE_10_HIGH4			(QSERDES_RX + 0x194)
7862306a36Sopenharmony_ci#define QSERDES_RX_DCC_CTRL1				(QSERDES_RX + 0x1a8)
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define QSERDES_TX					0x400
8162306a36Sopenharmony_ci#define QSERDES_TX_TX_BAND				(QSERDES_TX + 0x24)
8262306a36Sopenharmony_ci#define QSERDES_TX_SLEW_CNTL				(QSERDES_TX + 0x28)
8362306a36Sopenharmony_ci#define QSERDES_TX_RES_CODE_LANE_OFFSET_TX		(QSERDES_TX + 0x3c)
8462306a36Sopenharmony_ci#define QSERDES_TX_RES_CODE_LANE_OFFSET_RX		(QSERDES_TX + 0x40)
8562306a36Sopenharmony_ci#define QSERDES_TX_LANE_MODE_1				(QSERDES_TX + 0x84)
8662306a36Sopenharmony_ci#define QSERDES_TX_LANE_MODE_3				(QSERDES_TX + 0x8c)
8762306a36Sopenharmony_ci#define QSERDES_TX_RCV_DETECT_LVL_2			(QSERDES_TX + 0xa4)
8862306a36Sopenharmony_ci#define QSERDES_TX_TRAN_DRVR_EMP_EN			(QSERDES_TX + 0xc0)
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define QSERDES_PCS					0xC00
9162306a36Sopenharmony_ci#define QSERDES_PCS_PHY_START				(QSERDES_PCS + 0x0)
9262306a36Sopenharmony_ci#define QSERDES_PCS_POWER_DOWN_CONTROL			(QSERDES_PCS + 0x4)
9362306a36Sopenharmony_ci#define QSERDES_PCS_SW_RESET				(QSERDES_PCS + 0x8)
9462306a36Sopenharmony_ci#define QSERDES_PCS_LINE_RESET_TIME			(QSERDES_PCS + 0xc)
9562306a36Sopenharmony_ci#define QSERDES_PCS_TX_LARGE_AMP_DRV_LVL		(QSERDES_PCS + 0x20)
9662306a36Sopenharmony_ci#define QSERDES_PCS_TX_SMALL_AMP_DRV_LVL		(QSERDES_PCS + 0x28)
9762306a36Sopenharmony_ci#define QSERDES_PCS_TX_MID_TERM_CTRL1			(QSERDES_PCS + 0xd8)
9862306a36Sopenharmony_ci#define QSERDES_PCS_TX_MID_TERM_CTRL2			(QSERDES_PCS + 0xdc)
9962306a36Sopenharmony_ci#define QSERDES_PCS_SGMII_MISC_CTRL8			(QSERDES_PCS + 0x118)
10062306a36Sopenharmony_ci#define QSERDES_PCS_PCS_READY_STATUS			(QSERDES_PCS + 0x94)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci#define QSERDES_COM_C_READY				BIT(0)
10362306a36Sopenharmony_ci#define QSERDES_PCS_READY				BIT(0)
10462306a36Sopenharmony_ci#define QSERDES_PCS_SGMIIPHY_READY			BIT(7)
10562306a36Sopenharmony_ci#define QSERDES_COM_C_PLL_LOCKED			BIT(1)
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistruct qcom_dwmac_sgmii_phy_data {
10862306a36Sopenharmony_ci	struct regmap *regmap;
10962306a36Sopenharmony_ci	struct clk *refclk;
11062306a36Sopenharmony_ci	int speed;
11162306a36Sopenharmony_ci};
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistatic void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
11662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
11962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
12062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
12162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
12262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
12362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A);
12462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A);
12562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x82);
12662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
12762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
12862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
12962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0x24);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
13262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
13362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x04);
13462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
13562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x0A);
13662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
13762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9);
13862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E);
13962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_TX_BAND, 0x05);
14262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
14362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
14462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x09);
14562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
14662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
14762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
14862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
15162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
15262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
15362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
15462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
15562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
15662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
15762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
15862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x04);
15962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
16062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
16162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
16262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
16362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
16462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
16562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
16662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
16762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
16862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
16962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
17062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
17162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
17262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_BAND, 0x05);
17362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0xE0);
17462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
17562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
17662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x09);
17762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB1);
17862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
17962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
18062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
18162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
18262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
18362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
18462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
18562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
18662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
18762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
18862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
19162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
19262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
19362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
19462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
19562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x0C);
19662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
20462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
20762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
20862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
20962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
21062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
21162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x1A);
21262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x41);
21362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x7A);
21462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
21562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x20);
21662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x01);
21762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0xA1);
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
22062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
22162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x03);
22262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
22362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x05);
22462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
22562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD);
22662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C);
22762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_TX_BAND, 0x04);
23062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
23162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
23262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x02);
23362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
23462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
23562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
23662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
23962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
24062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
24162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
24262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
24362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
24462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
24562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
24662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x00);
24762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
24862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
24962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
25062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
25162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
25262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
25362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
25462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
25562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
25662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
25762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
25862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
25962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
26062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_BAND, 0x18);
26162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0x18);
26262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
26362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
26462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x0C);
26562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB8);
26662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
26762306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
26862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
26962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
27062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
27162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
27262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
27362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
27462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
27562306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
27662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
27962306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
28062306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
28162306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
28262306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
28362306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x8C);
28462306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_cistatic inline int
29062306a36Sopenharmony_ciqcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg,
29162306a36Sopenharmony_ci				 unsigned int bit)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	unsigned int val;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	return regmap_read_poll_timeout(regmap, reg, val,
29662306a36Sopenharmony_ci					val & bit, 1500, 750000);
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
30262306a36Sopenharmony_ci	struct device *dev = phy->dev.parent;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	switch (data->speed) {
30562306a36Sopenharmony_ci	case SPEED_10:
30662306a36Sopenharmony_ci	case SPEED_100:
30762306a36Sopenharmony_ci	case SPEED_1000:
30862306a36Sopenharmony_ci		qcom_dwmac_sgmii_phy_init_1g(data->regmap);
30962306a36Sopenharmony_ci		break;
31062306a36Sopenharmony_ci	case SPEED_2500:
31162306a36Sopenharmony_ci		qcom_dwmac_sgmii_phy_init_2p5g(data->regmap);
31262306a36Sopenharmony_ci		break;
31362306a36Sopenharmony_ci	}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
31662306a36Sopenharmony_ci					     QSERDES_COM_C_READY_STATUS,
31762306a36Sopenharmony_ci					     QSERDES_COM_C_READY)) {
31862306a36Sopenharmony_ci		dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out");
31962306a36Sopenharmony_ci		return -ETIMEDOUT;
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
32362306a36Sopenharmony_ci					     QSERDES_PCS_PCS_READY_STATUS,
32462306a36Sopenharmony_ci					     QSERDES_PCS_READY)) {
32562306a36Sopenharmony_ci		dev_err(dev, "PCS_READY timed-out");
32662306a36Sopenharmony_ci		return -ETIMEDOUT;
32762306a36Sopenharmony_ci	}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
33062306a36Sopenharmony_ci					     QSERDES_PCS_PCS_READY_STATUS,
33162306a36Sopenharmony_ci					     QSERDES_PCS_SGMIIPHY_READY)) {
33262306a36Sopenharmony_ci		dev_err(dev, "SGMIIPHY_READY timed-out");
33362306a36Sopenharmony_ci		return -ETIMEDOUT;
33462306a36Sopenharmony_ci	}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
33762306a36Sopenharmony_ci					     QSERDES_COM_CMN_STATUS,
33862306a36Sopenharmony_ci					     QSERDES_COM_C_PLL_LOCKED)) {
33962306a36Sopenharmony_ci		dev_err(dev, "PLL Lock Status timed-out");
34062306a36Sopenharmony_ci		return -ETIMEDOUT;
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	return 0;
34462306a36Sopenharmony_ci}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_cistatic int qcom_dwmac_sgmii_phy_power_on(struct phy *phy)
34762306a36Sopenharmony_ci{
34862306a36Sopenharmony_ci	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	return clk_prepare_enable(data->refclk);
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_cistatic int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
35462306a36Sopenharmony_ci{
35562306a36Sopenharmony_ci	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	regmap_write(data->regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
35862306a36Sopenharmony_ci	regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x01);
35962306a36Sopenharmony_ci	udelay(100);
36062306a36Sopenharmony_ci	regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x00);
36162306a36Sopenharmony_ci	regmap_write(data->regmap, QSERDES_PCS_PHY_START, 0x01);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	clk_disable_unprepare(data->refclk);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	return 0;
36662306a36Sopenharmony_ci}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_cistatic int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
36962306a36Sopenharmony_ci{
37062306a36Sopenharmony_ci	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	if (speed != data->speed)
37362306a36Sopenharmony_ci		data->speed = speed;
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	return qcom_dwmac_sgmii_phy_calibrate(phy);
37662306a36Sopenharmony_ci}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_cistatic const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
37962306a36Sopenharmony_ci	.power_on	= qcom_dwmac_sgmii_phy_power_on,
38062306a36Sopenharmony_ci	.power_off	= qcom_dwmac_sgmii_phy_power_off,
38162306a36Sopenharmony_ci	.set_speed	= qcom_dwmac_sgmii_phy_set_speed,
38262306a36Sopenharmony_ci	.calibrate	= qcom_dwmac_sgmii_phy_calibrate,
38362306a36Sopenharmony_ci	.owner		= THIS_MODULE,
38462306a36Sopenharmony_ci};
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = {
38762306a36Sopenharmony_ci	.reg_bits		= 32,
38862306a36Sopenharmony_ci	.val_bits		= 32,
38962306a36Sopenharmony_ci	.reg_stride		= 4,
39062306a36Sopenharmony_ci	.use_relaxed_mmio	= true,
39162306a36Sopenharmony_ci	.disable_locking	= true,
39262306a36Sopenharmony_ci};
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_cistatic int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
39562306a36Sopenharmony_ci{
39662306a36Sopenharmony_ci	struct qcom_dwmac_sgmii_phy_data *data;
39762306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
39862306a36Sopenharmony_ci	struct phy_provider *provider;
39962306a36Sopenharmony_ci	void __iomem *base;
40062306a36Sopenharmony_ci	struct phy *phy;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
40362306a36Sopenharmony_ci	if (!data)
40462306a36Sopenharmony_ci		return -ENOMEM;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	data->speed = SPEED_10;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	base = devm_platform_ioremap_resource(pdev, 0);
40962306a36Sopenharmony_ci	if (IS_ERR(base))
41062306a36Sopenharmony_ci		return PTR_ERR(base);
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	data->regmap = devm_regmap_init_mmio(dev, base,
41362306a36Sopenharmony_ci					     &qcom_dwmac_sgmii_phy_regmap_cfg);
41462306a36Sopenharmony_ci	if (IS_ERR(data->regmap))
41562306a36Sopenharmony_ci		return PTR_ERR(data->regmap);
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);
41862306a36Sopenharmony_ci	if (IS_ERR(phy))
41962306a36Sopenharmony_ci		return PTR_ERR(phy);
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	data->refclk = devm_clk_get(dev, "sgmi_ref");
42262306a36Sopenharmony_ci	if (IS_ERR(data->refclk))
42362306a36Sopenharmony_ci		return PTR_ERR(data->refclk);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
42662306a36Sopenharmony_ci	if (IS_ERR(provider))
42762306a36Sopenharmony_ci		return PTR_ERR(provider);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	phy_set_drvdata(phy, data);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	return 0;
43262306a36Sopenharmony_ci}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cistatic const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {
43562306a36Sopenharmony_ci	{ .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },
43662306a36Sopenharmony_ci	{ },
43762306a36Sopenharmony_ci};
43862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_cistatic struct platform_driver qcom_dwmac_sgmii_phy_driver = {
44162306a36Sopenharmony_ci	.probe	= qcom_dwmac_sgmii_phy_probe,
44262306a36Sopenharmony_ci	.driver = {
44362306a36Sopenharmony_ci		.name	= "qcom-dwmac-sgmii-phy",
44462306a36Sopenharmony_ci		.of_match_table	= qcom_dwmac_sgmii_phy_of_match,
44562306a36Sopenharmony_ci	}
44662306a36Sopenharmony_ci};
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_cimodule_platform_driver(qcom_dwmac_sgmii_phy_driver);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ciMODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");
45162306a36Sopenharmony_ciMODULE_LICENSE("GPL");
452