1 /*
2 * Copyright (c) 2023 PHOENIX CONTACT Electronics GmbH
3 * Copyright 2023 NXP
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/logging/log.h>
9
10 LOG_MODULE_REGISTER(DT_DRV_COMPAT, CONFIG_PHY_LOG_LEVEL);
11
12 #include <errno.h>
13 #include <stdint.h>
14 #include <stdbool.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/device.h>
17 #include <zephyr/sys/util.h>
18 #include <zephyr/net/phy.h>
19 #include <zephyr/net/mii.h>
20 #include <zephyr/net/mdio.h>
21 #include <zephyr/drivers/mdio.h>
22
23 /* PHYs out of reset check retry delay */
24 #define ADIN2111_PHY_AWAIT_DELAY_POLL_US 15U
25 /*
26 * Number of retries for PHYs out of reset check,
27 * rmii variants as ADIN11XX need 70ms maximum after hw reset to be up,
28 * so the increasing the count for that, as default 25ms (sw reset) + 45.
29 */
30 #define ADIN2111_PHY_AWAIT_RETRY_COUNT 3000U
31
32 /* PHY's software powerdown check retry delay */
33 #define ADIN2111_PHY_SFT_PD_DELAY_POLL_US 15U
34 /* Number of retries for PHY's software powerdown check */
35 #define ADIN2111_PHY_SFT_PD_RETRY_COUNT 200U
36
37 /* Software reset, CLK_25 disabled time*/
38 #define ADIN1100_PHY_SFT_RESET_MS 25U
39
40 /* PHYs autonegotiation complete timeout */
41 #define ADIN2111_AN_COMPLETE_AWAIT_TIMEOUT_MS 3000U
42
43 /* ADIN2111 PHY identifier */
44 #define ADIN2111_PHY_ID 0x0283BCA1U
45 #define ADIN1110_PHY_ID 0x0283BC91U
46 #define ADIN1100_PHY_ID 0x0283BC81U
47
48 /* System Interrupt Mask Register */
49 #define ADIN2111_PHY_CRSM_IRQ_MASK 0x0020U
50 /* System Interrupt Status Register */
51 #define ADIN2111_PHY_CRSM_IRQ_STATUS 0x0010U
52 /**
53 * Mask of reserved interrupts that indicates a fatal error in the system.
54 *
55 * There is inconsistency between RM and ADI driver example:
56 * - RM mask 0x6FFF
57 * - ADI driver example mask 0x2BFF
58 *
59 * The value from the example doesn't include reserved bits 10 and 14.
60 * The tests show that PHY is still functioning when bit 10 is raised.
61 *
62 * Here the value from ADI driver example is used instead of RM.
63 */
64 #define ADIN2111_PHY_CRSM_IRQ_STATUS_FATAL_ERR 0x2BFFU
65
66 /* PHY Subsystem Interrupt Mask Register */
67 #define ADIN2111_PHY_SUBSYS_IRQ_MASK 0x0021U
68 /* PHY Subsystem Interrupt Status Register */
69 #define ADIN2111_PHY_SUBSYS_IRQ_STATUS 0x0011U
70 /* Link Status Change */
71 #define ADIN2111_PHY_SUBSYS_IRQ_STATUS_LINK_STAT_CHNG_LH BIT(1)
72
73 /* Software Power-down Control Register */
74 #define ADIN2111_PHY_CRSM_SFT_PD_CNTRL 0x8812U
75 /* System Status Register */
76 #define ADIN2111_PHY_CRSM_STAT 0x8818U
77 /* Software Power-down Status */
78 #define ADIN2111_CRSM_STAT_CRSM_SFT_PD_RDY BIT(1)
79
80 /* LED Control Register */
81 #define ADIN2111_PHY_LED_CNTRL 0x8C82U
82 /* LED 1 Enable */
83 #define ADIN2111_PHY_LED_CNTRL_LED1_EN BIT(15)
84 /* LED 0 Enable */
85 #define ADIN2111_PHY_LED_CNTRL_LED0_EN BIT(7)
86
87 /* MMD bridge regs */
88 #define ADIN1100_MMD_ACCESS_CNTRL 0x0DU
89 #define ADIN1100_MMD_ACCESS 0x0EU
90
91 struct phy_adin2111_config {
92 const struct device *mdio;
93 uint8_t phy_addr;
94 bool led0_en;
95 bool led1_en;
96 bool tx_24v;
97 bool mii;
98 };
99
100 struct phy_adin2111_data {
101 const struct device *dev;
102 struct phy_link_state state;
103 struct k_sem sem;
104 struct k_work_delayable monitor_work;
105 phy_callback_t cb;
106 void *cb_data;
107 };
108
phy_adin2111_c22_read(const struct device * dev,uint16_t reg,uint16_t * val)109 static inline int phy_adin2111_c22_read(const struct device *dev, uint16_t reg,
110 uint16_t *val)
111 {
112 const struct phy_adin2111_config *const cfg = dev->config;
113
114 return mdio_read(cfg->mdio, cfg->phy_addr, reg, val);
115 }
116
phy_adin2111_c22_write(const struct device * dev,uint16_t reg,uint16_t val)117 static inline int phy_adin2111_c22_write(const struct device *dev, uint16_t reg,
118 uint16_t val)
119 {
120 const struct phy_adin2111_config *const cfg = dev->config;
121
122 return mdio_write(cfg->mdio, cfg->phy_addr, reg, val);
123 }
124
phy_adin2111_c45_setup_dev_reg(const struct device * dev,uint16_t devad,uint16_t reg)125 static int phy_adin2111_c45_setup_dev_reg(const struct device *dev, uint16_t devad,
126 uint16_t reg)
127 {
128 const struct phy_adin2111_config *cfg = dev->config;
129 int rval;
130
131 rval = mdio_write(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS_CNTRL, devad);
132 if (rval < 0) {
133 return rval;
134 }
135 rval = mdio_write(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS, reg);
136 if (rval < 0) {
137 return rval;
138 }
139
140 return mdio_write(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS_CNTRL, devad | BIT(14));
141 }
142
phy_adin2111_c45_read(const struct device * dev,uint16_t devad,uint16_t reg,uint16_t * val)143 static int phy_adin2111_c45_read(const struct device *dev, uint16_t devad,
144 uint16_t reg, uint16_t *val)
145 {
146 const struct phy_adin2111_config *cfg = dev->config;
147 int rval;
148
149 if (cfg->mii) {
150 /* Using C22 -> devad bridge */
151 rval = phy_adin2111_c45_setup_dev_reg(dev, devad, reg);
152 if (rval < 0) {
153 return rval;
154 }
155
156 return mdio_read(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS, val);
157 }
158
159 return mdio_read_c45(cfg->mdio, cfg->phy_addr, devad, reg, val);
160 }
161
phy_adin2111_c45_write(const struct device * dev,uint16_t devad,uint16_t reg,uint16_t val)162 static int phy_adin2111_c45_write(const struct device *dev, uint16_t devad,
163 uint16_t reg, uint16_t val)
164 {
165 const struct phy_adin2111_config *cfg = dev->config;
166 int rval;
167
168 if (cfg->mii) {
169 /* Using C22 -> devad bridge */
170 rval = phy_adin2111_c45_setup_dev_reg(dev, devad, reg);
171 if (rval < 0) {
172 return rval;
173 }
174
175 return mdio_write(cfg->mdio, cfg->phy_addr, ADIN1100_MMD_ACCESS, val);
176 }
177
178 return mdio_write_c45(cfg->mdio, cfg->phy_addr, devad, reg, val);
179 }
180
phy_adin2111_reg_read(const struct device * dev,uint16_t reg_addr,uint32_t * data)181 static int phy_adin2111_reg_read(const struct device *dev, uint16_t reg_addr,
182 uint32_t *data)
183 {
184 const struct phy_adin2111_config *cfg = dev->config;
185 int ret;
186
187 mdio_bus_enable(cfg->mdio);
188
189 ret = phy_adin2111_c22_read(dev, reg_addr, (uint16_t *) data);
190
191 mdio_bus_disable(cfg->mdio);
192
193 return ret;
194 }
195
phy_adin2111_reg_write(const struct device * dev,uint16_t reg_addr,uint32_t data)196 static int phy_adin2111_reg_write(const struct device *dev, uint16_t reg_addr,
197 uint32_t data)
198 {
199 const struct phy_adin2111_config *cfg = dev->config;
200 int ret;
201
202 mdio_bus_enable(cfg->mdio);
203
204 ret = phy_adin2111_c22_write(dev, reg_addr, (uint16_t) data);
205
206 mdio_bus_disable(cfg->mdio);
207
208 return ret;
209 }
210
phy_adin2111_await_phy(const struct device * dev)211 static int phy_adin2111_await_phy(const struct device *dev)
212 {
213 int ret;
214 uint32_t count;
215 uint16_t val;
216
217 /**
218 * Port 2 PHY comes out of reset after Port 1 PHY,
219 * wait until both are out of reset.
220 * Reading Port 2 PHY registers returns 0s until
221 * it comes out from reset.
222 */
223 for (count = 0U; count < ADIN2111_PHY_AWAIT_RETRY_COUNT; ++count) {
224 ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
225 ADIN2111_PHY_CRSM_IRQ_MASK, &val);
226 if (ret >= 0) {
227 if (val != 0U) {
228 break;
229 }
230 ret = -ETIMEDOUT;
231 }
232 k_sleep(K_USEC(ADIN2111_PHY_AWAIT_DELAY_POLL_US));
233 }
234
235 return ret;
236 }
237
phy_adin2111_an_state_read(const struct device * dev)238 static int phy_adin2111_an_state_read(const struct device *dev)
239 {
240 struct phy_adin2111_data *const data = dev->data;
241 uint16_t bmsr;
242 int ret;
243
244 /* read twice to get actual link status, latch low */
245 ret = phy_adin2111_c22_read(dev, MII_BMSR, &bmsr);
246 if (ret < 0) {
247 return ret;
248 }
249 ret = phy_adin2111_c22_read(dev, MII_BMSR, &bmsr);
250 if (ret < 0) {
251 return ret;
252 }
253
254 data->state.is_up = !!(bmsr & MII_BMSR_LINK_STATUS);
255
256 return 0;
257 }
258
phy_adin2111_handle_phy_irq(const struct device * dev,struct phy_link_state * state)259 int phy_adin2111_handle_phy_irq(const struct device *dev,
260 struct phy_link_state *state)
261 {
262 struct phy_adin2111_data *const data = dev->data;
263 uint16_t subsys_status;
264 int ret;
265
266 ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC2,
267 ADIN2111_PHY_SUBSYS_IRQ_STATUS,
268 &subsys_status);
269 if (ret < 0) {
270 return ret;
271 }
272
273 if ((subsys_status & ADIN2111_PHY_SUBSYS_IRQ_STATUS_LINK_STAT_CHNG_LH) == 0U) {
274 /* nothing to process */
275 return -EAGAIN;
276 }
277
278 k_sem_take(&data->sem, K_FOREVER);
279
280 ret = phy_adin2111_an_state_read(dev);
281
282 memcpy(state, &data->state, sizeof(struct phy_link_state));
283
284 k_sem_give(&data->sem);
285
286 return ret;
287 }
288
phy_adin2111_sft_pd(const struct device * dev,bool enter)289 static int phy_adin2111_sft_pd(const struct device *dev, bool enter)
290 {
291 int ret;
292 uint32_t count;
293 const uint16_t expected = enter ? ADIN2111_CRSM_STAT_CRSM_SFT_PD_RDY : 0U;
294 uint16_t val;
295
296 ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1,
297 ADIN2111_PHY_CRSM_SFT_PD_CNTRL,
298 enter ? 1U : 0U);
299 if (ret < 0) {
300 return ret;
301 }
302
303 for (count = 0U; count < ADIN2111_PHY_SFT_PD_RETRY_COUNT; ++count) {
304 ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
305 ADIN2111_PHY_CRSM_STAT, &val);
306 if (ret >= 0) {
307 if ((val & ADIN2111_CRSM_STAT_CRSM_SFT_PD_RDY) == expected) {
308 break;
309 }
310 ret = -ETIMEDOUT;
311 }
312 k_sleep(K_USEC(ADIN2111_PHY_SFT_PD_DELAY_POLL_US));
313 }
314
315 return ret;
316 }
317
phy_adin2111_id(const struct device * dev,uint32_t * phy_id)318 static int phy_adin2111_id(const struct device *dev, uint32_t *phy_id)
319 {
320 uint16_t val;
321
322 if (phy_adin2111_c22_read(dev, MII_PHYID1R, &val) < 0) {
323 return -EIO;
324 }
325
326 *phy_id = (val & UINT16_MAX) << 16;
327
328 if (phy_adin2111_c22_read(dev, MII_PHYID2R, &val) < 0) {
329 return -EIO;
330 }
331
332 *phy_id |= (val & UINT16_MAX);
333
334 return 0;
335 }
336
phy_adin2111_get_link_state(const struct device * dev,struct phy_link_state * state)337 static int phy_adin2111_get_link_state(const struct device *dev,
338 struct phy_link_state *state)
339 {
340 struct phy_adin2111_data *const data = dev->data;
341
342 k_sem_take(&data->sem, K_FOREVER);
343
344 memcpy(state, &data->state, sizeof(struct phy_link_state));
345
346 k_sem_give(&data->sem);
347
348 return 0;
349 }
350
phy_adin2111_cfg_link(const struct device * dev,enum phy_link_speed adv_speeds)351 static int phy_adin2111_cfg_link(const struct device *dev,
352 enum phy_link_speed adv_speeds)
353 {
354 ARG_UNUSED(dev);
355
356 if (!!(adv_speeds & LINK_FULL_10BASE_T)) {
357 return 0;
358 }
359
360 return -ENOTSUP;
361 }
362
phy_adin2111_reset(const struct device * dev)363 static int phy_adin2111_reset(const struct device *dev)
364 {
365 int ret;
366
367 ret = phy_adin2111_c22_write(dev, MII_BMCR, MII_BMCR_RESET);
368 if (ret < 0) {
369 return ret;
370 }
371
372 k_msleep(ADIN1100_PHY_SFT_RESET_MS);
373
374 return 0;
375 }
376
invoke_link_cb(const struct device * dev)377 static void invoke_link_cb(const struct device *dev)
378 {
379 struct phy_adin2111_data *const data = dev->data;
380 struct phy_link_state state;
381
382 if (data->cb == NULL) {
383 return;
384 }
385
386 data->cb(dev, &state, data->cb_data);
387 }
388
update_link_state(const struct device * dev)389 static int update_link_state(const struct device *dev)
390 {
391 struct phy_adin2111_data *const data = dev->data;
392 const struct phy_adin2111_config *config = dev->config;
393 struct phy_link_state old_state;
394 uint16_t bmsr;
395 int ret;
396
397 ret = phy_adin2111_c22_read(dev, MII_BMSR, &bmsr);
398 if (ret < 0) {
399 return ret;
400 }
401
402 old_state = data->state;
403 data->state.is_up = !!(bmsr & MII_BMSR_LINK_STATUS);
404
405 if (old_state.speed != data->state.speed || old_state.is_up != data->state.is_up) {
406
407 LOG_INF("PHY (%d) Link is %s", config->phy_addr, data->state.is_up ? "up" : "down");
408
409 if (data->state.is_up == false) {
410 return 0;
411 }
412
413 invoke_link_cb(dev);
414
415 LOG_INF("PHY (%d) Link speed %s Mb, %s duplex\n", config->phy_addr,
416 (PHY_LINK_IS_SPEED_100M(data->state.speed) ? "100" : "10"),
417 PHY_LINK_IS_FULL_DUPLEX(data->state.speed) ? "full" : "half");
418 }
419
420 return 0;
421 }
422
monitor_work_handler(struct k_work * work)423 static void monitor_work_handler(struct k_work *work)
424 {
425 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
426 struct phy_adin2111_data *const data =
427 CONTAINER_OF(dwork, struct phy_adin2111_data, monitor_work);
428 const struct device *dev = data->dev;
429 int rc;
430
431 k_sem_take(&data->sem, K_FOREVER);
432
433 rc = update_link_state(dev);
434
435 k_sem_give(&data->sem);
436
437 /* Submit delayed work */
438 k_work_reschedule(&data->monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
439 }
440
phy_adin2111_init(const struct device * dev)441 static int phy_adin2111_init(const struct device *dev)
442 {
443 const struct phy_adin2111_config *const cfg = dev->config;
444 struct phy_adin2111_data *const data = dev->data;
445 uint32_t phy_id;
446 uint16_t val;
447 bool tx_24v_supported = false;
448 int ret;
449
450 data->dev = dev;
451 data->state.is_up = false;
452 data->state.speed = LINK_FULL_10BASE_T;
453
454 /*
455 * For adin1100 and further mii stuff,
456 * reset may not be performed from the mac layer, doing a clean reset here.
457 */
458 if (cfg->mii) {
459 ret = phy_adin2111_reset(dev);
460 if (ret < 0) {
461 return ret;
462 }
463 }
464
465 ret = phy_adin2111_await_phy(dev);
466 if (ret < 0) {
467 LOG_ERR("PHY %u didn't come out of reset, %d",
468 cfg->phy_addr, ret);
469 return -ENODEV;
470 }
471
472 ret = phy_adin2111_id(dev, &phy_id);
473 if (ret < 0) {
474 LOG_ERR("Failed to read PHY %u ID, %d",
475 cfg->phy_addr, ret);
476 return -ENODEV;
477 }
478
479 if (phy_id != ADIN2111_PHY_ID && phy_id != ADIN1110_PHY_ID && phy_id != ADIN1100_PHY_ID) {
480 LOG_ERR("PHY %u unexpected PHY ID %X", cfg->phy_addr, phy_id);
481 return -EINVAL;
482 }
483
484 LOG_INF("PHY %u ID %X", cfg->phy_addr, phy_id);
485
486 /* enter software powerdown */
487 ret = phy_adin2111_sft_pd(dev, true);
488 if (ret < 0) {
489 return ret;
490 }
491
492 /* disable interrupts */
493 ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1,
494 ADIN2111_PHY_CRSM_IRQ_MASK, 0U);
495 if (ret < 0) {
496 return ret;
497 }
498
499 /* enable link status change irq */
500 ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC2,
501 ADIN2111_PHY_SUBSYS_IRQ_MASK,
502 ADIN2111_PHY_SUBSYS_IRQ_STATUS_LINK_STAT_CHNG_LH);
503 if (ret < 0) {
504 return ret;
505 }
506
507 /* clear PHY IRQ status before enabling ADIN IRQs */
508 ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
509 ADIN2111_PHY_CRSM_IRQ_STATUS, &val);
510 if (ret < 0) {
511 return ret;
512 }
513
514 if (val & ADIN2111_PHY_CRSM_IRQ_STATUS_FATAL_ERR) {
515 LOG_ERR("PHY %u CRSM reports fatal system error", cfg->phy_addr);
516 return -ENODEV;
517 }
518
519 ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC2,
520 ADIN2111_PHY_SUBSYS_IRQ_STATUS, &val);
521 if (ret < 0) {
522 return ret;
523 }
524
525 if (!cfg->led0_en || !cfg->led1_en) {
526 ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
527 ADIN2111_PHY_LED_CNTRL, &val);
528 if (ret < 0) {
529 return ret;
530 }
531 if (!cfg->led0_en) {
532 val &= ~(ADIN2111_PHY_LED_CNTRL_LED0_EN);
533 }
534 if (!cfg->led1_en) {
535 val &= ~(ADIN2111_PHY_LED_CNTRL_LED1_EN);
536 }
537 ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1,
538 ADIN2111_PHY_LED_CNTRL, val);
539 if (ret < 0) {
540 return ret;
541 }
542 }
543
544 /* check 2.4V support */
545 ret = phy_adin2111_c45_read(dev, MDIO_MMD_PMAPMD, MDIO_PMA_B10L_STAT, &val);
546 if (ret < 0) {
547 return ret;
548 }
549
550 tx_24v_supported = !!(val & MDIO_PMA_B10L_STAT_2V4_ABLE);
551
552 LOG_INF("PHY %u 2.4V mode %s", cfg->phy_addr,
553 tx_24v_supported ? "supported" : "not supported");
554
555 if (!cfg->tx_24v & tx_24v_supported) {
556 LOG_ERR("PHY %u 2.4V mode supported, but not enabled",
557 cfg->phy_addr);
558 }
559
560 /* config 2.4V auto-negotiation */
561 ret = phy_adin2111_c45_read(dev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H, &val);
562 if (ret < 0) {
563 return ret;
564 }
565
566 if (tx_24v_supported) {
567 val |= MDIO_AN_T1_ADV_H_10L_TX_HI;
568 } else {
569 val &= ~MDIO_AN_T1_ADV_H_10L_TX_HI;
570 }
571
572 if (cfg->tx_24v) {
573 if (!tx_24v_supported) {
574 LOG_ERR("PHY %u 2.4V mode enabled, but not supported",
575 cfg->phy_addr);
576 return -EINVAL;
577 }
578
579 val |= MDIO_AN_T1_ADV_H_10L_TX_HI_REQ;
580 } else {
581 val &= ~MDIO_AN_T1_ADV_H_10L_TX_HI_REQ;
582 }
583
584 ret = phy_adin2111_c45_write(dev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H, val);
585 if (ret < 0) {
586 return ret;
587 }
588
589 /* enable auto-negotiation */
590 ret = phy_adin2111_c45_write(dev, MDIO_MMD_AN, MDIO_AN_T1_CTRL,
591 MDIO_AN_T1_CTRL_EN);
592 if (ret < 0) {
593 return ret;
594 }
595
596 if (cfg->mii) {
597 k_work_init_delayable(&data->monitor_work, monitor_work_handler);
598 monitor_work_handler(&data->monitor_work.work);
599 }
600
601 /**
602 * done, PHY is in software powerdown (SFT PD)
603 * exit software powerdown, PHY 1 has to exit before PHY 2
604 * correct PHY order is expected to be in DTS to guarantee that
605 */
606 return phy_adin2111_sft_pd(dev, false);
607 }
608
phy_adin2111_link_cb_set(const struct device * dev,phy_callback_t cb,void * user_data)609 static int phy_adin2111_link_cb_set(const struct device *dev, phy_callback_t cb,
610 void *user_data)
611 {
612 struct phy_adin2111_data *const data = dev->data;
613
614 data->cb = cb;
615 data->cb_data = user_data;
616
617 /* Invoke the callback to notify the caller of the current
618 * link status.
619 */
620 invoke_link_cb(dev);
621
622 return 0;
623 }
624
625 static DEVICE_API(ethphy, phy_adin2111_api) = {
626 .get_link = phy_adin2111_get_link_state,
627 .cfg_link = phy_adin2111_cfg_link,
628 .link_cb_set = phy_adin2111_link_cb_set,
629 .read = phy_adin2111_reg_read,
630 .write = phy_adin2111_reg_write,
631 };
632
633 #define ADIN2111_PHY_INITIALIZE(n, model) \
634 static const struct phy_adin2111_config phy_adin##model##_config_##n = { \
635 .mdio = DEVICE_DT_GET(DT_INST_BUS(n)), \
636 .phy_addr = DT_INST_REG_ADDR(n), \
637 .led0_en = DT_INST_PROP(n, led0_en), \
638 .led1_en = DT_INST_PROP(n, led1_en), \
639 .tx_24v = !(DT_INST_PROP(n, disable_tx_mode_24v)), \
640 IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(adi_adin1100_phy), \
641 (.mii = 1)) \
642 }; \
643 static struct phy_adin2111_data phy_adin##model##_data_##n = { \
644 .sem = Z_SEM_INITIALIZER(phy_adin##model##_data_##n.sem, 1, 1), \
645 }; \
646 DEVICE_DT_INST_DEFINE(n, &phy_adin2111_init, NULL, \
647 &phy_adin##model##_data_##n, \
648 &phy_adin##model##_config_##n, \
649 POST_KERNEL, CONFIG_PHY_INIT_PRIORITY, \
650 &phy_adin2111_api);
651
652 #define DT_DRV_COMPAT adi_adin2111_phy
653 DT_INST_FOREACH_STATUS_OKAY_VARGS(ADIN2111_PHY_INITIALIZE, 2111)
654 #undef DT_DRV_COMPAT
655 #define DT_DRV_COMPAT adi_adin1100_phy
656 DT_INST_FOREACH_STATUS_OKAY_VARGS(ADIN2111_PHY_INITIALIZE, 1100)
657 #undef DT_DRV_COMPAT
658