xref: /linux/drivers/phy/microchip/lan966x_serdes.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 #include <linux/err.h>
4 #include <linux/module.h>
5 #include <linux/of.h>
6 #include <linux/of_platform.h>
7 #include <linux/phy.h>
8 #include <linux/phy/phy.h>
9 #include <linux/platform_device.h>
10 
11 #include <dt-bindings/phy/phy-lan966x-serdes.h>
12 #include "lan966x_serdes_regs.h"
13 
14 #define PLL_CONF_MASK		GENMASK(4, 3)
15 #define PLL_CONF_25MHZ		0
16 #define PLL_CONF_125MHZ		1
17 #define PLL_CONF_SERDES_125MHZ	2
18 #define PLL_CONF_BYPASS		3
19 
20 #define lan_offset_(id, tinst, tcnt,			\
21 		   gbase, ginst, gcnt, gwidth,		\
22 		   raddr, rinst, rcnt, rwidth)		\
23 	(gbase + ((ginst) * gwidth) + raddr + ((rinst) * rwidth))
24 #define lan_offset(...) lan_offset_(__VA_ARGS__)
25 
26 #define lan_rmw(val, mask, reg, off)		\
27 	lan_rmw_(val, mask, reg, lan_offset(off))
28 
29 #define SERDES_MUX(_idx, _port, _mode, _submode, _mask, _mux) { \
30 	.idx = _idx,						\
31 	.port = _port,						\
32 	.mode = _mode,						\
33 	.submode = _submode,					\
34 	.mask = _mask,						\
35 	.mux = _mux,						\
36 }
37 
38 #define SERDES_MUX_GMII(i, p, m, c) \
39 	SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_GMII, m, c)
40 #define SERDES_MUX_SGMII(i, p, m, c) \
41 	SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_SGMII, m, c)
42 #define SERDES_MUX_QSGMII(i, p, m, c) \
43 	SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c)
44 #define SERDES_MUX_RGMII(i, p, m, c) \
45 	SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII, m, c), \
46 	SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_TXID, m, c), \
47 	SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_RXID, m, c), \
48 	SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_ID, m, c)
49 
50 static void lan_rmw_(u32 val, u32 mask, void __iomem *mem, u32 offset)
51 {
52 	u32 v;
53 
54 	v = readl(mem + offset);
55 	v = (v & ~mask) | (val & mask);
56 	writel(v, mem + offset);
57 }
58 
59 struct serdes_mux {
60 	u8			idx;
61 	u8			port;
62 	enum phy_mode		mode;
63 	int			submode;
64 	u32			mask;
65 	u32			mux;
66 };
67 
68 static const struct serdes_mux lan966x_serdes_muxes[] = {
69 	SERDES_MUX_QSGMII(SERDES6G(1), 0, HSIO_HW_CFG_QSGMII_ENA,
70 			  HSIO_HW_CFG_QSGMII_ENA_SET(BIT(0))),
71 	SERDES_MUX_QSGMII(SERDES6G(1), 1, HSIO_HW_CFG_QSGMII_ENA,
72 			  HSIO_HW_CFG_QSGMII_ENA_SET(BIT(0))),
73 	SERDES_MUX_QSGMII(SERDES6G(1), 2, HSIO_HW_CFG_QSGMII_ENA,
74 			  HSIO_HW_CFG_QSGMII_ENA_SET(BIT(0))),
75 	SERDES_MUX_QSGMII(SERDES6G(1), 3, HSIO_HW_CFG_QSGMII_ENA,
76 			  HSIO_HW_CFG_QSGMII_ENA_SET(BIT(0))),
77 
78 	SERDES_MUX_QSGMII(SERDES6G(2), 4, HSIO_HW_CFG_QSGMII_ENA,
79 			  HSIO_HW_CFG_QSGMII_ENA_SET(BIT(1))),
80 	SERDES_MUX_QSGMII(SERDES6G(2), 5, HSIO_HW_CFG_QSGMII_ENA,
81 			  HSIO_HW_CFG_QSGMII_ENA_SET(BIT(1))),
82 	SERDES_MUX_QSGMII(SERDES6G(2), 6, HSIO_HW_CFG_QSGMII_ENA,
83 			  HSIO_HW_CFG_QSGMII_ENA_SET(BIT(1))),
84 	SERDES_MUX_QSGMII(SERDES6G(2), 7, HSIO_HW_CFG_QSGMII_ENA,
85 			  HSIO_HW_CFG_QSGMII_ENA_SET(BIT(1))),
86 
87 	SERDES_MUX_GMII(CU(0), 0, HSIO_HW_CFG_GMII_ENA,
88 			HSIO_HW_CFG_GMII_ENA_SET(BIT(0))),
89 	SERDES_MUX_GMII(CU(1), 1, HSIO_HW_CFG_GMII_ENA,
90 			HSIO_HW_CFG_GMII_ENA_SET(BIT(1))),
91 
92 	SERDES_MUX_SGMII(SERDES6G(0), 0, HSIO_HW_CFG_SD6G_0_CFG, 0),
93 	SERDES_MUX_SGMII(SERDES6G(1), 1, HSIO_HW_CFG_SD6G_1_CFG, 0),
94 	SERDES_MUX_SGMII(SERDES6G(0), 2, HSIO_HW_CFG_SD6G_0_CFG,
95 			 HSIO_HW_CFG_SD6G_0_CFG_SET(1)),
96 	SERDES_MUX_SGMII(SERDES6G(1), 3, HSIO_HW_CFG_SD6G_1_CFG,
97 			 HSIO_HW_CFG_SD6G_1_CFG_SET(1)),
98 
99 	SERDES_MUX_SGMII(SERDES6G(2), 4, 0, 0),
100 
101 	SERDES_MUX_RGMII(RGMII(0), 2, HSIO_HW_CFG_RGMII_0_CFG |
102 			 HSIO_HW_CFG_RGMII_ENA |
103 			 HSIO_HW_CFG_GMII_ENA,
104 			 HSIO_HW_CFG_RGMII_0_CFG_SET(0) |
105 			 HSIO_HW_CFG_RGMII_ENA_SET(BIT(0)) |
106 			 HSIO_HW_CFG_GMII_ENA_SET(BIT(2))),
107 	SERDES_MUX_RGMII(RGMII(1), 3, HSIO_HW_CFG_RGMII_1_CFG |
108 			 HSIO_HW_CFG_RGMII_ENA |
109 			 HSIO_HW_CFG_GMII_ENA,
110 			 HSIO_HW_CFG_RGMII_1_CFG_SET(0) |
111 			 HSIO_HW_CFG_RGMII_ENA_SET(BIT(1)) |
112 			 HSIO_HW_CFG_GMII_ENA_SET(BIT(3))),
113 	SERDES_MUX_RGMII(RGMII(0), 5, HSIO_HW_CFG_RGMII_0_CFG |
114 			 HSIO_HW_CFG_RGMII_ENA |
115 			 HSIO_HW_CFG_GMII_ENA,
116 			 HSIO_HW_CFG_RGMII_0_CFG_SET(BIT(0)) |
117 			 HSIO_HW_CFG_RGMII_ENA_SET(BIT(0)) |
118 			 HSIO_HW_CFG_GMII_ENA_SET(BIT(5))),
119 	SERDES_MUX_RGMII(RGMII(1), 6, HSIO_HW_CFG_RGMII_1_CFG |
120 			 HSIO_HW_CFG_RGMII_ENA |
121 			 HSIO_HW_CFG_GMII_ENA,
122 			 HSIO_HW_CFG_RGMII_1_CFG_SET(BIT(0)) |
123 			 HSIO_HW_CFG_RGMII_ENA_SET(BIT(1)) |
124 			 HSIO_HW_CFG_GMII_ENA_SET(BIT(6))),
125 };
126 
127 struct serdes_ctrl {
128 	void __iomem		*regs;
129 	struct device		*dev;
130 	struct phy		*phys[SERDES_MAX];
131 	int			ref125;
132 };
133 
134 struct serdes_macro {
135 	u8			idx;
136 	int			port;
137 	struct serdes_ctrl	*ctrl;
138 	int			speed;
139 	phy_interface_t		mode;
140 };
141 
142 enum lan966x_sd6g40_mode {
143 	LAN966X_SD6G40_MODE_QSGMII,
144 	LAN966X_SD6G40_MODE_SGMII,
145 };
146 
147 enum lan966x_sd6g40_ltx2rx {
148 	LAN966X_SD6G40_TX2RX_LOOP_NONE,
149 	LAN966X_SD6G40_LTX2RX
150 };
151 
152 struct lan966x_sd6g40_setup_args {
153 	enum lan966x_sd6g40_mode	mode;
154 	enum lan966x_sd6g40_ltx2rx	tx2rx_loop;
155 	bool				txinvert;
156 	bool				rxinvert;
157 	bool				refclk125M;
158 	bool				mute;
159 };
160 
161 struct lan966x_sd6g40_mode_args {
162 	enum lan966x_sd6g40_mode	mode;
163 	u8				 lane_10bit_sel;
164 	u8				 mpll_multiplier;
165 	u8				 ref_clkdiv2;
166 	u8				 tx_rate;
167 	u8				 rx_rate;
168 };
169 
170 struct lan966x_sd6g40_setup {
171 	u8	rx_term_en;
172 	u8	lane_10bit_sel;
173 	u8	tx_invert;
174 	u8	rx_invert;
175 	u8	mpll_multiplier;
176 	u8	lane_loopbk_en;
177 	u8	ref_clkdiv2;
178 	u8	tx_rate;
179 	u8	rx_rate;
180 };
181 
182 static int lan966x_sd6g40_reg_cfg(struct serdes_macro *macro,
183 				  struct lan966x_sd6g40_setup *res_struct,
184 				  u32 idx)
185 {
186 	u32 value;
187 
188 	/* Note: SerDes HSIO is configured in 1G_LAN mode */
189 	lan_rmw(HSIO_SD_CFG_LANE_10BIT_SEL_SET(res_struct->lane_10bit_sel) |
190 		HSIO_SD_CFG_RX_RATE_SET(res_struct->rx_rate) |
191 		HSIO_SD_CFG_TX_RATE_SET(res_struct->tx_rate) |
192 		HSIO_SD_CFG_TX_INVERT_SET(res_struct->tx_invert) |
193 		HSIO_SD_CFG_RX_INVERT_SET(res_struct->rx_invert) |
194 		HSIO_SD_CFG_LANE_LOOPBK_EN_SET(res_struct->lane_loopbk_en) |
195 		HSIO_SD_CFG_RX_RESET_SET(0) |
196 		HSIO_SD_CFG_TX_RESET_SET(0),
197 		HSIO_SD_CFG_LANE_10BIT_SEL |
198 		HSIO_SD_CFG_RX_RATE |
199 		HSIO_SD_CFG_TX_RATE |
200 		HSIO_SD_CFG_TX_INVERT |
201 		HSIO_SD_CFG_RX_INVERT |
202 		HSIO_SD_CFG_LANE_LOOPBK_EN |
203 		HSIO_SD_CFG_RX_RESET |
204 		HSIO_SD_CFG_TX_RESET,
205 		macro->ctrl->regs, HSIO_SD_CFG(idx));
206 
207 	lan_rmw(HSIO_MPLL_CFG_MPLL_MULTIPLIER_SET(res_struct->mpll_multiplier) |
208 		HSIO_MPLL_CFG_REF_CLKDIV2_SET(res_struct->ref_clkdiv2),
209 		HSIO_MPLL_CFG_MPLL_MULTIPLIER |
210 		HSIO_MPLL_CFG_REF_CLKDIV2,
211 		macro->ctrl->regs, HSIO_MPLL_CFG(idx));
212 
213 	lan_rmw(HSIO_SD_CFG_RX_TERM_EN_SET(res_struct->rx_term_en),
214 		HSIO_SD_CFG_RX_TERM_EN,
215 		macro->ctrl->regs, HSIO_SD_CFG(idx));
216 
217 	lan_rmw(HSIO_MPLL_CFG_REF_SSP_EN_SET(1),
218 		HSIO_MPLL_CFG_REF_SSP_EN,
219 		macro->ctrl->regs, HSIO_MPLL_CFG(idx));
220 
221 	usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
222 
223 	lan_rmw(HSIO_SD_CFG_PHY_RESET_SET(0),
224 		HSIO_SD_CFG_PHY_RESET,
225 		macro->ctrl->regs, HSIO_SD_CFG(idx));
226 
227 	usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
228 
229 	lan_rmw(HSIO_MPLL_CFG_MPLL_EN_SET(1),
230 		HSIO_MPLL_CFG_MPLL_EN,
231 		macro->ctrl->regs, HSIO_MPLL_CFG(idx));
232 
233 	usleep_range(7 * USEC_PER_MSEC, 8 * USEC_PER_MSEC);
234 
235 	value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx)));
236 	value = HSIO_SD_STAT_MPLL_STATE_GET(value);
237 	if (value != 0x1) {
238 		dev_err(macro->ctrl->dev,
239 			"Unexpected sd_sd_stat[%u] mpll_state was 0x1 but is 0x%x\n",
240 			idx, value);
241 		return -EIO;
242 	}
243 
244 	lan_rmw(HSIO_SD_CFG_TX_CM_EN_SET(1),
245 		HSIO_SD_CFG_TX_CM_EN,
246 		macro->ctrl->regs, HSIO_SD_CFG(idx));
247 
248 	usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
249 
250 	value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx)));
251 	value = HSIO_SD_STAT_TX_CM_STATE_GET(value);
252 	if (value != 0x1) {
253 		dev_err(macro->ctrl->dev,
254 			"Unexpected sd_sd_stat[%u] tx_cm_state was 0x1 but is 0x%x\n",
255 			idx, value);
256 		return -EIO;
257 	}
258 
259 	lan_rmw(HSIO_SD_CFG_RX_PLL_EN_SET(1) |
260 		HSIO_SD_CFG_TX_EN_SET(1),
261 		HSIO_SD_CFG_RX_PLL_EN |
262 		HSIO_SD_CFG_TX_EN,
263 		macro->ctrl->regs, HSIO_SD_CFG(idx));
264 
265 	usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
266 
267 	/* Waiting for serdes 0 rx DPLL to lock...  */
268 	value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx)));
269 	value = HSIO_SD_STAT_RX_PLL_STATE_GET(value);
270 	if (value != 0x1) {
271 		dev_err(macro->ctrl->dev,
272 			"Unexpected sd_sd_stat[%u] rx_pll_state was 0x1 but is 0x%x\n",
273 			idx, value);
274 		return -EIO;
275 	}
276 
277 	/* Waiting for serdes 0 tx operational...  */
278 	value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx)));
279 	value = HSIO_SD_STAT_TX_STATE_GET(value);
280 	if (value != 0x1) {
281 		dev_err(macro->ctrl->dev,
282 			"Unexpected sd_sd_stat[%u] tx_state was 0x1 but is 0x%x\n",
283 			idx, value);
284 		return -EIO;
285 	}
286 
287 	lan_rmw(HSIO_SD_CFG_TX_DATA_EN_SET(1) |
288 		HSIO_SD_CFG_RX_DATA_EN_SET(1),
289 		HSIO_SD_CFG_TX_DATA_EN |
290 		HSIO_SD_CFG_RX_DATA_EN,
291 		macro->ctrl->regs, HSIO_SD_CFG(idx));
292 
293 	return 0;
294 }
295 
296 static int lan966x_sd6g40_get_conf_from_mode(struct serdes_macro *macro,
297 					     enum lan966x_sd6g40_mode f_mode,
298 					     bool ref125M,
299 					     struct lan966x_sd6g40_mode_args *ret_val)
300 {
301 	switch (f_mode) {
302 	case LAN966X_SD6G40_MODE_QSGMII:
303 		ret_val->lane_10bit_sel = 0;
304 		if (ref125M) {
305 			ret_val->mpll_multiplier = 40;
306 			ret_val->ref_clkdiv2 = 0x1;
307 			ret_val->tx_rate = 0x0;
308 			ret_val->rx_rate = 0x0;
309 		} else {
310 			ret_val->mpll_multiplier = 100;
311 			ret_val->ref_clkdiv2 = 0x0;
312 			ret_val->tx_rate = 0x0;
313 			ret_val->rx_rate = 0x0;
314 		}
315 		break;
316 
317 	case LAN966X_SD6G40_MODE_SGMII:
318 		ret_val->lane_10bit_sel = 1;
319 		if (ref125M) {
320 			ret_val->mpll_multiplier = macro->speed == SPEED_2500 ? 50 : 40;
321 			ret_val->ref_clkdiv2 = 0x1;
322 			ret_val->tx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2;
323 			ret_val->rx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2;
324 		} else {
325 			ret_val->mpll_multiplier = macro->speed == SPEED_2500 ? 125 : 100;
326 			ret_val->ref_clkdiv2 = 0x0;
327 			ret_val->tx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2;
328 			ret_val->rx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2;
329 		}
330 		break;
331 
332 	default:
333 		return -EOPNOTSUPP;
334 	}
335 
336 	return 0;
337 }
338 
339 static int lan966x_calc_sd6g40_setup_lane(struct serdes_macro *macro,
340 					  struct lan966x_sd6g40_setup_args config,
341 					  struct lan966x_sd6g40_setup *ret_val)
342 {
343 	struct lan966x_sd6g40_mode_args sd6g40_mode;
344 	struct lan966x_sd6g40_mode_args *mode_args = &sd6g40_mode;
345 	int ret;
346 
347 	ret = lan966x_sd6g40_get_conf_from_mode(macro, config.mode,
348 						config.refclk125M, mode_args);
349 	if (ret)
350 		return ret;
351 
352 	ret_val->lane_10bit_sel = mode_args->lane_10bit_sel;
353 	ret_val->rx_rate = mode_args->rx_rate;
354 	ret_val->tx_rate = mode_args->tx_rate;
355 	ret_val->mpll_multiplier = mode_args->mpll_multiplier;
356 	ret_val->ref_clkdiv2 = mode_args->ref_clkdiv2;
357 	ret_val->rx_term_en = 0;
358 
359 	if (config.tx2rx_loop == LAN966X_SD6G40_LTX2RX)
360 		ret_val->lane_loopbk_en = 1;
361 	else
362 		ret_val->lane_loopbk_en = 0;
363 
364 	ret_val->tx_invert = !!config.txinvert;
365 	ret_val->rx_invert = !!config.rxinvert;
366 
367 	return 0;
368 }
369 
370 static int lan966x_sd6g40_setup_lane(struct serdes_macro *macro,
371 				     struct lan966x_sd6g40_setup_args config,
372 				     u32 idx)
373 {
374 	struct lan966x_sd6g40_setup calc_results = {};
375 	int ret;
376 
377 	ret = lan966x_calc_sd6g40_setup_lane(macro, config, &calc_results);
378 	if (ret)
379 		return ret;
380 
381 	return lan966x_sd6g40_reg_cfg(macro, &calc_results, idx);
382 }
383 
384 static int lan966x_sd6g40_setup(struct serdes_macro *macro, u32 idx, int mode)
385 {
386 	struct lan966x_sd6g40_setup_args conf = {};
387 
388 	conf.refclk125M = macro->ctrl->ref125;
389 
390 	if (mode == PHY_INTERFACE_MODE_QSGMII)
391 		conf.mode = LAN966X_SD6G40_MODE_QSGMII;
392 	else
393 		conf.mode = LAN966X_SD6G40_MODE_SGMII;
394 
395 	return lan966x_sd6g40_setup_lane(macro, conf, idx);
396 }
397 
398 static int lan966x_rgmii_setup(struct serdes_macro *macro, u32 idx, int mode)
399 {
400 	bool tx_delay = false;
401 	bool rx_delay = false;
402 
403 	/* Configure RGMII */
404 	lan_rmw(HSIO_RGMII_CFG_RGMII_RX_RST_SET(0) |
405 		HSIO_RGMII_CFG_RGMII_TX_RST_SET(0) |
406 		HSIO_RGMII_CFG_TX_CLK_CFG_SET(macro->speed == SPEED_1000 ? 1 :
407 					      macro->speed == SPEED_100 ? 2 :
408 					      macro->speed == SPEED_10 ? 3 : 0),
409 		HSIO_RGMII_CFG_RGMII_RX_RST |
410 		HSIO_RGMII_CFG_RGMII_TX_RST |
411 		HSIO_RGMII_CFG_TX_CLK_CFG,
412 		macro->ctrl->regs, HSIO_RGMII_CFG(idx));
413 
414 	if (mode == PHY_INTERFACE_MODE_RGMII ||
415 	    mode == PHY_INTERFACE_MODE_RGMII_TXID)
416 		rx_delay = true;
417 
418 	if (mode == PHY_INTERFACE_MODE_RGMII ||
419 	    mode == PHY_INTERFACE_MODE_RGMII_RXID)
420 		tx_delay = true;
421 
422 	/* Setup DLL configuration */
423 	lan_rmw(HSIO_DLL_CFG_DLL_RST_SET(0) |
424 		HSIO_DLL_CFG_DLL_ENA_SET(rx_delay),
425 		HSIO_DLL_CFG_DLL_RST |
426 		HSIO_DLL_CFG_DLL_ENA,
427 		macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2));
428 
429 	lan_rmw(HSIO_DLL_CFG_DELAY_ENA_SET(rx_delay),
430 		HSIO_DLL_CFG_DELAY_ENA,
431 		macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2));
432 
433 	lan_rmw(HSIO_DLL_CFG_DLL_RST_SET(0) |
434 		HSIO_DLL_CFG_DLL_ENA_SET(tx_delay),
435 		HSIO_DLL_CFG_DLL_RST |
436 		HSIO_DLL_CFG_DLL_ENA,
437 		macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3));
438 
439 	lan_rmw(HSIO_DLL_CFG_DELAY_ENA_SET(tx_delay),
440 		HSIO_DLL_CFG_DELAY_ENA,
441 		macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3));
442 
443 	return 0;
444 }
445 
446 static int serdes_set_speed(struct phy *phy, int speed)
447 {
448 	struct serdes_macro *macro = phy_get_drvdata(phy);
449 
450 	if (!phy_interface_mode_is_rgmii(macro->mode))
451 		return 0;
452 
453 	macro->speed = speed;
454 	lan966x_rgmii_setup(macro, macro->idx - (SERDES6G_MAX + 1), macro->mode);
455 
456 	return 0;
457 }
458 
459 static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
460 {
461 	struct serdes_macro *macro = phy_get_drvdata(phy);
462 	unsigned int i;
463 	int val;
464 
465 	/* As of now only PHY_MODE_ETHERNET is supported */
466 	if (mode != PHY_MODE_ETHERNET)
467 		return -EOPNOTSUPP;
468 
469 	if (submode == PHY_INTERFACE_MODE_2500BASEX)
470 		macro->speed = SPEED_2500;
471 	else
472 		macro->speed = SPEED_1000;
473 
474 	if (submode == PHY_INTERFACE_MODE_1000BASEX ||
475 	    submode == PHY_INTERFACE_MODE_2500BASEX)
476 		submode = PHY_INTERFACE_MODE_SGMII;
477 
478 	if (submode == PHY_INTERFACE_MODE_QUSGMII)
479 		submode = PHY_INTERFACE_MODE_QSGMII;
480 
481 	for (i = 0; i < ARRAY_SIZE(lan966x_serdes_muxes); i++) {
482 		if (macro->idx != lan966x_serdes_muxes[i].idx ||
483 		    mode != lan966x_serdes_muxes[i].mode ||
484 		    submode != lan966x_serdes_muxes[i].submode ||
485 		    macro->port != lan966x_serdes_muxes[i].port)
486 			continue;
487 
488 		val = readl(macro->ctrl->regs + lan_offset(HSIO_HW_CFG));
489 		val |= lan966x_serdes_muxes[i].mux;
490 		lan_rmw(val, lan966x_serdes_muxes[i].mask,
491 			macro->ctrl->regs, HSIO_HW_CFG);
492 
493 		macro->mode = lan966x_serdes_muxes[i].submode;
494 
495 		if (macro->idx < CU_MAX)
496 			return 0;
497 
498 		if (macro->idx < SERDES6G_MAX)
499 			return lan966x_sd6g40_setup(macro,
500 						    macro->idx - (CU_MAX + 1),
501 						    macro->mode);
502 
503 		if (macro->idx < RGMII_MAX)
504 			return lan966x_rgmii_setup(macro,
505 						   macro->idx - (SERDES6G_MAX + 1),
506 						   macro->mode);
507 
508 		return -EOPNOTSUPP;
509 	}
510 
511 	return -EINVAL;
512 }
513 
514 static const struct phy_ops serdes_ops = {
515 	.set_mode	= serdes_set_mode,
516 	.set_speed	= serdes_set_speed,
517 	.owner		= THIS_MODULE,
518 };
519 
520 static struct phy *serdes_simple_xlate(struct device *dev,
521 				       const struct of_phandle_args *args)
522 {
523 	struct serdes_ctrl *ctrl = dev_get_drvdata(dev);
524 	unsigned int port, idx, i;
525 
526 	if (args->args_count != 2)
527 		return ERR_PTR(-EINVAL);
528 
529 	port = args->args[0];
530 	idx = args->args[1];
531 
532 	for (i = 0; i < SERDES_MAX; i++) {
533 		struct serdes_macro *macro = phy_get_drvdata(ctrl->phys[i]);
534 
535 		if (idx != macro->idx)
536 			continue;
537 
538 		macro->port = port;
539 		return ctrl->phys[i];
540 	}
541 
542 	return ERR_PTR(-ENODEV);
543 }
544 
545 static int serdes_phy_create(struct serdes_ctrl *ctrl, u8 idx, struct phy **phy)
546 {
547 	struct serdes_macro *macro;
548 
549 	*phy = devm_phy_create(ctrl->dev, NULL, &serdes_ops);
550 	if (IS_ERR(*phy))
551 		return PTR_ERR(*phy);
552 
553 	macro = devm_kzalloc(ctrl->dev, sizeof(*macro), GFP_KERNEL);
554 	if (!macro)
555 		return -ENOMEM;
556 
557 	macro->idx = idx;
558 	macro->ctrl = ctrl;
559 	macro->port = -1;
560 
561 	phy_set_drvdata(*phy, macro);
562 
563 	return 0;
564 }
565 
566 static int serdes_probe(struct platform_device *pdev)
567 {
568 	struct phy_provider *provider;
569 	struct serdes_ctrl *ctrl;
570 	void __iomem *hw_stat;
571 	unsigned int i;
572 	u32 val;
573 	int ret;
574 
575 	ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
576 	if (!ctrl)
577 		return -ENOMEM;
578 
579 	ctrl->dev = &pdev->dev;
580 	ctrl->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
581 	if (IS_ERR(ctrl->regs))
582 		return PTR_ERR(ctrl->regs);
583 
584 	hw_stat = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
585 	if (IS_ERR(hw_stat))
586 		return PTR_ERR(hw_stat);
587 
588 	for (i = 0; i < SERDES_MAX; i++) {
589 		ret = serdes_phy_create(ctrl, i, &ctrl->phys[i]);
590 		if (ret)
591 			return ret;
592 	}
593 
594 	val = readl(hw_stat);
595 	val = FIELD_GET(PLL_CONF_MASK, val);
596 	ctrl->ref125 = (val == PLL_CONF_125MHZ ||
597 			val == PLL_CONF_SERDES_125MHZ);
598 
599 	dev_set_drvdata(&pdev->dev, ctrl);
600 
601 	provider = devm_of_phy_provider_register(ctrl->dev,
602 						 serdes_simple_xlate);
603 
604 	return PTR_ERR_OR_ZERO(provider);
605 }
606 
607 static const struct of_device_id serdes_ids[] = {
608 	{ .compatible = "microchip,lan966x-serdes", },
609 	{},
610 };
611 MODULE_DEVICE_TABLE(of, serdes_ids);
612 
613 static struct platform_driver mscc_lan966x_serdes = {
614 	.probe		= serdes_probe,
615 	.driver		= {
616 		.name	= "microchip,lan966x-serdes",
617 		.of_match_table = of_match_ptr(serdes_ids),
618 	},
619 };
620 
621 module_platform_driver(mscc_lan966x_serdes);
622 
623 MODULE_DESCRIPTION("Microchip lan966x switch serdes driver");
624 MODULE_AUTHOR("Horatiu Vultur <horatiu.vultur@microchip.com>");
625 MODULE_LICENSE("GPL v2");
626