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 <errno.h>
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/mdio.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/net/mdio.h>
16 #include <zephyr/net/mii.h>
17 #include <zephyr/net/phy.h>
18 #include <zephyr/sys/util.h>
19 #include "phy_adin2111_priv.h"
20
21 LOG_MODULE_REGISTER(phy_adin, CONFIG_PHY_LOG_LEVEL);
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_reset(const struct device * dev)351 static int phy_adin2111_reset(const struct device *dev)
352 {
353 int ret;
354
355 ret = phy_adin2111_c22_write(dev, MII_BMCR, MII_BMCR_RESET);
356 if (ret < 0) {
357 return ret;
358 }
359
360 k_msleep(ADIN1100_PHY_SFT_RESET_MS);
361
362 return 0;
363 }
364
invoke_link_cb(const struct device * dev)365 static void invoke_link_cb(const struct device *dev)
366 {
367 struct phy_adin2111_data *const data = dev->data;
368 struct phy_link_state state;
369
370 if (data->cb == NULL) {
371 return;
372 }
373
374 data->cb(dev, &state, data->cb_data);
375 }
376
update_link_state(const struct device * dev)377 static int update_link_state(const struct device *dev)
378 {
379 struct phy_adin2111_data *const data = dev->data;
380 const struct phy_adin2111_config *config = dev->config;
381 struct phy_link_state old_state;
382 uint16_t bmsr;
383 int ret;
384
385 ret = phy_adin2111_c22_read(dev, MII_BMSR, &bmsr);
386 if (ret < 0) {
387 return ret;
388 }
389
390 old_state = data->state;
391 data->state.is_up = !!(bmsr & MII_BMSR_LINK_STATUS);
392
393 if (old_state.speed != data->state.speed || old_state.is_up != data->state.is_up) {
394
395 LOG_INF("PHY (%d) Link is %s", config->phy_addr, data->state.is_up ? "up" : "down");
396
397 if (data->state.is_up == false) {
398 return 0;
399 }
400
401 invoke_link_cb(dev);
402
403 LOG_INF("PHY (%d) Link speed %s Mb, %s duplex\n", config->phy_addr,
404 (PHY_LINK_IS_SPEED_100M(data->state.speed) ? "100" : "10"),
405 PHY_LINK_IS_FULL_DUPLEX(data->state.speed) ? "full" : "half");
406 }
407
408 return 0;
409 }
410
monitor_work_handler(struct k_work * work)411 static void monitor_work_handler(struct k_work *work)
412 {
413 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
414 struct phy_adin2111_data *const data =
415 CONTAINER_OF(dwork, struct phy_adin2111_data, monitor_work);
416 const struct device *dev = data->dev;
417 int rc;
418
419 k_sem_take(&data->sem, K_FOREVER);
420
421 rc = update_link_state(dev);
422
423 k_sem_give(&data->sem);
424
425 /* Submit delayed work */
426 k_work_reschedule(&data->monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
427 }
428
phy_adin2111_init(const struct device * dev)429 static int phy_adin2111_init(const struct device *dev)
430 {
431 const struct phy_adin2111_config *const cfg = dev->config;
432 struct phy_adin2111_data *const data = dev->data;
433 uint32_t phy_id;
434 uint16_t val;
435 bool tx_24v_supported = false;
436 int ret;
437
438 data->dev = dev;
439 data->state.is_up = false;
440 data->state.speed = LINK_FULL_10BASE;
441
442 /*
443 * For adin1100 and further mii stuff,
444 * reset may not be performed from the mac layer, doing a clean reset here.
445 */
446 if (cfg->mii) {
447 ret = phy_adin2111_reset(dev);
448 if (ret < 0) {
449 return ret;
450 }
451 }
452
453 ret = phy_adin2111_await_phy(dev);
454 if (ret < 0) {
455 LOG_ERR("PHY %u didn't come out of reset, %d",
456 cfg->phy_addr, ret);
457 return -ENODEV;
458 }
459
460 ret = phy_adin2111_id(dev, &phy_id);
461 if (ret < 0) {
462 LOG_ERR("Failed to read PHY %u ID, %d",
463 cfg->phy_addr, ret);
464 return -ENODEV;
465 }
466
467 if (phy_id != ADIN2111_PHY_ID && phy_id != ADIN1110_PHY_ID && phy_id != ADIN1100_PHY_ID) {
468 LOG_ERR("PHY %u unexpected PHY ID %X", cfg->phy_addr, phy_id);
469 return -EINVAL;
470 }
471
472 LOG_INF("PHY %u ID %X", cfg->phy_addr, phy_id);
473
474 /* enter software powerdown */
475 ret = phy_adin2111_sft_pd(dev, true);
476 if (ret < 0) {
477 return ret;
478 }
479
480 /* disable interrupts */
481 ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1,
482 ADIN2111_PHY_CRSM_IRQ_MASK, 0U);
483 if (ret < 0) {
484 return ret;
485 }
486
487 /* enable link status change irq */
488 ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC2,
489 ADIN2111_PHY_SUBSYS_IRQ_MASK,
490 ADIN2111_PHY_SUBSYS_IRQ_STATUS_LINK_STAT_CHNG_LH);
491 if (ret < 0) {
492 return ret;
493 }
494
495 /* clear PHY IRQ status before enabling ADIN IRQs */
496 ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
497 ADIN2111_PHY_CRSM_IRQ_STATUS, &val);
498 if (ret < 0) {
499 return ret;
500 }
501
502 if (val & ADIN2111_PHY_CRSM_IRQ_STATUS_FATAL_ERR) {
503 LOG_ERR("PHY %u CRSM reports fatal system error", cfg->phy_addr);
504 return -ENODEV;
505 }
506
507 ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC2,
508 ADIN2111_PHY_SUBSYS_IRQ_STATUS, &val);
509 if (ret < 0) {
510 return ret;
511 }
512
513 if (!cfg->led0_en || !cfg->led1_en) {
514 ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
515 ADIN2111_PHY_LED_CNTRL, &val);
516 if (ret < 0) {
517 return ret;
518 }
519 if (!cfg->led0_en) {
520 val &= ~(ADIN2111_PHY_LED_CNTRL_LED0_EN);
521 }
522 if (!cfg->led1_en) {
523 val &= ~(ADIN2111_PHY_LED_CNTRL_LED1_EN);
524 }
525 ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1,
526 ADIN2111_PHY_LED_CNTRL, val);
527 if (ret < 0) {
528 return ret;
529 }
530 }
531
532 /* check 2.4V support */
533 ret = phy_adin2111_c45_read(dev, MDIO_MMD_PMAPMD, MDIO_PMA_B10L_STAT, &val);
534 if (ret < 0) {
535 return ret;
536 }
537
538 tx_24v_supported = !!(val & MDIO_PMA_B10L_STAT_2V4_ABLE);
539
540 LOG_INF("PHY %u 2.4V mode %s", cfg->phy_addr,
541 tx_24v_supported ? "supported" : "not supported");
542
543 if (!cfg->tx_24v & tx_24v_supported) {
544 LOG_ERR("PHY %u 2.4V mode supported, but not enabled",
545 cfg->phy_addr);
546 }
547
548 /* config 2.4V auto-negotiation */
549 ret = phy_adin2111_c45_read(dev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H, &val);
550 if (ret < 0) {
551 return ret;
552 }
553
554 if (tx_24v_supported) {
555 val |= MDIO_AN_T1_ADV_H_10L_TX_HI;
556 } else {
557 val &= ~MDIO_AN_T1_ADV_H_10L_TX_HI;
558 }
559
560 if (cfg->tx_24v) {
561 if (!tx_24v_supported) {
562 LOG_ERR("PHY %u 2.4V mode enabled, but not supported",
563 cfg->phy_addr);
564 return -EINVAL;
565 }
566
567 val |= MDIO_AN_T1_ADV_H_10L_TX_HI_REQ;
568 } else {
569 val &= ~MDIO_AN_T1_ADV_H_10L_TX_HI_REQ;
570 }
571
572 ret = phy_adin2111_c45_write(dev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H, val);
573 if (ret < 0) {
574 return ret;
575 }
576
577 /* enable auto-negotiation */
578 ret = phy_adin2111_c45_write(dev, MDIO_MMD_AN, MDIO_AN_T1_CTRL,
579 MDIO_AN_T1_CTRL_EN);
580 if (ret < 0) {
581 return ret;
582 }
583
584 if (cfg->mii) {
585 k_work_init_delayable(&data->monitor_work, monitor_work_handler);
586 monitor_work_handler(&data->monitor_work.work);
587 }
588
589 /**
590 * done, PHY is in software powerdown (SFT PD)
591 * exit software powerdown, PHY 1 has to exit before PHY 2
592 * correct PHY order is expected to be in DTS to guarantee that
593 */
594 return phy_adin2111_sft_pd(dev, false);
595 }
596
phy_adin2111_link_cb_set(const struct device * dev,phy_callback_t cb,void * user_data)597 static int phy_adin2111_link_cb_set(const struct device *dev, phy_callback_t cb,
598 void *user_data)
599 {
600 struct phy_adin2111_data *const data = dev->data;
601
602 data->cb = cb;
603 data->cb_data = user_data;
604
605 /* Invoke the callback to notify the caller of the current
606 * link status.
607 */
608 invoke_link_cb(dev);
609
610 return 0;
611 }
612
613 static DEVICE_API(ethphy, phy_adin2111_api) = {
614 .get_link = phy_adin2111_get_link_state,
615 .link_cb_set = phy_adin2111_link_cb_set,
616 .read = phy_adin2111_reg_read,
617 .write = phy_adin2111_reg_write,
618 };
619
620 #define ADIN2111_PHY_INITIALIZE(n, model) \
621 static const struct phy_adin2111_config phy_adin##model##_config_##n = { \
622 .mdio = DEVICE_DT_GET(DT_INST_BUS(n)), \
623 .phy_addr = DT_INST_REG_ADDR(n), \
624 .led0_en = DT_INST_PROP(n, led0_en), \
625 .led1_en = DT_INST_PROP(n, led1_en), \
626 .tx_24v = !(DT_INST_PROP(n, disable_tx_mode_24v)), \
627 IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(adi_adin1100_phy), \
628 (.mii = 1)) \
629 }; \
630 static struct phy_adin2111_data phy_adin##model##_data_##n = { \
631 .sem = Z_SEM_INITIALIZER(phy_adin##model##_data_##n.sem, 1, 1), \
632 }; \
633 DEVICE_DT_INST_DEFINE(n, &phy_adin2111_init, NULL, \
634 &phy_adin##model##_data_##n, \
635 &phy_adin##model##_config_##n, \
636 POST_KERNEL, CONFIG_PHY_INIT_PRIORITY, \
637 &phy_adin2111_api);
638
639 #define DT_DRV_COMPAT adi_adin2111_phy
640 DT_INST_FOREACH_STATUS_OKAY_VARGS(ADIN2111_PHY_INITIALIZE, 2111)
641 #undef DT_DRV_COMPAT
642 #define DT_DRV_COMPAT adi_adin1100_phy
643 DT_INST_FOREACH_STATUS_OKAY_VARGS(ADIN2111_PHY_INITIALIZE, 1100)
644 #undef DT_DRV_COMPAT
645