1 /*
2 * Copyright 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 qca_ar8031
12
13 #include <errno.h>
14 #include <zephyr/device.h>
15 #include <zephyr/init.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/drivers/mdio.h>
18 #include <zephyr/net/phy.h>
19 #include <zephyr/net/mdio.h>
20 #include <zephyr/net/mii.h>
21
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_REGISTER(phy_qc_ar8031, CONFIG_PHY_LOG_LEVEL);
24
25 #define AR8031_PHY_ID1 0x004DU
26 #define PHY_READID_TIMEOUT_COUNT 1000U
27
28 /* PHY Specific Status Register */
29 #define PHY_SPECIFIC_STATUS_REG 0x11
30 #define SPEC_STATUS_REG_LINK_MASK (1U << 10)
31 #define SPEC_STATUS_REG_DUPLEX_MASK (1U << 13)
32 #define PHY_DUPLEX_HALF (0U << 13)
33 #define PHY_DUPLEX_FULL (1U << 13)
34 #define SPEC_STATUS_REG_SPEED_MASK (0x3U << 14)
35 #define PHY_SPEED_10M (0U << 14)
36 #define PHY_SPEED_100M (1U << 14)
37 #define PHY_SPEED_1000M (2U << 14)
38
39 /* The PHY Debug port address register */
40 #define PHY_DEBUGPORT_ADDR_REG 0x1DU
41 /* The PHY Debug port data register */
42 #define PHY_DEBUGPORT_DATA_REG 0x1EU
43
44 /* PCS Register: smartEEE control 3 Register */
45 #define MDIO_PCS_SMARTEEE_CTRL3 0x805DU
46 #define MDIO_PCS_SMARTEEE_CTRL3_LPI_EN (1U << 8)
47
48 /* Debug port registers */
49 /* Analog Test Control */
50 #define PHY_DEBUGPORT_ANALOG_CTRL 0x0
51 #define PHY_DEBUGPORT_ANALOG_CTRL_RX_DELAY (1U << 15)
52 /* SerDes Test and System Mode Control */
53 #define PHY_DEBUGPORT_SD_SM_CTRL 0x5
54 #define PHY_DEBUGPORT_SD_SM_CTRL_TX_DELAY (1U << 8)
55
56 struct qc_ar8031_config {
57 uint8_t addr;
58 bool fixed_link;
59 bool enable_eee;
60 int fixed_speed;
61 const struct device *mdio_dev;
62 };
63
64 struct qc_ar8031_data {
65 const struct device *dev;
66 phy_callback_t cb;
67 void *cb_data;
68 struct k_work_delayable monitor_work;
69 struct phy_link_state state;
70 struct k_sem sem;
71 };
72
73 static int qc_ar8031_get_link_state(const struct device *dev, struct phy_link_state *state);
74
qc_ar8031_read(const struct device * dev,uint16_t reg_addr,uint32_t * data)75 static int qc_ar8031_read(const struct device *dev, uint16_t reg_addr, uint32_t *data)
76 {
77 const struct qc_ar8031_config *config = dev->config;
78 int ret;
79
80 /* Make sure excessive bits 16-31 are reset */
81 *data = 0U;
82
83 /* Read the PHY register */
84 ret = mdio_read(config->mdio_dev, config->addr, reg_addr, (uint16_t *)data);
85 if (ret) {
86 return ret;
87 }
88
89 return 0;
90 }
91
qc_ar8031_write(const struct device * dev,uint16_t reg_addr,uint32_t data)92 static int qc_ar8031_write(const struct device *dev, uint16_t reg_addr, uint32_t data)
93 {
94 const struct qc_ar8031_config *config = dev->config;
95 int ret;
96
97 ret = mdio_write(config->mdio_dev, config->addr, reg_addr, (uint16_t)data);
98 if (ret) {
99 return ret;
100 }
101
102 return 0;
103 }
104
qc_ar8031_mmd_set_device(const struct device * dev,uint32_t device,uint32_t addr,uint16_t mode)105 static int qc_ar8031_mmd_set_device(const struct device *dev, uint32_t device, uint32_t addr,
106 uint16_t mode)
107 {
108 uint16_t reg_value = (device & MII_MMD_ACR_DEVAD_MASK) | MII_MMD_ACR_ADDR;
109
110 if (qc_ar8031_write(dev, MII_MMD_ACR, reg_value) < 0) {
111 return -EIO;
112 }
113 if (qc_ar8031_write(dev, MII_MMD_AADR, addr) < 0) {
114 return -EIO;
115 }
116 /* Set Function mode of data access(b01~11) and device address. */
117 if (qc_ar8031_write(dev, MII_MMD_ACR, (device & MII_MMD_ACR_DEVAD_MASK) | mode) < 0) {
118 return -EIO;
119 }
120
121 return 0;
122 }
123
qc_ar8031_mmd_read(const struct device * dev,uint32_t device,uint32_t addr,uint32_t * data)124 static int qc_ar8031_mmd_read(const struct device *dev, uint32_t device, uint32_t addr,
125 uint32_t *data)
126 {
127 int ret;
128
129 *data = 0U;
130
131 ret = qc_ar8031_mmd_set_device(dev, device, addr, MII_MMD_ACR_DATA_NO_POS_INC);
132 if (ret) {
133 return -EIO;
134 }
135
136 ret = qc_ar8031_read(dev, MII_MMD_AADR, data);
137
138 return ret;
139 }
140
qc_ar8031_mmd_write(const struct device * dev,uint32_t device,uint32_t addr,uint32_t data)141 static int qc_ar8031_mmd_write(const struct device *dev, uint32_t device, uint32_t addr,
142 uint32_t data)
143 {
144 int ret;
145
146 ret = qc_ar8031_mmd_set_device(dev, device, addr, MII_MMD_ACR_DATA_NO_POS_INC);
147 if (ret) {
148 return -EIO;
149 }
150
151 ret = qc_ar8031_write(dev, MII_MMD_AADR, data);
152
153 return ret;
154 }
155
qc_ar8031_update_link_state(const struct device * dev)156 static int qc_ar8031_update_link_state(const struct device *dev)
157 {
158 const struct qc_ar8031_config *const cfg = dev->config;
159 struct qc_ar8031_data *const data = dev->data;
160 bool link_up;
161 uint32_t reg_value;
162 uint16_t speed, duplex;
163
164 if (qc_ar8031_read(dev, PHY_SPECIFIC_STATUS_REG, ®_value) < 0) {
165 return -EIO;
166 }
167
168 link_up = (uint16_t)reg_value & SPEC_STATUS_REG_LINK_MASK;
169
170 /* If there is no change in link state don't proceed. */
171 if (link_up == data->state.is_up) {
172 return -EAGAIN;
173 }
174
175 data->state.is_up = link_up;
176
177 /* If link is down, there is nothing more to be done */
178 if (data->state.is_up == false) {
179 return 0;
180 }
181
182 if (qc_ar8031_read(dev, PHY_SPECIFIC_STATUS_REG, ®_value) < 0) {
183 return -EIO;
184 }
185
186 speed = reg_value & SPEC_STATUS_REG_SPEED_MASK;
187 duplex = reg_value & SPEC_STATUS_REG_DUPLEX_MASK;
188
189 switch (speed | duplex) {
190 case PHY_SPEED_10M | PHY_DUPLEX_FULL:
191 data->state.speed = LINK_FULL_10BASE_T;
192 break;
193 case PHY_SPEED_10M | PHY_DUPLEX_HALF:
194 data->state.speed = LINK_HALF_10BASE_T;
195 break;
196 case PHY_SPEED_100M | PHY_DUPLEX_FULL:
197 data->state.speed = LINK_FULL_100BASE_T;
198 break;
199 case PHY_SPEED_100M | PHY_DUPLEX_HALF:
200 data->state.speed = LINK_HALF_100BASE_T;
201 break;
202 case PHY_SPEED_1000M | PHY_DUPLEX_FULL:
203 data->state.speed = LINK_FULL_1000BASE_T;
204 break;
205 case PHY_SPEED_1000M | PHY_DUPLEX_HALF:
206 data->state.speed = LINK_HALF_1000BASE_T;
207 break;
208 }
209
210 LOG_DBG("PHY (%d) Link speed %s Mb, %s duplex", cfg->addr,
211 PHY_LINK_IS_SPEED_1000M(data->state.speed)
212 ? "1000"
213 : (PHY_LINK_IS_SPEED_100M(data->state.speed) ? "100" : "10"),
214 PHY_LINK_IS_FULL_DUPLEX(data->state.speed) ? "full" : "half");
215
216 return 0;
217 }
218
invoke_link_cb(const struct device * dev)219 static void invoke_link_cb(const struct device *dev)
220 {
221 struct qc_ar8031_data *const data = dev->data;
222 struct phy_link_state state;
223
224 if (data->cb == NULL) {
225 return;
226 }
227
228 qc_ar8031_get_link_state(dev, &state);
229
230 data->cb(data->dev, &state, data->cb_data);
231 }
232
monitor_work_handler(struct k_work * work)233 static void monitor_work_handler(struct k_work *work)
234 {
235 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
236 struct qc_ar8031_data *const data =
237 CONTAINER_OF(dwork, struct qc_ar8031_data, monitor_work);
238 const struct device *dev = data->dev;
239 int rc;
240
241 k_sem_take(&data->sem, K_FOREVER);
242
243 rc = qc_ar8031_update_link_state(dev);
244
245 k_sem_give(&data->sem);
246
247 /* If link state has changed and a callback is set, invoke callback */
248 if (rc == 0) {
249 invoke_link_cb(dev);
250 }
251
252 /* Submit delayed work */
253 k_work_reschedule(&data->monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
254 }
255
qc_ar8031_cfg_link(const struct device * dev,enum phy_link_speed adv_speeds)256 static int qc_ar8031_cfg_link(const struct device *dev, enum phy_link_speed adv_speeds)
257 {
258 uint32_t anar_reg;
259 uint32_t bmcr_reg;
260 uint32_t c1kt_reg;
261
262 if (qc_ar8031_read(dev, MII_ANAR, &anar_reg) < 0) {
263 return -EIO;
264 }
265
266 if (qc_ar8031_read(dev, MII_BMCR, &bmcr_reg) < 0) {
267 return -EIO;
268 }
269
270 if (qc_ar8031_read(dev, MII_1KTCR, &c1kt_reg) < 0) {
271 return -EIO;
272 }
273
274 if (adv_speeds & LINK_FULL_10BASE_T) {
275 anar_reg |= MII_ADVERTISE_10_FULL;
276 } else {
277 anar_reg &= ~MII_ADVERTISE_10_FULL;
278 }
279
280 if (adv_speeds & LINK_HALF_10BASE_T) {
281 anar_reg |= MII_ADVERTISE_10_HALF;
282 } else {
283 anar_reg &= ~MII_ADVERTISE_10_HALF;
284 }
285
286 if (adv_speeds & LINK_FULL_100BASE_T) {
287 anar_reg |= MII_ADVERTISE_100_FULL;
288 } else {
289 anar_reg &= ~MII_ADVERTISE_100_FULL;
290 }
291
292 if (adv_speeds & LINK_HALF_100BASE_T) {
293 anar_reg |= MII_ADVERTISE_100_HALF;
294 } else {
295 anar_reg &= ~MII_ADVERTISE_100_HALF;
296 }
297
298 if (adv_speeds & LINK_FULL_1000BASE_T) {
299 c1kt_reg |= MII_ADVERTISE_1000_FULL;
300 } else {
301 c1kt_reg &= ~MII_ADVERTISE_1000_FULL;
302 }
303
304 if (adv_speeds & LINK_HALF_1000BASE_T) {
305 c1kt_reg |= MII_ADVERTISE_1000_HALF;
306 } else {
307 c1kt_reg &= ~MII_ADVERTISE_1000_HALF;
308 }
309
310 if (qc_ar8031_write(dev, MII_1KTCR, c1kt_reg) < 0) {
311 return -EIO;
312 }
313
314 bmcr_reg |= MII_BMCR_AUTONEG_ENABLE | MII_BMCR_AUTONEG_RESTART;
315
316 if (qc_ar8031_write(dev, MII_ANAR, anar_reg) < 0) {
317 return -EIO;
318 }
319
320 if (qc_ar8031_write(dev, MII_BMCR, bmcr_reg) < 0) {
321 return -EIO;
322 }
323
324 return 0;
325 }
326
qc_ar8031_get_link_state(const struct device * dev,struct phy_link_state * state)327 static int qc_ar8031_get_link_state(const struct device *dev, struct phy_link_state *state)
328 {
329 struct qc_ar8031_data *const data = dev->data;
330
331 k_sem_take(&data->sem, K_FOREVER);
332
333 memcpy(state, &data->state, sizeof(struct phy_link_state));
334
335 k_sem_give(&data->sem);
336
337 return 0;
338 }
339
qc_ar8031_link_cb_set(const struct device * dev,phy_callback_t cb,void * user_data)340 static int qc_ar8031_link_cb_set(const struct device *dev, phy_callback_t cb, void *user_data)
341 {
342 struct qc_ar8031_data *const data = dev->data;
343
344 data->cb = cb;
345 data->cb_data = user_data;
346
347 /**
348 * Immediately invoke the callback to notify the caller of the
349 * current link status.
350 */
351 invoke_link_cb(dev);
352
353 return 0;
354 }
355
qc_ar8031_init(const struct device * dev)356 static int qc_ar8031_init(const struct device *dev)
357 {
358 const struct qc_ar8031_config *const cfg = dev->config;
359 struct qc_ar8031_data *const data = dev->data;
360 uint32_t counter = PHY_READID_TIMEOUT_COUNT;
361 uint32_t reg_value = 0;
362 int ret;
363
364 k_sem_init(&data->sem, 1, 1);
365
366 mdio_bus_enable(cfg->mdio_dev);
367
368 data->state.is_up = false;
369
370 data->dev = dev;
371 data->cb = NULL;
372
373 do {
374 if (qc_ar8031_read(dev, MII_PHYID1R, ®_value) < 0) {
375 return -EIO;
376 }
377 } while (reg_value != AR8031_PHY_ID1 && counter-- > 0);
378 if (counter == 0U) {
379 LOG_ERR("PHY (%d) can't read ID", cfg->addr);
380 return -EIO;
381 }
382
383 /* Reset PHY */
384 ret = qc_ar8031_write(dev, MII_BMCR, MII_BMCR_RESET);
385 if (ret) {
386 return -EIO;
387 }
388
389 /* Close smartEEE */
390 ret = qc_ar8031_mmd_set_device(dev, MDIO_MMD_PCS, MDIO_PCS_SMARTEEE_CTRL3,
391 MII_MMD_ACR_DATA_NO_POS_INC);
392 if (ret) {
393 return -EIO;
394 }
395 ret = qc_ar8031_read(dev, MII_MMD_AADR, ®_value);
396 if (ret) {
397 return -EIO;
398 }
399 ret = qc_ar8031_write(dev, MII_MMD_AADR, reg_value & ~(MDIO_PCS_SMARTEEE_CTRL3_LPI_EN));
400 if (ret) {
401 return -EIO;
402 }
403
404 /* Enable Tx clock delay */
405 ret = qc_ar8031_write(dev, PHY_DEBUGPORT_ADDR_REG, PHY_DEBUGPORT_SD_SM_CTRL);
406 if (ret) {
407 return -EIO;
408 }
409 ret = qc_ar8031_read(dev, PHY_DEBUGPORT_DATA_REG, ®_value);
410 if (ret) {
411 return -EIO;
412 }
413 ret = qc_ar8031_write(dev, PHY_DEBUGPORT_DATA_REG,
414 reg_value | PHY_DEBUGPORT_SD_SM_CTRL_TX_DELAY);
415 if (ret) {
416 return -EIO;
417 }
418
419 /* Enable Rx clock delay */
420 ret = qc_ar8031_write(dev, PHY_DEBUGPORT_ADDR_REG, PHY_DEBUGPORT_ANALOG_CTRL);
421 if (ret) {
422 return -EIO;
423 }
424 ret = qc_ar8031_read(dev, PHY_DEBUGPORT_DATA_REG, ®_value);
425 if (ret) {
426 return -EIO;
427 }
428 ret = qc_ar8031_write(dev, PHY_DEBUGPORT_DATA_REG,
429 reg_value | PHY_DEBUGPORT_ANALOG_CTRL_RX_DELAY);
430 if (ret) {
431 return -EIO;
432 }
433
434 /* Energy Efficient Ethernet configuration */
435 if (cfg->enable_eee) {
436 ret = qc_ar8031_mmd_read(dev, MDIO_MMD_PCS, MDIO_PCS_EEE_CAP, ®_value);
437 if (ret) {
438 return -EIO;
439 }
440 ret = qc_ar8031_mmd_write(dev, MDIO_MMD_AN, MDIO_AN_EEE_ADV,
441 reg_value & (MDIO_AN_EEE_ADV_1000T | MDIO_AN_EEE_ADV_100TX));
442 if (ret) {
443 return -EIO;
444 }
445 } else {
446 ret = qc_ar8031_mmd_write(dev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
447 if (ret) {
448 return -EIO;
449 }
450 }
451
452 /* Fixed Link */
453 if (cfg->fixed_link) {
454 /* Disable isolate */
455 ret = qc_ar8031_read(dev, MII_BMCR, ®_value);
456 if (ret) {
457 return -EIO;
458 }
459 reg_value &= ~MII_BMCR_ISOLATE;
460 ret = qc_ar8031_write(dev, MII_BMCR, reg_value);
461 if (ret) {
462 return -EIO;
463 }
464
465 const static int speed_to_phy_link_speed[] = {
466 LINK_HALF_10BASE_T, LINK_FULL_10BASE_T, LINK_HALF_100BASE_T,
467 LINK_FULL_100BASE_T, LINK_HALF_1000BASE_T, LINK_FULL_1000BASE_T,
468 };
469
470 data->state.speed = speed_to_phy_link_speed[cfg->fixed_speed];
471 data->state.is_up = true;
472 } else { /* Auto negotiation */
473 /* Advertise all speeds */
474 qc_ar8031_cfg_link(dev, LINK_HALF_10BASE_T | LINK_FULL_10BASE_T |
475 LINK_HALF_100BASE_T | LINK_FULL_100BASE_T |
476 LINK_HALF_1000BASE_T | LINK_FULL_1000BASE_T);
477
478 k_work_init_delayable(&data->monitor_work, monitor_work_handler);
479
480 monitor_work_handler(&data->monitor_work.work);
481 }
482
483 return 0;
484 }
485
486 static DEVICE_API(ethphy, ar8031_driver_api) = {
487 .get_link = qc_ar8031_get_link_state,
488 .cfg_link = qc_ar8031_cfg_link,
489 .link_cb_set = qc_ar8031_link_cb_set,
490 .read = qc_ar8031_read,
491 .write = qc_ar8031_write,
492 };
493
494 #define AR8031_CONFIG(n) \
495 static const struct qc_ar8031_config qc_ar8031_config_##n = { \
496 .addr = DT_INST_REG_ADDR(n), \
497 .fixed_link = DT_INST_NODE_HAS_PROP(n, fixed_link), \
498 .fixed_speed = DT_INST_ENUM_IDX_OR(n, fixed_link, 0), \
499 .mdio_dev = DEVICE_DT_GET(DT_INST_BUS(n)), \
500 .enable_eee = DT_INST_NODE_HAS_PROP(n, eee_en), \
501 };
502
503 #define AR8031_DEVICE(n) \
504 AR8031_CONFIG(n); \
505 static struct qc_ar8031_data qc_ar8031_data_##n; \
506 DEVICE_DT_INST_DEFINE(n, &qc_ar8031_init, NULL, &qc_ar8031_data_##n, \
507 &qc_ar8031_config_##n, POST_KERNEL, CONFIG_PHY_INIT_PRIORITY, \
508 &ar8031_driver_api);
509
510 DT_INST_FOREACH_STATUS_OKAY(AR8031_DEVICE)
511