1 /*
2  * Copyright (c) 2024 Microchip Technology Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT microchip_t1s_phy
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/net/phy.h>
11 #include <zephyr/net/mii.h>
12 #include <zephyr/net/mdio.h>
13 #include <zephyr/drivers/mdio.h>
14 
15 #define LOG_MODULE_NAME phy_mc_t1s
16 #define LOG_LEVEL       CONFIG_PHY_LOG_LEVEL
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
19 
20 /* Support: Microchip Phys:
21  * lan8650/1 Rev.B0/B1 Internal PHYs
22  * lan8670/1/2 Rev.C1/C2 PHYs
23  */
24 /* Both Rev.B0 and B1 clause 22 PHYID's are same due to B1 chip limitation */
25 #define PHY_ID_LAN865X_REVB  0x0007C1B3
26 #define PHY_ID_LAN867X_REVC1 0x0007C164
27 #define PHY_ID_LAN867X_REVC2 0x0007C165
28 
29 /* Configuration param registers */
30 #define LAN865X_REG_CFGPARAM_ADDR    0x00D8
31 #define LAN865X_REG_CFGPARAM_DATA    0x00D9
32 #define LAN865X_REG_CFGPARAM_CTRL    0x00DA
33 #define LAN865X_REG_STS2             0x0019
34 #define LAN865X_CFGPARAM_READ_ENABLE BIT(1)
35 
36 /* Collision detection enable/disable registers */
37 #define LAN86XX_DISABLE_COL_DET   0x0000
38 #define LAN86XX_ENABLE_COL_DET    0x8000
39 #define LAN86XX_COL_DET_MASK      0x8000
40 #define LAN86XX_REG_COL_DET_CTRL0 0x0087
41 
42 /* Structure holding configuration register address and value */
43 typedef struct {
44 	uint32_t address;
45 	uint16_t value;
46 } lan865x_config;
47 
48 /* LAN865x Rev.B0/B1 configuration parameters from AN1760
49  * As per the Configuration Application Note AN1760 published in the below link,
50  * https://www.microchip.com/en-us/application-notes/an1760
51  * Revision F (DS60001760G - June 2024)
52  * Addresses 0x0084, 0x008A, 0x00AD, 0x00AE and 0x00AF will be updated with cfgparam1, cfgparam2,
53  * cfgparam3, cfgparam4 and cfgparam5 respectively.
54  *
55  * LAN867x Rev.C1/C2 configuration settings described in AN1699 are equal to
56  * the first 11 configuration settings and all the sqi fixup settings from
57  * LAN865x Rev.B0/B1. So the same fixup registers and values from LAN865x
58  * Rev.B0/B1 are used for LAN867x Rev.C1/C2 to avoid duplication.
59  * Refer the below link for the AN1699,
60  * https://www.microchip.com/en-us/application-notes/an1699
61  * Revision E (DS60001699F - June 2024)
62  */
63 static lan865x_config lan865x_revb_config[] = {
64 	{.address = 0x00D0, .value = 0x3F31}, {.address = 0x00E0, .value = 0xC000},
65 	{.address = 0x0084, .value = 0x0000}, {.address = 0x008A, .value = 0x0000},
66 	{.address = 0x00E9, .value = 0x9E50}, {.address = 0x00F5, .value = 0x1CF8},
67 	{.address = 0x00F4, .value = 0xC020}, {.address = 0x00F8, .value = 0xB900},
68 	{.address = 0x00F9, .value = 0x4E53}, {.address = 0x0081, .value = 0x0080},
69 	{.address = 0x0091, .value = 0x9660}, {.address = 0x0043, .value = 0x00FF},
70 	{.address = 0x0044, .value = 0xFFFF}, {.address = 0x0045, .value = 0x0000},
71 	{.address = 0x0053, .value = 0x00FF}, {.address = 0x0054, .value = 0xFFFF},
72 	{.address = 0x0055, .value = 0x0000}, {.address = 0x0040, .value = 0x0002},
73 	{.address = 0x0050, .value = 0x0002}, {.address = 0x00AD, .value = 0x0000},
74 	{.address = 0x00AE, .value = 0x0000}, {.address = 0x00AF, .value = 0x0000},
75 	{.address = 0x00B0, .value = 0x0103}, {.address = 0x00B1, .value = 0x0910},
76 	{.address = 0x00B2, .value = 0x1D26}, {.address = 0x00B3, .value = 0x002A},
77 	{.address = 0x00B4, .value = 0x0103}, {.address = 0x00B5, .value = 0x070D},
78 	{.address = 0x00B6, .value = 0x1720}, {.address = 0x00B7, .value = 0x0027},
79 	{.address = 0x00B8, .value = 0x0509}, {.address = 0x00B9, .value = 0x0E13},
80 	{.address = 0x00BA, .value = 0x1C25}, {.address = 0x00BB, .value = 0x002B},
81 };
82 
83 struct mc_t1s_plca_config {
84 	bool enable;
85 	uint8_t node_id;
86 	uint8_t node_count;
87 	uint8_t burst_count;
88 	uint8_t burst_timer;
89 	uint8_t to_timer;
90 };
91 
92 struct mc_t1s_config {
93 	uint8_t phy_addr;
94 	const struct device *mdio;
95 	struct mc_t1s_plca_config *plca;
96 };
97 
98 struct mc_t1s_data {
99 	const struct device *dev;
100 	struct phy_link_state state;
101 	phy_callback_t cb;
102 	void *cb_data;
103 	struct k_work_delayable phy_monitor_work;
104 };
105 
phy_mc_t1s_read(const struct device * dev,uint16_t reg,uint32_t * data)106 static int phy_mc_t1s_read(const struct device *dev, uint16_t reg, uint32_t *data)
107 {
108 	const struct mc_t1s_config *cfg = dev->config;
109 
110 	/* Make sure excessive bits 16-31 are reset */
111 	*data = 0U;
112 
113 	return mdio_read(cfg->mdio, cfg->phy_addr, reg, (uint16_t *)data);
114 }
115 
phy_mc_t1s_write(const struct device * dev,uint16_t reg,uint32_t data)116 static int phy_mc_t1s_write(const struct device *dev, uint16_t reg, uint32_t data)
117 {
118 	const struct mc_t1s_config *cfg = dev->config;
119 
120 	return mdio_write(cfg->mdio, cfg->phy_addr, reg, (uint16_t)data);
121 }
122 
mdio_setup_c45_indirect_access(const struct device * dev,uint16_t devad,uint16_t reg)123 static int mdio_setup_c45_indirect_access(const struct device *dev, uint16_t devad, uint16_t reg)
124 {
125 	const struct mc_t1s_config *cfg = dev->config;
126 	int ret;
127 
128 	ret = mdio_write(cfg->mdio, cfg->phy_addr, MII_MMD_ACR, devad);
129 	if (ret) {
130 		return ret;
131 	}
132 
133 	ret = mdio_write(cfg->mdio, cfg->phy_addr, MII_MMD_AADR, reg);
134 	if (ret < 0) {
135 		return ret;
136 	}
137 
138 	return mdio_write(cfg->mdio, cfg->phy_addr, MII_MMD_ACR, devad | BIT(14));
139 }
140 
phy_mc_t1s_c45_read(const struct device * dev,uint8_t devad,uint16_t reg,uint16_t * val)141 static int phy_mc_t1s_c45_read(const struct device *dev, uint8_t devad, uint16_t reg, uint16_t *val)
142 {
143 	const struct mc_t1s_config *cfg = dev->config;
144 	int ret;
145 
146 	ret = mdio_read_c45(cfg->mdio, cfg->phy_addr, devad, reg, val);
147 	/* @retval -ENOSYS if read using Clause 45 direct access is not supported */
148 	if (ret == -ENOSYS) {
149 		/* Read C45 registers using C22 indirect access registers */
150 		ret = mdio_setup_c45_indirect_access(dev, devad, reg);
151 		if (ret) {
152 			return ret;
153 		}
154 
155 		return mdio_read(cfg->mdio, cfg->phy_addr, MII_MMD_AADR, val);
156 	}
157 
158 	return ret;
159 }
160 
phy_mc_t1s_c45_write(const struct device * dev,uint8_t devad,uint16_t reg,uint16_t val)161 static int phy_mc_t1s_c45_write(const struct device *dev, uint8_t devad, uint16_t reg, uint16_t val)
162 {
163 	const struct mc_t1s_config *cfg = dev->config;
164 	int ret;
165 
166 	ret = mdio_write_c45(cfg->mdio, cfg->phy_addr, devad, reg, val);
167 	/* @retval -ENOSYS if write using Clause 45 direct access is not supported */
168 	if (ret == -ENOSYS) {
169 		/* Write C45 registers using C22 indirect access registers */
170 		ret = mdio_setup_c45_indirect_access(dev, devad, reg);
171 		if (ret) {
172 			return ret;
173 		}
174 
175 		return mdio_write(cfg->mdio, cfg->phy_addr, MII_MMD_AADR, val);
176 	}
177 
178 	return ret;
179 }
180 
phy_mc_t1s_get_link(const struct device * dev,struct phy_link_state * state)181 static int phy_mc_t1s_get_link(const struct device *dev, struct phy_link_state *state)
182 {
183 	const struct mc_t1s_config *cfg = dev->config;
184 	struct mc_t1s_data *data = dev->data;
185 	struct phy_link_state old_state = data->state;
186 	uint32_t value = 0;
187 	int ret;
188 
189 	ret = phy_mc_t1s_read(dev, MII_BMSR, &value);
190 	if (ret) {
191 		LOG_ERR("Failed MII_BMSR register read: %d\n", ret);
192 		return ret;
193 	}
194 
195 	state->is_up = value & MII_BMSR_LINK_STATUS;
196 	state->speed = LINK_HALF_10BASE_T;
197 
198 	if (memcmp(&old_state, state, sizeof(struct phy_link_state)) != 0) {
199 		if (state->is_up) {
200 			LOG_INF("PHY (%d) Link speed 10 Mbps, half duplex\n", cfg->phy_addr);
201 		}
202 	}
203 
204 	return 0;
205 }
206 
phy_mc_t1s_link_cb_set(const struct device * dev,phy_callback_t cb,void * user_data)207 static int phy_mc_t1s_link_cb_set(const struct device *dev, phy_callback_t cb, void *user_data)
208 {
209 	struct mc_t1s_data *data = dev->data;
210 
211 	data->cb = cb;
212 	data->cb_data = user_data;
213 
214 	if (data->cb) {
215 		data->cb(dev, &data->state, data->cb_data);
216 	}
217 
218 	return 0;
219 }
220 
phy_monitor_work_handler(struct k_work * work)221 static void phy_monitor_work_handler(struct k_work *work)
222 {
223 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
224 	struct mc_t1s_data *const data = CONTAINER_OF(dwork, struct mc_t1s_data, phy_monitor_work);
225 	const struct device *dev = data->dev;
226 
227 	if (!data->cb) {
228 		return;
229 	}
230 
231 	phy_mc_t1s_get_link(dev, &data->state);
232 
233 	data->cb(dev, &data->state, data->cb_data);
234 
235 	/* Submit delayed work */
236 	k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
237 }
238 
239 /* Pulled from AN1760 describing 'indirect read'
240  *
241  * write_register(0x4, 0x00D8, addr)
242  * write_register(0x4, 0x00DA, 0x2)
243  * return (int8)(read_register(0x4, 0x00D9))
244  *
245  * 0x4 refers to memory map selector 4, which maps to MDIO_MMD_VENDOR_SPECIFIC2
246  */
lan865x_indirect_read(const struct device * dev,uint16_t addr,uint16_t * value)247 static int lan865x_indirect_read(const struct device *dev, uint16_t addr, uint16_t *value)
248 {
249 	int ret;
250 
251 	ret = phy_mc_t1s_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC2, LAN865X_REG_CFGPARAM_ADDR, addr);
252 	if (ret) {
253 		return ret;
254 	}
255 
256 	ret = phy_mc_t1s_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC2, LAN865X_REG_CFGPARAM_CTRL,
257 				   LAN865X_CFGPARAM_READ_ENABLE);
258 	if (ret) {
259 		return ret;
260 	}
261 
262 	return phy_mc_t1s_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC2, LAN865X_REG_CFGPARAM_DATA,
263 				   value);
264 }
265 
lan865x_calculate_offset(const struct device * dev,uint16_t address,int8_t * offset)266 static int lan865x_calculate_offset(const struct device *dev, uint16_t address, int8_t *offset)
267 {
268 	uint16_t value;
269 	int ret;
270 
271 	ret = lan865x_indirect_read(dev, address, &value);
272 	if (ret) {
273 		return ret;
274 	}
275 
276 	/* 5-bit signed value, sign extend */
277 	value &= GENMASK(4, 0);
278 	if (value & BIT(4)) {
279 		*offset = (int8_t)((uint8_t)value - 0x20);
280 	} else {
281 		*offset = (int8_t)value;
282 	}
283 
284 	return 0;
285 }
286 
lan865x_update_cfgparam(uint32_t address,uint16_t cfgparam)287 static void lan865x_update_cfgparam(uint32_t address, uint16_t cfgparam)
288 {
289 	for (uint8_t i = 0; i < ARRAY_SIZE(lan865x_revb_config); i++) {
290 		if (lan865x_revb_config[i].address == address) {
291 			lan865x_revb_config[i].value = cfgparam;
292 		}
293 	}
294 }
295 
lan865x_calculate_update_cfgparams(const struct device * dev)296 static int lan865x_calculate_update_cfgparams(const struct device *dev)
297 {
298 	uint16_t cfgparam;
299 	int8_t offset1;
300 	int8_t offset2;
301 	int ret;
302 
303 	/* Calculate offset1 */
304 	ret = lan865x_calculate_offset(dev, 0x04, &offset1);
305 	if (ret) {
306 		return ret;
307 	}
308 
309 	/* Calculate offset2 */
310 	ret = lan865x_calculate_offset(dev, 0x08, &offset2);
311 	if (ret) {
312 		return ret;
313 	}
314 
315 	/* Calculate & update cfgparam1 for configuration */
316 	cfgparam = (uint16_t)(((9 + offset1) & 0x3F) << 10) |
317 		   (uint16_t)(((14 + offset1) & 0x3F) << 4) | 0x03;
318 	lan865x_update_cfgparam(0x0084, cfgparam);
319 
320 	/* Calculate & update cfgparam2 for configuration */
321 	cfgparam = (uint16_t)(((40 + offset2) & 0x3F) << 10);
322 	lan865x_update_cfgparam(0x008A, cfgparam);
323 
324 	/* Calculate & update cfgparam3 for configuration */
325 	cfgparam = (uint16_t)(((5 + offset1) & 0x3F) << 8) | (uint16_t)((9 + offset1) & 0x3F);
326 	lan865x_update_cfgparam(0x00AD, cfgparam);
327 
328 	/* Calculate & update cfgparam4 for configuration */
329 	cfgparam = (uint16_t)(((9 + offset1) & 0x3F) << 8) | (uint16_t)((14 + offset1) & 0x3F);
330 	lan865x_update_cfgparam(0x00AE, cfgparam);
331 
332 	/* Calculate & update cfgparam5 for configuration */
333 	cfgparam = (uint16_t)(((17 + offset1) & 0x3F) << 8) | (uint16_t)((22 + offset1) & 0x3F);
334 	lan865x_update_cfgparam(0x00AF, cfgparam);
335 
336 	return 0;
337 }
338 
phy_mc_lan865x_revb_config_init(const struct device * dev)339 static int phy_mc_lan865x_revb_config_init(const struct device *dev)
340 {
341 	int ret;
342 
343 	ret = lan865x_calculate_update_cfgparams(dev);
344 	if (ret) {
345 		return ret;
346 	}
347 
348 	/* Configure lan865x initial settings */
349 	for (int i = 0; i < ARRAY_SIZE(lan865x_revb_config); i++) {
350 		ret = phy_mc_t1s_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC2,
351 					   lan865x_revb_config[i].address,
352 					   lan865x_revb_config[i].value);
353 		if (ret) {
354 			return ret;
355 		}
356 	}
357 
358 	return 0;
359 }
360 
361 /* LAN867x Rev.C1/C2 configuration settings are equal to the first 11 configuration settings and all
362  * the sqi fixup settings from LAN865x Rev.B0/B1. So the same fixup registers and values from
363  * LAN865x Rev.B0/B1 are used for LAN867x Rev.C1/C2 to avoid duplication.
364  * Refer the below links for the comparison.
365  * https://www.microchip.com/en-us/application-notes/an1760
366  * Revision F (DS60001760G - June 2024)
367  * https://www.microchip.com/en-us/application-notes/an1699
368  * Revision E (DS60001699F - June 2024)
369  */
phy_mc_lan867x_revc_config_init(const struct device * dev)370 static int phy_mc_lan867x_revc_config_init(const struct device *dev)
371 {
372 	int ret;
373 
374 	ret = lan865x_calculate_update_cfgparams(dev);
375 	if (ret) {
376 		return ret;
377 	}
378 
379 	for (int i = 0; i < ARRAY_SIZE(lan865x_revb_config); i++) {
380 		ret = phy_mc_t1s_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC2,
381 					   lan865x_revb_config[i].address,
382 					   lan865x_revb_config[i].value);
383 		if (ret) {
384 			return ret;
385 		}
386 
387 		/* LAN867x Rev.C1/C2 configuration settings are equal to the first 11 configuration
388 		 * settings and all the sqi fixup settings from LAN865x Rev.B0/B1. So the 8
389 		 * inbetween configuration settings are skipped.
390 		 */
391 		if (i == 10) {
392 			i += 8;
393 		}
394 	}
395 
396 	return 0;
397 }
398 
lan86xx_config_collision_detection(const struct device * dev,bool plca_enable)399 static int lan86xx_config_collision_detection(const struct device *dev, bool plca_enable)
400 {
401 	uint16_t val;
402 	uint16_t new;
403 	int ret;
404 
405 	ret = phy_mc_t1s_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC2, LAN86XX_REG_COL_DET_CTRL0, &val);
406 	if (ret) {
407 		return ret;
408 	}
409 
410 	if (plca_enable) {
411 		new = (val & ~LAN86XX_COL_DET_MASK) | LAN86XX_DISABLE_COL_DET;
412 	} else {
413 		new = (val & ~LAN86XX_COL_DET_MASK) | LAN86XX_ENABLE_COL_DET;
414 	}
415 
416 	if (new == val) {
417 		return 0;
418 	}
419 
420 	return phy_mc_t1s_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC2, LAN86XX_REG_COL_DET_CTRL0, new);
421 }
422 
phy_mc_t1s_cfg_link(const struct device * dev,enum phy_link_speed speeds)423 static int phy_mc_t1s_cfg_link(const struct device *dev, enum phy_link_speed speeds)
424 {
425 	ARG_UNUSED(dev);
426 
427 	if (speeds & LINK_HALF_10BASE_T) {
428 		return 0;
429 	}
430 
431 	return -ENOTSUP;
432 }
433 
phy_mc_t1s_id(const struct device * dev,uint32_t * phy_id)434 static int phy_mc_t1s_id(const struct device *dev, uint32_t *phy_id)
435 {
436 	uint32_t value;
437 	int ret;
438 
439 	ret = phy_mc_t1s_read(dev, MII_PHYID1R, &value);
440 	if (ret) {
441 		LOG_ERR("Failed MII_PHYID1R register read: %d\n", ret);
442 		return ret;
443 	}
444 
445 	*phy_id = value << 16;
446 
447 	ret = phy_mc_t1s_read(dev, MII_PHYID2R, &value);
448 	if (ret) {
449 		LOG_ERR("Failed MII_PHYID2R register read: %d\n", ret);
450 		return ret;
451 	}
452 
453 	*phy_id |= value;
454 
455 	return 0;
456 }
457 
phy_mc_t1s_set_plca_cfg(const struct device * dev,struct phy_plca_cfg * plca_cfg)458 static int phy_mc_t1s_set_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg)
459 {
460 	int ret;
461 
462 	ret = genphy_set_plca_cfg(dev, plca_cfg);
463 	if (ret) {
464 		return ret;
465 	}
466 
467 	return lan86xx_config_collision_detection(dev, plca_cfg->enable);
468 }
469 
phy_mc_t1s_set_dt_plca(const struct device * dev)470 static int phy_mc_t1s_set_dt_plca(const struct device *dev)
471 {
472 	const struct mc_t1s_config *cfg = dev->config;
473 	struct phy_plca_cfg plca_cfg;
474 
475 	if (!cfg->plca->enable) {
476 		return 0;
477 	}
478 
479 	plca_cfg.enable = cfg->plca->enable;
480 	plca_cfg.node_id = cfg->plca->node_id;
481 	plca_cfg.node_count = cfg->plca->node_count;
482 	plca_cfg.burst_count = cfg->plca->burst_count;
483 	plca_cfg.burst_timer = cfg->plca->burst_timer;
484 	plca_cfg.to_timer = cfg->plca->to_timer;
485 
486 	return phy_mc_t1s_set_plca_cfg(dev, &plca_cfg);
487 }
488 
phy_mc_t1s_init(const struct device * dev)489 static int phy_mc_t1s_init(const struct device *dev)
490 {
491 	struct mc_t1s_data *data = dev->data;
492 	uint32_t phy_id;
493 	int ret;
494 
495 	data->dev = dev;
496 
497 	ret = phy_mc_t1s_id(dev, &phy_id);
498 	if (ret) {
499 		return ret;
500 	}
501 
502 	switch (phy_id) {
503 	case PHY_ID_LAN867X_REVC1:
504 	case PHY_ID_LAN867X_REVC2:
505 		ret = phy_mc_lan867x_revc_config_init(dev);
506 		if (ret) {
507 			LOG_ERR("PHY initial configuration error: %d\n", ret);
508 			return ret;
509 		}
510 		break;
511 	case PHY_ID_LAN865X_REVB:
512 		ret = phy_mc_lan865x_revb_config_init(dev);
513 		if (ret) {
514 			LOG_ERR("PHY initial configuration error: %d\n", ret);
515 			return ret;
516 		}
517 		break;
518 	default:
519 		LOG_ERR("Unsupported PHY ID: %x\n", phy_id);
520 		return -ENODEV;
521 	}
522 
523 	ret = phy_mc_t1s_set_dt_plca(dev);
524 	if (ret) {
525 		return ret;
526 	}
527 
528 	k_work_init_delayable(&data->phy_monitor_work, phy_monitor_work_handler);
529 	phy_monitor_work_handler(&data->phy_monitor_work.work);
530 
531 	return 0;
532 }
533 
534 static DEVICE_API(ethphy, mc_t1s_phy_api) = {
535 	.get_link = phy_mc_t1s_get_link,
536 	.cfg_link = phy_mc_t1s_cfg_link,
537 	.link_cb_set = phy_mc_t1s_link_cb_set,
538 	.set_plca_cfg = phy_mc_t1s_set_plca_cfg,
539 	.get_plca_cfg = genphy_get_plca_cfg,
540 	.get_plca_sts = genphy_get_plca_sts,
541 	.read = phy_mc_t1s_read,
542 	.write = phy_mc_t1s_write,
543 	.read_c45 = phy_mc_t1s_c45_read,
544 	.write_c45 = phy_mc_t1s_c45_write,
545 };
546 
547 #define MICROCHIP_T1S_PHY_INIT(n)                                                                  \
548 	static struct mc_t1s_plca_config mc_t1s_plca_##n##_config = {                              \
549 		.enable = DT_INST_PROP(n, plca_enable),                                            \
550 		.node_id = DT_INST_PROP(n, plca_node_id),                                          \
551 		.node_count = DT_INST_PROP(n, plca_node_count),                                    \
552 		.burst_count = DT_INST_PROP(n, plca_burst_count),                                  \
553 		.burst_timer = DT_INST_PROP(n, plca_burst_timer),                                  \
554 		.to_timer = DT_INST_PROP(n, plca_to_timer),                                        \
555 	};                                                                                         \
556                                                                                                    \
557 	static const struct mc_t1s_config mc_t1s_##n##_config = {                                  \
558 		.phy_addr = DT_INST_REG_ADDR(n),                                                   \
559 		.mdio = DEVICE_DT_GET(DT_INST_PARENT(n)),                                          \
560 		.plca = &mc_t1s_plca_##n##_config,                                                 \
561 	};                                                                                         \
562                                                                                                    \
563 	static struct mc_t1s_data mc_t1s_##n##_data;                                               \
564                                                                                                    \
565 	DEVICE_DT_INST_DEFINE(n, &phy_mc_t1s_init, NULL, &mc_t1s_##n##_data, &mc_t1s_##n##_config, \
566 			      POST_KERNEL, CONFIG_PHY_MICROCHIP_T1S_INIT_PRIORITY, &mc_t1s_phy_api);
567 
568 DT_INST_FOREACH_STATUS_OKAY(MICROCHIP_T1S_PHY_INIT);
569