1 /*
2 * Copyright 2023-2024 NXP
3 *
4 * Inspiration from phy_mii.c, which is:
5 * Copyright (c) 2021 IP-Logix Inc.
6 * Copyright 2022 NXP
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #define DT_DRV_COMPAT microchip_ksz8081
12
13 #include <zephyr/kernel.h>
14 #include <zephyr/net/phy.h>
15 #include <zephyr/net/mii.h>
16 #include <zephyr/drivers/mdio.h>
17 #include <string.h>
18 #include <zephyr/sys/util_macro.h>
19 #include <zephyr/drivers/gpio.h>
20
21 #define LOG_MODULE_NAME phy_mc_ksz8081
22 #define LOG_LEVEL CONFIG_PHY_LOG_LEVEL
23 #include <zephyr/logging/log.h>
24 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
25
26 #define PHY_MC_KSZ8081_OMSO_REG 0x16
27 #define PHY_MC_KSZ8081_OMSO_FACTORY_MODE_MASK BIT(15)
28 #define PHY_MC_KSZ8081_OMSO_NAND_TREE_MASK BIT(5)
29 #define PHY_MC_KSZ8081_OMSO_RMII_OVERRIDE_MASK BIT(1)
30 #define PHY_MC_KSZ8081_OMSO_MII_OVERRIDE_MASK BIT(0)
31
32 #define PHY_MC_KSZ8081_CTRL2_REG 0x1F
33 #define PHY_MC_KSZ8081_CTRL2_REF_CLK_SEL BIT(7)
34
35 enum ksz8081_interface {
36 KSZ8081_MII,
37 KSZ8081_RMII,
38 KSZ8081_RMII_25MHZ,
39 };
40
41 struct mc_ksz8081_config {
42 uint8_t addr;
43 const struct device *mdio_dev;
44 enum ksz8081_interface phy_iface;
45 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios)
46 const struct gpio_dt_spec reset_gpio;
47 #endif
48 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
49 const struct gpio_dt_spec interrupt_gpio;
50 #endif
51 };
52
53 struct mc_ksz8081_data {
54 const struct device *dev;
55 struct phy_link_state state;
56 phy_callback_t cb;
57 void *cb_data;
58 struct k_mutex mutex;
59 struct k_work_delayable phy_monitor_work;
60 };
61
phy_mc_ksz8081_read(const struct device * dev,uint16_t reg_addr,uint32_t * data)62 static int phy_mc_ksz8081_read(const struct device *dev,
63 uint16_t reg_addr, uint32_t *data)
64 {
65 const struct mc_ksz8081_config *config = dev->config;
66 int ret;
67
68 /* Make sure excessive bits 16-31 are reset */
69 *data = 0U;
70
71 ret = mdio_read(config->mdio_dev, config->addr, reg_addr, (uint16_t *)data);
72 if (ret) {
73 return ret;
74 }
75
76 return 0;
77 }
78
phy_mc_ksz8081_write(const struct device * dev,uint16_t reg_addr,uint32_t data)79 static int phy_mc_ksz8081_write(const struct device *dev,
80 uint16_t reg_addr, uint32_t data)
81 {
82 const struct mc_ksz8081_config *config = dev->config;
83 int ret;
84
85 ret = mdio_write(config->mdio_dev, config->addr, reg_addr, (uint16_t)data);
86 if (ret) {
87 return ret;
88 }
89
90 return 0;
91 }
92
phy_mc_ksz8081_autonegotiate(const struct device * dev)93 static int phy_mc_ksz8081_autonegotiate(const struct device *dev)
94 {
95 const struct mc_ksz8081_config *config = dev->config;
96 int ret;
97 uint32_t bmcr = 0;
98 uint32_t bmsr = 0;
99 uint16_t timeout = CONFIG_PHY_AUTONEG_TIMEOUT_MS / 100;
100
101 /* Read control register to write back with autonegotiation bit */
102 ret = phy_mc_ksz8081_read(dev, MII_BMCR, &bmcr);
103 if (ret) {
104 LOG_ERR("Error reading phy (%d) basic control register", config->addr);
105 return ret;
106 }
107
108 /* (re)start autonegotiation */
109 LOG_DBG("PHY (%d) is entering autonegotiation sequence", config->addr);
110 bmcr |= MII_BMCR_AUTONEG_ENABLE | MII_BMCR_AUTONEG_RESTART;
111 bmcr &= ~MII_BMCR_ISOLATE;
112
113 ret = phy_mc_ksz8081_write(dev, MII_BMCR, bmcr);
114 if (ret) {
115 LOG_ERR("Error writing phy (%d) basic control register", config->addr);
116 return ret;
117 }
118
119 /* TODO change this to GPIO interrupt driven */
120 do {
121 if (timeout-- == 0) {
122 LOG_DBG("PHY (%d) autonegotiation timed out", config->addr);
123 /* The value -ETIMEDOUT can be returned by PHY read/write functions, so
124 * return -ENETDOWN instead to distinguish link timeout from PHY timeout.
125 */
126 return -ENETDOWN;
127 }
128 k_msleep(100);
129
130 ret = phy_mc_ksz8081_read(dev, MII_BMSR, &bmsr);
131 if (ret) {
132 LOG_ERR("Error reading phy (%d) basic status register", config->addr);
133 return ret;
134 }
135 } while (!(bmsr & MII_BMSR_AUTONEG_COMPLETE));
136
137 LOG_DBG("PHY (%d) autonegotiation completed", config->addr);
138
139 return 0;
140 }
141
phy_mc_ksz8081_get_link(const struct device * dev,struct phy_link_state * state)142 static int phy_mc_ksz8081_get_link(const struct device *dev,
143 struct phy_link_state *state)
144 {
145 const struct mc_ksz8081_config *config = dev->config;
146 struct mc_ksz8081_data *data = dev->data;
147 int ret;
148 uint32_t bmsr = 0;
149 uint32_t anar = 0;
150 uint32_t anlpar = 0;
151 struct phy_link_state old_state = data->state;
152
153 /* Lock mutex */
154 ret = k_mutex_lock(&data->mutex, K_FOREVER);
155 if (ret) {
156 LOG_ERR("PHY mutex lock error");
157 return ret;
158 }
159
160 /* Read link state */
161 ret = phy_mc_ksz8081_read(dev, MII_BMSR, &bmsr);
162 if (ret) {
163 LOG_ERR("Error reading phy (%d) basic status register", config->addr);
164 k_mutex_unlock(&data->mutex);
165 return ret;
166 }
167 state->is_up = bmsr & MII_BMSR_LINK_STATUS;
168
169 if (!state->is_up) {
170 k_mutex_unlock(&data->mutex);
171 goto result;
172 }
173
174 /* Read currently configured advertising options */
175 ret = phy_mc_ksz8081_read(dev, MII_ANAR, &anar);
176 if (ret) {
177 LOG_ERR("Error reading phy (%d) advertising register", config->addr);
178 k_mutex_unlock(&data->mutex);
179 return ret;
180 }
181
182 /* Read link partner capability */
183 ret = phy_mc_ksz8081_read(dev, MII_ANLPAR, &anlpar);
184 if (ret) {
185 LOG_ERR("Error reading phy (%d) link partner register", config->addr);
186 k_mutex_unlock(&data->mutex);
187 return ret;
188 }
189
190 /* Unlock mutex */
191 k_mutex_unlock(&data->mutex);
192
193 uint32_t mutual_capabilities = anar & anlpar;
194
195 if (mutual_capabilities & MII_ADVERTISE_100_FULL) {
196 state->speed = LINK_FULL_100BASE_T;
197 } else if (mutual_capabilities & MII_ADVERTISE_100_HALF) {
198 state->speed = LINK_HALF_100BASE_T;
199 } else if (mutual_capabilities & MII_ADVERTISE_10_FULL) {
200 state->speed = LINK_FULL_10BASE_T;
201 } else if (mutual_capabilities & MII_ADVERTISE_10_HALF) {
202 state->speed = LINK_HALF_10BASE_T;
203 } else {
204 ret = -EIO;
205 }
206
207 result:
208 if (memcmp(&old_state, state, sizeof(struct phy_link_state)) != 0) {
209 LOG_DBG("PHY %d is %s", config->addr, state->is_up ? "up" : "down");
210 if (state->is_up) {
211 LOG_DBG("PHY (%d) Link speed %s Mb, %s duplex\n", config->addr,
212 (PHY_LINK_IS_SPEED_100M(state->speed) ? "100" : "10"),
213 PHY_LINK_IS_FULL_DUPLEX(state->speed) ? "full" : "half");
214 }
215 }
216
217 return ret;
218 }
219
220 /*
221 * Configuration set statically (DT) that should never change
222 * This function is needed in case the PHY is reset then the next call
223 * to configure the phy will ensure this configuration will be redone
224 */
phy_mc_ksz8081_static_cfg(const struct device * dev)225 static int phy_mc_ksz8081_static_cfg(const struct device *dev)
226 {
227 const struct mc_ksz8081_config *config = dev->config;
228 uint32_t omso = 0;
229 uint32_t ctrl2 = 0;
230 int ret = 0;
231
232 /* Force normal operation in the case of factory mode */
233 ret = phy_mc_ksz8081_read(dev, PHY_MC_KSZ8081_OMSO_REG, (uint32_t *)&omso);
234 if (ret) {
235 return ret;
236 }
237
238 omso &= ~PHY_MC_KSZ8081_OMSO_FACTORY_MODE_MASK &
239 ~PHY_MC_KSZ8081_OMSO_NAND_TREE_MASK;
240 if (config->phy_iface == KSZ8081_RMII) {
241 omso &= ~PHY_MC_KSZ8081_OMSO_MII_OVERRIDE_MASK;
242 omso |= PHY_MC_KSZ8081_OMSO_RMII_OVERRIDE_MASK;
243 }
244
245 ret = phy_mc_ksz8081_write(dev, PHY_MC_KSZ8081_OMSO_REG, (uint32_t)omso);
246 if (ret) {
247 return ret;
248 }
249
250 /* Select correct reference clock mode depending on interface setup */
251 ret = phy_mc_ksz8081_read(dev, PHY_MC_KSZ8081_CTRL2_REG, (uint32_t *)&ctrl2);
252 if (ret) {
253 return ret;
254 }
255
256 if (config->phy_iface == KSZ8081_RMII) {
257 ctrl2 |= PHY_MC_KSZ8081_CTRL2_REF_CLK_SEL;
258 } else {
259 ctrl2 &= ~PHY_MC_KSZ8081_CTRL2_REF_CLK_SEL;
260 }
261
262 ret = phy_mc_ksz8081_write(dev, PHY_MC_KSZ8081_CTRL2_REG, (uint32_t)ctrl2);
263 if (ret) {
264 return ret;
265 }
266
267 return 0;
268 }
269
phy_mc_ksz8081_reset(const struct device * dev)270 static int phy_mc_ksz8081_reset(const struct device *dev)
271 {
272 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios)
273 const struct mc_ksz8081_config *config = dev->config;
274 #endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */
275 struct mc_ksz8081_data *data = dev->data;
276 int ret;
277
278 /* Lock mutex */
279 ret = k_mutex_lock(&data->mutex, K_FOREVER);
280 if (ret) {
281 LOG_ERR("PHY mutex lock error");
282 return ret;
283 }
284
285 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios)
286 if (!config->reset_gpio.port) {
287 goto skip_reset_gpio;
288 }
289
290 /* Start reset */
291 ret = gpio_pin_set_dt(&config->reset_gpio, 0);
292 if (ret) {
293 goto done;
294 }
295
296 /* Wait for at least 500 us as specified by datasheet */
297 k_busy_wait(1000);
298
299 /* Reset over */
300 ret = gpio_pin_set_dt(&config->reset_gpio, 1);
301
302 /* After deasserting reset, must wait at least 100 us to use programming interface */
303 k_busy_wait(200);
304
305 goto done;
306 skip_reset_gpio:
307 #endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */
308 ret = phy_mc_ksz8081_write(dev, MII_BMCR, MII_BMCR_RESET);
309 if (ret) {
310 goto done;
311 }
312
313 /* According to IEEE 802.3, Section 2, Subsection 22.2.4.1.1,
314 * a PHY reset may take up to 0.5 s.
315 */
316 k_busy_wait(500 * USEC_PER_MSEC);
317
318 done:
319 /* Unlock mutex */
320 k_mutex_unlock(&data->mutex);
321 return ret;
322 }
323
phy_mc_ksz8081_cfg_link(const struct device * dev,enum phy_link_speed speeds)324 static int phy_mc_ksz8081_cfg_link(const struct device *dev,
325 enum phy_link_speed speeds)
326 {
327 const struct mc_ksz8081_config *config = dev->config;
328 struct mc_ksz8081_data *data = dev->data;
329 struct phy_link_state state = {};
330 int ret;
331 uint32_t anar;
332
333 /* Lock mutex */
334 ret = k_mutex_lock(&data->mutex, K_FOREVER);
335 if (ret) {
336 LOG_ERR("PHY mutex lock error");
337 goto done;
338 }
339
340 /* We are going to reconfigure the phy, don't need to monitor until done */
341 k_work_cancel_delayable(&data->phy_monitor_work);
342
343 /* DT configurations */
344 ret = phy_mc_ksz8081_static_cfg(dev);
345 if (ret) {
346 goto done;
347 }
348
349 /* Read ANAR register to write back */
350 ret = phy_mc_ksz8081_read(dev, MII_ANAR, &anar);
351 if (ret) {
352 LOG_ERR("Error reading phy (%d) advertising register", config->addr);
353 goto done;
354 }
355
356 /* Setup advertising register */
357 if (speeds & LINK_FULL_100BASE_T) {
358 anar |= MII_ADVERTISE_100_FULL;
359 } else {
360 anar &= ~MII_ADVERTISE_100_FULL;
361 }
362 if (speeds & LINK_HALF_100BASE_T) {
363 anar |= MII_ADVERTISE_100_HALF;
364 } else {
365 anar &= ~MII_ADVERTISE_100_HALF;
366 }
367 if (speeds & LINK_FULL_10BASE_T) {
368 anar |= MII_ADVERTISE_10_FULL;
369 } else {
370 anar &= ~MII_ADVERTISE_10_FULL;
371 }
372 if (speeds & LINK_HALF_10BASE_T) {
373 anar |= MII_ADVERTISE_10_HALF;
374 } else {
375 anar &= ~MII_ADVERTISE_10_HALF;
376 }
377
378 /* Write capabilities to advertising register */
379 ret = phy_mc_ksz8081_write(dev, MII_ANAR, anar);
380 if (ret) {
381 LOG_ERR("Error writing phy (%d) advertising register", config->addr);
382 goto done;
383 }
384
385 /* (re)do autonegotiation */
386 ret = phy_mc_ksz8081_autonegotiate(dev);
387 if (ret && (ret != -ENETDOWN)) {
388 LOG_ERR("Error in autonegotiation");
389 goto done;
390 }
391
392 /* Get link status */
393 ret = phy_mc_ksz8081_get_link(dev, &state);
394
395 if (ret == 0 && memcmp(&state, &data->state, sizeof(struct phy_link_state)) != 0) {
396 memcpy(&data->state, &state, sizeof(struct phy_link_state));
397 if (data->cb) {
398 data->cb(dev, &data->state, data->cb_data);
399 }
400 }
401
402 /* Log the results of the configuration */
403 LOG_INF("PHY %d is %s", config->addr, data->state.is_up ? "up" : "down");
404 if (data->state.is_up) {
405 LOG_INF("PHY (%d) Link speed %s Mb, %s duplex\n", config->addr,
406 (PHY_LINK_IS_SPEED_100M(data->state.speed) ? "100" : "10"),
407 PHY_LINK_IS_FULL_DUPLEX(data->state.speed) ? "full" : "half");
408 }
409
410 done:
411 /* Unlock mutex */
412 k_mutex_unlock(&data->mutex);
413
414 /* Start monitoring */
415 k_work_reschedule(&data->phy_monitor_work,
416 K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
417
418 return ret;
419 }
420
phy_mc_ksz8081_link_cb_set(const struct device * dev,phy_callback_t cb,void * user_data)421 static int phy_mc_ksz8081_link_cb_set(const struct device *dev,
422 phy_callback_t cb, void *user_data)
423 {
424 struct mc_ksz8081_data *data = dev->data;
425
426 data->cb = cb;
427 data->cb_data = user_data;
428
429 phy_mc_ksz8081_get_link(dev, &data->state);
430
431 data->cb(dev, &data->state, data->cb_data);
432
433 return 0;
434 }
435
phy_mc_ksz8081_monitor_work_handler(struct k_work * work)436 static void phy_mc_ksz8081_monitor_work_handler(struct k_work *work)
437 {
438 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
439 struct mc_ksz8081_data *data =
440 CONTAINER_OF(dwork, struct mc_ksz8081_data, phy_monitor_work);
441 const struct device *dev = data->dev;
442 struct phy_link_state state = {};
443 int rc;
444
445 rc = phy_mc_ksz8081_get_link(dev, &state);
446
447 if (rc == 0 && memcmp(&state, &data->state, sizeof(struct phy_link_state)) != 0) {
448 memcpy(&data->state, &state, sizeof(struct phy_link_state));
449 if (data->cb) {
450 data->cb(dev, &data->state, data->cb_data);
451 }
452 }
453
454 /* TODO change this to GPIO interrupt driven */
455 k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
456 }
457
phy_mc_ksz8081_init(const struct device * dev)458 static int phy_mc_ksz8081_init(const struct device *dev)
459 {
460 const struct mc_ksz8081_config *config = dev->config;
461 struct mc_ksz8081_data *data = dev->data;
462 int ret;
463
464 data->dev = dev;
465
466 ret = k_mutex_init(&data->mutex);
467 if (ret) {
468 return ret;
469 }
470
471 mdio_bus_enable(config->mdio_dev);
472
473 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
474 if (!config->interrupt_gpio.port) {
475 goto skip_int_gpio;
476 }
477
478 /* Prevent NAND TREE mode */
479 ret = gpio_pin_configure_dt(&config->interrupt_gpio, GPIO_OUTPUT_ACTIVE);
480 if (ret) {
481 return ret;
482 }
483
484 skip_int_gpio:
485 #endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */
486
487 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios)
488 if (config->reset_gpio.port) {
489 ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_ACTIVE);
490 if (ret) {
491 return ret;
492 }
493 }
494 #endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */
495
496 /* Reset PHY */
497 ret = phy_mc_ksz8081_reset(dev);
498 if (ret) {
499 return ret;
500 }
501
502 k_work_init_delayable(&data->phy_monitor_work,
503 phy_mc_ksz8081_monitor_work_handler);
504
505 return 0;
506 }
507
508 static DEVICE_API(ethphy, mc_ksz8081_phy_api) = {
509 .get_link = phy_mc_ksz8081_get_link,
510 .cfg_link = phy_mc_ksz8081_cfg_link,
511 .link_cb_set = phy_mc_ksz8081_link_cb_set,
512 .read = phy_mc_ksz8081_read,
513 .write = phy_mc_ksz8081_write,
514 };
515
516 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios)
517 #define RESET_GPIO(n) \
518 .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}),
519 #else
520 #define RESET_GPIO(n)
521 #endif /* reset gpio */
522
523 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
524 #define INTERRUPT_GPIO(n) \
525 .interrupt_gpio = GPIO_DT_SPEC_INST_GET_OR(n, int_gpios, {0}),
526 #else
527 #define INTERRUPT_GPIO(n)
528 #endif /* interrupt gpio */
529
530 #define MICROCHIP_KSZ8081_INIT(n) \
531 static const struct mc_ksz8081_config mc_ksz8081_##n##_config = { \
532 .addr = DT_INST_REG_ADDR(n), \
533 .mdio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \
534 .phy_iface = DT_INST_ENUM_IDX(n, microchip_interface_type), \
535 RESET_GPIO(n) \
536 INTERRUPT_GPIO(n) \
537 }; \
538 \
539 static struct mc_ksz8081_data mc_ksz8081_##n##_data; \
540 \
541 DEVICE_DT_INST_DEFINE(n, &phy_mc_ksz8081_init, NULL, \
542 &mc_ksz8081_##n##_data, &mc_ksz8081_##n##_config, \
543 POST_KERNEL, CONFIG_PHY_INIT_PRIORITY, \
544 &mc_ksz8081_phy_api);
545
546 DT_INST_FOREACH_STATUS_OKAY(MICROCHIP_KSZ8081_INIT)
547