xref: /linux/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
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 #include "phy-qcom-qmp-pcs-sgmii.h"
15 #include "phy-qcom-qmp-qserdes-com-v5.h"
16 #include "phy-qcom-qmp-qserdes-txrx-v5.h"
17 
18 #define QSERDES_QMP_PLL					0x0
19 #define QSERDES_RX					0x600
20 #define QSERDES_TX					0x400
21 #define QSERDES_PCS					0xc00
22 
23 #define QSERDES_COM_C_READY				BIT(0)
24 #define QSERDES_PCS_READY				BIT(0)
25 #define QSERDES_PCS_SGMIIPHY_READY			BIT(7)
26 #define QSERDES_COM_C_PLL_LOCKED			BIT(1)
27 
28 struct qcom_dwmac_sgmii_phy_data {
29 	struct regmap *regmap;
30 	struct clk *refclk;
31 	int speed;
32 };
33 
qcom_dwmac_sgmii_phy_init_1g(struct regmap * regmap)34 static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)
35 {
36 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01);
37 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_POWER_DOWN_CONTROL, 0x01);
38 
39 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_IVCO, 0x0F);
40 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CP_CTRL_MODE0, 0x06);
41 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16);
42 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36);
43 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1A);
44 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0A);
45 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1A);
46 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DEC_START_MODE0, 0x82);
47 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55);
48 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55);
49 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03);
50 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24);
51 
52 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE2_MODE0, 0x02);
53 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00);
54 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_SEL, 0x04);
55 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00);
56 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0A);
57 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORE_CLK_EN, 0x00);
58 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9);
59 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E);
60 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
61 
62 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TX_BAND, 0x05);
63 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_SLEW_CNTL, 0x0A);
64 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
65 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09);
66 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_1, 0x05);
67 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_3, 0x00);
68 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12);
69 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0C);
70 
71 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FO_GAIN, 0x0A);
72 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_GAIN, 0x06);
73 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
74 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
75 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
76 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
77 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x81);
78 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80);
79 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_TERM_BW, 0x04);
80 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x08);
81 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_GM_CAL, 0x0F);
82 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
83 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
84 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
85 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
86 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0x80);
87 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
88 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x20);
89 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
90 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
91 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_CNTRL, 0x0F);
92 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
93 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_BAND, 0x05);
94 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_LOW, 0xE0);
95 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH, 0xC8);
96 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xC8);
97 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x09);
98 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xB1);
99 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_LOW, 0xE0);
100 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH, 0xC8);
101 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xC8);
102 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x09);
103 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xB1);
104 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_LOW, 0xE0);
105 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH, 0xC8);
106 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xC8);
107 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3B);
108 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xB7);
109 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_DCC_CTRL1, 0x0C);
110 
111 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_LINE_RESET_TIME, 0x0C);
112 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
113 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
114 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL1, 0x83);
115 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08);
116 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL8, 0x0C);
117 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00);
118 
119 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01);
120 }
121 
qcom_dwmac_sgmii_phy_init_2p5g(struct regmap * regmap)122 static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap)
123 {
124 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01);
125 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_POWER_DOWN_CONTROL, 0x01);
126 
127 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_IVCO, 0x0F);
128 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CP_CTRL_MODE0, 0x06);
129 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16);
130 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36);
131 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1A);
132 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x1A);
133 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x41);
134 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DEC_START_MODE0, 0x7A);
135 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x00);
136 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x20);
137 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x01);
138 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE1_MODE0, 0xA1);
139 
140 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE2_MODE0, 0x02);
141 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00);
142 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_SEL, 0x03);
143 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00);
144 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x05);
145 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORE_CLK_EN, 0x00);
146 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD);
147 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C);
148 	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
149 
150 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TX_BAND, 0x04);
151 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_SLEW_CNTL, 0x0A);
152 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
153 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x02);
154 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_1, 0x05);
155 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_3, 0x00);
156 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12);
157 	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0C);
158 
159 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FO_GAIN, 0x0A);
160 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_GAIN, 0x06);
161 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
162 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
163 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
164 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
165 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x81);
166 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80);
167 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_TERM_BW, 0x00);
168 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x08);
169 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_GM_CAL, 0x0F);
170 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
171 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
172 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
173 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
174 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0x80);
175 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
176 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x20);
177 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
178 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
179 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_CNTRL, 0x0F);
180 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
181 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_BAND, 0x18);
182 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_LOW, 0x18);
183 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH, 0xC8);
184 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xC8);
185 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x0C);
186 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xB8);
187 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_LOW, 0xE0);
188 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH, 0xC8);
189 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xC8);
190 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x09);
191 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xB1);
192 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_LOW, 0xE0);
193 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH, 0xC8);
194 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xC8);
195 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3B);
196 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xB7);
197 	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_DCC_CTRL1, 0x0C);
198 
199 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_LINE_RESET_TIME, 0x0C);
200 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
201 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
202 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL1, 0x83);
203 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08);
204 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL8, 0x8C);
205 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00);
206 
207 	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01);
208 }
209 
210 static inline int
qcom_dwmac_sgmii_phy_poll_status(struct regmap * regmap,unsigned int reg,unsigned int bit)211 qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg,
212 				 unsigned int bit)
213 {
214 	unsigned int val;
215 
216 	return regmap_read_poll_timeout(regmap, reg, val,
217 					val & bit, 1500, 750000);
218 }
219 
qcom_dwmac_sgmii_phy_calibrate(struct phy * phy)220 static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
221 {
222 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
223 	struct device *dev = phy->dev.parent;
224 
225 	switch (data->speed) {
226 	case SPEED_10:
227 	case SPEED_100:
228 	case SPEED_1000:
229 		qcom_dwmac_sgmii_phy_init_1g(data->regmap);
230 		break;
231 	case SPEED_2500:
232 		qcom_dwmac_sgmii_phy_init_2p5g(data->regmap);
233 		break;
234 	}
235 
236 	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
237 					     QSERDES_QMP_PLL + QSERDES_V5_COM_C_READY_STATUS,
238 					     QSERDES_COM_C_READY)) {
239 		dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out");
240 		return -ETIMEDOUT;
241 	}
242 
243 	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
244 					     QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS,
245 					     QSERDES_PCS_READY)) {
246 		dev_err(dev, "PCS_READY timed-out");
247 		return -ETIMEDOUT;
248 	}
249 
250 	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
251 					     QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS,
252 					     QSERDES_PCS_SGMIIPHY_READY)) {
253 		dev_err(dev, "SGMIIPHY_READY timed-out");
254 		return -ETIMEDOUT;
255 	}
256 
257 	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
258 					     QSERDES_QMP_PLL + QSERDES_V5_COM_CMN_STATUS,
259 					     QSERDES_COM_C_PLL_LOCKED)) {
260 		dev_err(dev, "PLL Lock Status timed-out");
261 		return -ETIMEDOUT;
262 	}
263 
264 	return 0;
265 }
266 
qcom_dwmac_sgmii_phy_power_on(struct phy * phy)267 static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy)
268 {
269 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
270 
271 	return clk_prepare_enable(data->refclk);
272 }
273 
qcom_dwmac_sgmii_phy_power_off(struct phy * phy)274 static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
275 {
276 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
277 
278 	regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08);
279 	regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01);
280 	udelay(100);
281 	regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00);
282 	regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01);
283 
284 	clk_disable_unprepare(data->refclk);
285 
286 	return 0;
287 }
288 
qcom_dwmac_sgmii_phy_set_speed(struct phy * phy,int speed)289 static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
290 {
291 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
292 
293 	if (speed != data->speed)
294 		data->speed = speed;
295 
296 	return qcom_dwmac_sgmii_phy_calibrate(phy);
297 }
298 
299 static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
300 	.power_on	= qcom_dwmac_sgmii_phy_power_on,
301 	.power_off	= qcom_dwmac_sgmii_phy_power_off,
302 	.set_speed	= qcom_dwmac_sgmii_phy_set_speed,
303 	.calibrate	= qcom_dwmac_sgmii_phy_calibrate,
304 	.owner		= THIS_MODULE,
305 };
306 
307 static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = {
308 	.reg_bits		= 32,
309 	.val_bits		= 32,
310 	.reg_stride		= 4,
311 	.use_relaxed_mmio	= true,
312 	.disable_locking	= true,
313 };
314 
qcom_dwmac_sgmii_phy_probe(struct platform_device * pdev)315 static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
316 {
317 	struct qcom_dwmac_sgmii_phy_data *data;
318 	struct device *dev = &pdev->dev;
319 	struct phy_provider *provider;
320 	void __iomem *base;
321 	struct phy *phy;
322 
323 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
324 	if (!data)
325 		return -ENOMEM;
326 
327 	data->speed = SPEED_10;
328 
329 	base = devm_platform_ioremap_resource(pdev, 0);
330 	if (IS_ERR(base))
331 		return PTR_ERR(base);
332 
333 	data->regmap = devm_regmap_init_mmio(dev, base,
334 					     &qcom_dwmac_sgmii_phy_regmap_cfg);
335 	if (IS_ERR(data->regmap))
336 		return PTR_ERR(data->regmap);
337 
338 	phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);
339 	if (IS_ERR(phy))
340 		return PTR_ERR(phy);
341 
342 	data->refclk = devm_clk_get(dev, "sgmi_ref");
343 	if (IS_ERR(data->refclk))
344 		return PTR_ERR(data->refclk);
345 
346 	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
347 	if (IS_ERR(provider))
348 		return PTR_ERR(provider);
349 
350 	phy_set_drvdata(phy, data);
351 
352 	return 0;
353 }
354 
355 static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {
356 	{ .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },
357 	{ },
358 };
359 MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);
360 
361 static struct platform_driver qcom_dwmac_sgmii_phy_driver = {
362 	.probe	= qcom_dwmac_sgmii_phy_probe,
363 	.driver = {
364 		.name	= "qcom-dwmac-sgmii-phy",
365 		.of_match_table	= qcom_dwmac_sgmii_phy_of_match,
366 	}
367 };
368 
369 module_platform_driver(qcom_dwmac_sgmii_phy_driver);
370 
371 MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");
372 MODULE_LICENSE("GPL");
373