GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / phy / qualcomm / phy-qcom-sgmii-eth.c
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
107 struct qcom_dwmac_sgmii_phy_data {
108         struct regmap *regmap;
109         struct clk *refclk;
110         int speed;
111 };
112
113 static 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
201 static 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
289 static inline int
290 qcom_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
299 static 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
346 static 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
353 static 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
368 static 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
378 static 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
386 static 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
394 static 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
434 static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {
435         { .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },
436         { },
437 };
438 MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);
439
440 static 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
448 module_platform_driver(qcom_dwmac_sgmii_phy_driver);
449
450 MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");
451 MODULE_LICENSE("GPL");