Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.14.15.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2023, Linaro Limited
  4 */
  5
  6#include <linux/clk.h>
  7#include <linux/ethtool.h>
  8#include <linux/module.h>
  9#include <linux/of.h>
 10#include <linux/phy/phy.h>
 11#include <linux/platform_device.h>
 12#include <linux/regmap.h>
 13
 14#define QSERDES_QMP_PLL					0x0
 15#define QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0		(QSERDES_QMP_PLL + 0x1ac)
 16#define QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0		(QSERDES_QMP_PLL + 0x1b0)
 17#define QSERDES_COM_BIN_VCOCAL_HSCLK_SEL		(QSERDES_QMP_PLL + 0x1bc)
 18#define QSERDES_COM_CORE_CLK_EN				(QSERDES_QMP_PLL + 0x174)
 19#define QSERDES_COM_CORECLK_DIV_MODE0			(QSERDES_QMP_PLL + 0x168)
 20#define QSERDES_COM_CP_CTRL_MODE0			(QSERDES_QMP_PLL + 0x74)
 21#define QSERDES_COM_DEC_START_MODE0			(QSERDES_QMP_PLL + 0xbc)
 22#define QSERDES_COM_DIV_FRAC_START1_MODE0		(QSERDES_QMP_PLL + 0xcc)
 23#define QSERDES_COM_DIV_FRAC_START2_MODE0		(QSERDES_QMP_PLL + 0xd0)
 24#define QSERDES_COM_DIV_FRAC_START3_MODE0		(QSERDES_QMP_PLL + 0xd4)
 25#define QSERDES_COM_HSCLK_HS_SWITCH_SEL			(QSERDES_QMP_PLL + 0x15c)
 26#define QSERDES_COM_HSCLK_SEL				(QSERDES_QMP_PLL + 0x158)
 27#define QSERDES_COM_LOCK_CMP1_MODE0			(QSERDES_QMP_PLL + 0xac)
 28#define QSERDES_COM_LOCK_CMP2_MODE0			(QSERDES_QMP_PLL + 0xb0)
 29#define QSERDES_COM_PLL_CCTRL_MODE0			(QSERDES_QMP_PLL + 0x84)
 30#define QSERDES_COM_PLL_IVCO				(QSERDES_QMP_PLL + 0x58)
 31#define QSERDES_COM_PLL_RCTRL_MODE0			(QSERDES_QMP_PLL + 0x7c)
 32#define QSERDES_COM_SYSCLK_EN_SEL			(QSERDES_QMP_PLL + 0x94)
 33#define QSERDES_COM_VCO_TUNE1_MODE0			(QSERDES_QMP_PLL + 0x110)
 34#define QSERDES_COM_VCO_TUNE2_MODE0			(QSERDES_QMP_PLL + 0x114)
 35#define QSERDES_COM_VCO_TUNE_INITVAL2			(QSERDES_QMP_PLL + 0x124)
 36#define QSERDES_COM_C_READY_STATUS			(QSERDES_QMP_PLL + 0x178)
 37#define QSERDES_COM_CMN_STATUS				(QSERDES_QMP_PLL + 0x140)
 38
 39#define QSERDES_RX					0x600
 40#define QSERDES_RX_UCDR_FO_GAIN				(QSERDES_RX + 0x8)
 41#define QSERDES_RX_UCDR_SO_GAIN				(QSERDES_RX + 0x14)
 42#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN		(QSERDES_RX + 0x30)
 43#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE	(QSERDES_RX + 0x34)
 44#define QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW		(QSERDES_RX + 0x3c)
 45#define QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH		(QSERDES_RX + 0x40)
 46#define QSERDES_RX_UCDR_PI_CONTROLS			(QSERDES_RX + 0x44)
 47#define QSERDES_RX_UCDR_PI_CTRL2			(QSERDES_RX + 0x48)
 48#define QSERDES_RX_RX_TERM_BW				(QSERDES_RX + 0x80)
 49#define QSERDES_RX_VGA_CAL_CNTRL2			(QSERDES_RX + 0xd8)
 50#define QSERDES_RX_GM_CAL				(QSERDES_RX + 0xdc)
 51#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1		(QSERDES_RX + 0xe8)
 52#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2		(QSERDES_RX + 0xec)
 53#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3		(QSERDES_RX + 0xf0)
 54#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4		(QSERDES_RX + 0xf4)
 55#define QSERDES_RX_RX_IDAC_TSETTLE_LOW			(QSERDES_RX + 0xf8)
 56#define QSERDES_RX_RX_IDAC_TSETTLE_HIGH			(QSERDES_RX + 0xfc)
 57#define QSERDES_RX_RX_IDAC_MEASURE_TIME			(QSERDES_RX + 0x100)
 58#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1		(QSERDES_RX + 0x110)
 59#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2		(QSERDES_RX + 0x114)
 60#define QSERDES_RX_SIGDET_CNTRL				(QSERDES_RX + 0x11c)
 61#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL		(QSERDES_RX + 0x124)
 62#define QSERDES_RX_RX_BAND				(QSERDES_RX + 0x128)
 63#define QSERDES_RX_RX_MODE_00_LOW			(QSERDES_RX + 0x15c)
 64#define QSERDES_RX_RX_MODE_00_HIGH			(QSERDES_RX + 0x160)
 65#define QSERDES_RX_RX_MODE_00_HIGH2			(QSERDES_RX + 0x164)
 66#define QSERDES_RX_RX_MODE_00_HIGH3			(QSERDES_RX + 0x168)
 67#define QSERDES_RX_RX_MODE_00_HIGH4			(QSERDES_RX + 0x16c)
 68#define QSERDES_RX_RX_MODE_01_LOW			(QSERDES_RX + 0x170)
 69#define QSERDES_RX_RX_MODE_01_HIGH			(QSERDES_RX + 0x174)
 70#define QSERDES_RX_RX_MODE_01_HIGH2			(QSERDES_RX + 0x178)
 71#define QSERDES_RX_RX_MODE_01_HIGH3			(QSERDES_RX + 0x17c)
 72#define QSERDES_RX_RX_MODE_01_HIGH4			(QSERDES_RX + 0x180)
 73#define QSERDES_RX_RX_MODE_10_LOW			(QSERDES_RX + 0x184)
 74#define QSERDES_RX_RX_MODE_10_HIGH			(QSERDES_RX + 0x188)
 75#define QSERDES_RX_RX_MODE_10_HIGH2			(QSERDES_RX + 0x18c)
 76#define QSERDES_RX_RX_MODE_10_HIGH3			(QSERDES_RX + 0x190)
 77#define QSERDES_RX_RX_MODE_10_HIGH4			(QSERDES_RX + 0x194)
 78#define QSERDES_RX_DCC_CTRL1				(QSERDES_RX + 0x1a8)
 79
 80#define QSERDES_TX					0x400
 81#define QSERDES_TX_TX_BAND				(QSERDES_TX + 0x24)
 82#define QSERDES_TX_SLEW_CNTL				(QSERDES_TX + 0x28)
 83#define QSERDES_TX_RES_CODE_LANE_OFFSET_TX		(QSERDES_TX + 0x3c)
 84#define QSERDES_TX_RES_CODE_LANE_OFFSET_RX		(QSERDES_TX + 0x40)
 85#define QSERDES_TX_LANE_MODE_1				(QSERDES_TX + 0x84)
 86#define QSERDES_TX_LANE_MODE_3				(QSERDES_TX + 0x8c)
 87#define QSERDES_TX_RCV_DETECT_LVL_2			(QSERDES_TX + 0xa4)
 88#define QSERDES_TX_TRAN_DRVR_EMP_EN			(QSERDES_TX + 0xc0)
 89
 90#define QSERDES_PCS					0xC00
 91#define QSERDES_PCS_PHY_START				(QSERDES_PCS + 0x0)
 92#define QSERDES_PCS_POWER_DOWN_CONTROL			(QSERDES_PCS + 0x4)
 93#define QSERDES_PCS_SW_RESET				(QSERDES_PCS + 0x8)
 94#define QSERDES_PCS_LINE_RESET_TIME			(QSERDES_PCS + 0xc)
 95#define QSERDES_PCS_TX_LARGE_AMP_DRV_LVL		(QSERDES_PCS + 0x20)
 96#define QSERDES_PCS_TX_SMALL_AMP_DRV_LVL		(QSERDES_PCS + 0x28)
 97#define QSERDES_PCS_TX_MID_TERM_CTRL1			(QSERDES_PCS + 0xd8)
 98#define QSERDES_PCS_TX_MID_TERM_CTRL2			(QSERDES_PCS + 0xdc)
 99#define QSERDES_PCS_SGMII_MISC_CTRL8			(QSERDES_PCS + 0x118)
100#define QSERDES_PCS_PCS_READY_STATUS			(QSERDES_PCS + 0x94)
101
102#define QSERDES_COM_C_READY				BIT(0)
103#define QSERDES_PCS_READY				BIT(0)
104#define QSERDES_PCS_SGMIIPHY_READY			BIT(7)
105#define QSERDES_COM_C_PLL_LOCKED			BIT(1)
106
107struct qcom_dwmac_sgmii_phy_data {
108	struct regmap *regmap;
109	struct clk *refclk;
110	int speed;
111};
112
113static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)
114{
115	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
116	regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
117
118	regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
119	regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
120	regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
121	regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
122	regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
123	regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A);
124	regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A);
125	regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x82);
126	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
127	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
128	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
129	regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0x24);
130
131	regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
132	regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
133	regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x04);
134	regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
135	regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x0A);
136	regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
137	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9);
138	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E);
139	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
140
141	regmap_write(regmap, QSERDES_TX_TX_BAND, 0x05);
142	regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
143	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
144	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x09);
145	regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
146	regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
147	regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
148	regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
149
150	regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
151	regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
152	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
153	regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
154	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
155	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
156	regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
157	regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
158	regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x04);
159	regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
160	regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
161	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
162	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
163	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
164	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
165	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
166	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
167	regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
168	regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
169	regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
170	regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
171	regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
172	regmap_write(regmap, QSERDES_RX_RX_BAND, 0x05);
173	regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0xE0);
174	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
175	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
176	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x09);
177	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB1);
178	regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
179	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
180	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
181	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
182	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
183	regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
184	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
185	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
186	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
187	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
188	regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
189
190	regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
191	regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
192	regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
193	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
194	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
195	regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x0C);
196	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
197
198	regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
199}
200
201static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap)
202{
203	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
204	regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
205
206	regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
207	regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
208	regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
209	regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
210	regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
211	regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x1A);
212	regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x41);
213	regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x7A);
214	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
215	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x20);
216	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x01);
217	regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0xA1);
218
219	regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
220	regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
221	regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x03);
222	regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
223	regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x05);
224	regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
225	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD);
226	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C);
227	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
228
229	regmap_write(regmap, QSERDES_TX_TX_BAND, 0x04);
230	regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
231	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
232	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x02);
233	regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
234	regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
235	regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
236	regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
237
238	regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
239	regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
240	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
241	regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
242	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
243	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
244	regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
245	regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
246	regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x00);
247	regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
248	regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
249	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
250	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
251	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
252	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
253	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
254	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
255	regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
256	regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
257	regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
258	regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
259	regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
260	regmap_write(regmap, QSERDES_RX_RX_BAND, 0x18);
261	regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0x18);
262	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
263	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
264	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x0C);
265	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB8);
266	regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
267	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
268	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
269	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
270	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
271	regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
272	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
273	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
274	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
275	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
276	regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
277
278	regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
279	regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
280	regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
281	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
282	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
283	regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x8C);
284	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
285
286	regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
287}
288
289static inline int
290qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg,
291				 unsigned int bit)
292{
293	unsigned int val;
294
295	return regmap_read_poll_timeout(regmap, reg, val,
296					val & bit, 1500, 750000);
297}
298
299static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
300{
301	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
302	struct device *dev = phy->dev.parent;
303
304	switch (data->speed) {
305	case SPEED_10:
306	case SPEED_100:
307	case SPEED_1000:
308		qcom_dwmac_sgmii_phy_init_1g(data->regmap);
309		break;
310	case SPEED_2500:
311		qcom_dwmac_sgmii_phy_init_2p5g(data->regmap);
312		break;
313	}
314
315	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
316					     QSERDES_COM_C_READY_STATUS,
317					     QSERDES_COM_C_READY)) {
318		dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out");
319		return -ETIMEDOUT;
320	}
321
322	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
323					     QSERDES_PCS_PCS_READY_STATUS,
324					     QSERDES_PCS_READY)) {
325		dev_err(dev, "PCS_READY timed-out");
326		return -ETIMEDOUT;
327	}
328
329	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
330					     QSERDES_PCS_PCS_READY_STATUS,
331					     QSERDES_PCS_SGMIIPHY_READY)) {
332		dev_err(dev, "SGMIIPHY_READY timed-out");
333		return -ETIMEDOUT;
334	}
335
336	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
337					     QSERDES_COM_CMN_STATUS,
338					     QSERDES_COM_C_PLL_LOCKED)) {
339		dev_err(dev, "PLL Lock Status timed-out");
340		return -ETIMEDOUT;
341	}
342
343	return 0;
344}
345
346static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy)
347{
348	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
349
350	return clk_prepare_enable(data->refclk);
351}
352
353static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
354{
355	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
356
357	regmap_write(data->regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
358	regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x01);
359	udelay(100);
360	regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x00);
361	regmap_write(data->regmap, QSERDES_PCS_PHY_START, 0x01);
362
363	clk_disable_unprepare(data->refclk);
364
365	return 0;
366}
367
368static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
369{
370	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
371
372	if (speed != data->speed)
373		data->speed = speed;
374
375	return qcom_dwmac_sgmii_phy_calibrate(phy);
376}
377
378static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
379	.power_on	= qcom_dwmac_sgmii_phy_power_on,
380	.power_off	= qcom_dwmac_sgmii_phy_power_off,
381	.set_speed	= qcom_dwmac_sgmii_phy_set_speed,
382	.calibrate	= qcom_dwmac_sgmii_phy_calibrate,
383	.owner		= THIS_MODULE,
384};
385
386static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = {
387	.reg_bits		= 32,
388	.val_bits		= 32,
389	.reg_stride		= 4,
390	.use_relaxed_mmio	= true,
391	.disable_locking	= true,
392};
393
394static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
395{
396	struct qcom_dwmac_sgmii_phy_data *data;
397	struct device *dev = &pdev->dev;
398	struct phy_provider *provider;
399	void __iomem *base;
400	struct phy *phy;
401
402	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
403	if (!data)
404		return -ENOMEM;
405
406	data->speed = SPEED_10;
407
408	base = devm_platform_ioremap_resource(pdev, 0);
409	if (IS_ERR(base))
410		return PTR_ERR(base);
411
412	data->regmap = devm_regmap_init_mmio(dev, base,
413					     &qcom_dwmac_sgmii_phy_regmap_cfg);
414	if (IS_ERR(data->regmap))
415		return PTR_ERR(data->regmap);
416
417	phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);
418	if (IS_ERR(phy))
419		return PTR_ERR(phy);
420
421	data->refclk = devm_clk_get(dev, "sgmi_ref");
422	if (IS_ERR(data->refclk))
423		return PTR_ERR(data->refclk);
424
425	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
426	if (IS_ERR(provider))
427		return PTR_ERR(provider);
428
429	phy_set_drvdata(phy, data);
430
431	return 0;
432}
433
434static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {
435	{ .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },
436	{ },
437};
438MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);
439
440static struct platform_driver qcom_dwmac_sgmii_phy_driver = {
441	.probe	= qcom_dwmac_sgmii_phy_probe,
442	.driver = {
443		.name	= "qcom-dwmac-sgmii-phy",
444		.of_match_table	= qcom_dwmac_sgmii_phy_of_match,
445	}
446};
447
448module_platform_driver(qcom_dwmac_sgmii_phy_driver);
449
450MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");
451MODULE_LICENSE("GPL");