@@ -16,6 +16,9 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL);
16
16
#include <zephyr/sys/util_macro.h>
17
17
#include <zephyr/drivers/gpio.h>
18
18
19
+ #include "phy_mii.h"
20
+ #include "phy_common.h"
21
+
19
22
/* phy page selectors */
20
23
#define PHY_PAGE_0 0x00 /* main registers space active */
21
24
#define PHY_PAGE_1 0x01 /* reg 16 - 30 will be redirected to ext. register space 1 */
@@ -26,25 +29,14 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL);
26
29
#define PHY_REG (page , reg ) ((page << 8) | (reg << 0))
27
30
28
31
/* Generic Register */
29
- #define PHY_REG_PAGE0_BMCR PHY_REG(PHY_PAGE_0, 0x00)
30
- #define PHY_REG_PAGE0_BMSR PHY_REG(PHY_PAGE_0, 0x01)
31
- #define PHY_REG_PAGE0_ID1 PHY_REG(PHY_PAGE_0, 0x02)
32
- #define PHY_REG_PAGE0_ID2 PHY_REG(PHY_PAGE_0, 0x03)
33
- #define PHY_REG_PAGE0_ADV PHY_REG(PHY_PAGE_0, 0x04)
34
- #define PHY_REG_LPA 0x05
35
- #define PHY_REG_EXP 0x06
36
- #define PHY_REG_PAGE0_CTRL1000 PHY_REG(PHY_PAGE_0, 0x09)
37
- #define PHY_REG_PAGE0_STAT1000 PHY_REG(0, 0x0A)
38
- #define PHY_REG_MMD_CTRL 0x0D
39
- #define PHY_REG_MMD_DATA 0x0E
40
- #define PHY_REG_STAT1000_EXT1 0x0F
41
32
#define PHY_REG_PAGE0_STAT100 PHY_REG(PHY_PAGE_0, 0x10)
42
33
#define PHY_REG_PAGE0_STAT1000_EXT2 PHY_REG(PHY_PAGE_0, 0x11)
43
34
#define PHY_REG_AUX_CTRL 0x12
44
35
#define PHY_REG_PAGE0_ERROR_COUNTER_1 PHY_REG(0, 0x13)
45
36
#define PHY_REG_PAGE0_ERROR_COUNTER_2 PHY_REG(0, 0x14)
46
37
#define PHY_REG_PAGE0_EXT_CTRL_STAT PHY_REG(PHY_PAGE_0, 0x16)
47
38
#define PHY_REG_PAGE0_EXT_CONTROL_1 PHY_REG(PHY_PAGE_0, 0x17)
39
+ #define PHY_REG_PAGE0_EXT_DEV_AUX PHY_REG(PHY_PAGE_0, 0x1C)
48
40
#define PHY_REG_LED_MODE 0x1d
49
41
50
42
#define PHY_REG_PAGE_SELECTOR 0x1F
@@ -54,19 +46,7 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL);
54
46
#define PHY_REG_PAGE2_RGMII_CONTROL PHY_REG(PHY_PAGE_2, 0x14)
55
47
#define PHY_REG_PAGE2_MAC_IF_CONTROL PHY_REG(PHY_PAGE_2, 0x1b)
56
48
57
- /* selected bits in registers */
58
- #define BMCR_RESET (1 << 15)
59
- #define BMCR_LOOPBACK (1 << 14)
60
- #define BMCR_ANENABLE (1 << 12)
61
- #define BMCR_ANRESTART (1 << 9)
62
- #define BMCR_FULLDPLX (1 << 8)
63
- #define BMCR_SPEED10 ((0 << 13) | (0 << 6))
64
- #define BMCR_SPEED100 ((1 << 13) | (0 << 6))
65
- #define BMCR_SPEED1000 ((0 << 13) | (1 << 6))
66
-
67
- #define BMCR_SPEEDMASK ((1 << 13) | (1 << 6))
68
-
69
- #define BMSR_LSTATUS (1 << 2)
49
+ #define PHY_REG_PAGE0_EXT_DEV_AUX_DUPLEX BIT(5)
70
50
71
51
enum vsc8541_interface {
72
52
VSC8541_MII ,
@@ -85,6 +65,7 @@ struct mc_vsc8541_config {
85
65
uint8_t addr ;
86
66
const struct device * mdio_dev ;
87
67
enum vsc8541_interface microchip_interface_type ;
68
+ enum phy_link_speed default_speeds ;
88
69
uint8_t rgmii_rx_clk_delay ;
89
70
uint8_t rgmii_tx_clk_delay ;
90
71
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
@@ -123,11 +104,11 @@ static int phy_mc_vsc8541_verify_phy_id(const struct device *dev)
123
104
uint16_t phy_id_1 ;
124
105
uint16_t phy_id_2 ;
125
106
126
- if (0 != phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_ID1 , (uint32_t * )& phy_id_1 )) {
107
+ if (0 != phy_mc_vsc8541_read (dev , MII_PHYID1R , (uint32_t * )& phy_id_1 )) {
127
108
return - EINVAL ;
128
109
}
129
110
130
- if (0 != phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_ID2 , (uint32_t * )& phy_id_2 )) {
111
+ if (0 != phy_mc_vsc8541_read (dev , MII_PHYID2R , (uint32_t * )& phy_id_2 )) {
131
112
return - EINVAL ;
132
113
}
133
114
@@ -210,7 +191,7 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
210
191
}
211
192
212
193
/* software reset */
213
- ret = phy_mc_vsc8541_write (dev , PHY_REG_PAGE0_BMCR , MII_BMCR_RESET );
194
+ ret = phy_mc_vsc8541_write (dev , MII_BMCR , MII_BMCR_RESET );
214
195
if (ret ) {
215
196
return ret ;
216
197
}
@@ -219,47 +200,17 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
219
200
uint32_t reg = 0 ;
220
201
221
202
do {
222
- phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_BMCR , & reg );
223
- } while (reg & BMCR_RESET );
224
-
225
- /* forced MDI-X */
226
- ret = phy_mc_vsc8541_write (dev , PHY_REG_PAGE1_EXT_MODE_CTRL , (3 << 2 ));
227
- if (ret ) {
228
- return ret ;
229
- }
203
+ phy_mc_vsc8541_read (dev , MII_BMCR , & reg );
204
+ } while (reg & MII_BMCR_RESET );
230
205
231
206
/* configure the RGMII clk delay */
232
207
reg = 0x0 ;
233
208
/* RX_CLK delay */
234
209
reg |= (cfg -> rgmii_rx_clk_delay << 4 );
235
210
/* TX_CLK delay */
236
211
reg |= (cfg -> rgmii_tx_clk_delay << 0 );
237
- ret = phy_mc_vsc8541_write (dev , PHY_REG_PAGE2_RGMII_CONTROL , reg );
238
- if (ret ) {
239
- return ret ;
240
- }
241
-
242
- /* we use limited advertising, to force gigabit speed */
243
- /* initial version of this driver supports only 1GB/s */
244
-
245
- /* 1000MBit/s + AUTO */
246
- ret = phy_mc_vsc8541_write (dev , PHY_REG_PAGE0_ADV , (1 << 8 ) | (1 << 6 ) | 0x01 );
247
- if (ret ) {
248
- return ret ;
249
- }
250
-
251
- ret = phy_mc_vsc8541_write (dev , PHY_REG_PAGE0_CTRL1000 , (1 << 12 ) | (1 << 11 ) | (1 << 9 ));
252
- if (ret ) {
253
- return ret ;
254
- }
255
212
256
- /* start auto negotiation */
257
- ret = phy_mc_vsc8541_write (dev , PHY_REG_PAGE0_BMCR , BMCR_ANENABLE | BMCR_ANRESTART );
258
- if (ret ) {
259
- return ret ;
260
- }
261
-
262
- return ret ;
213
+ return phy_mc_vsc8541_write (dev , PHY_REG_PAGE2_RGMII_CONTROL , reg );
263
214
}
264
215
265
216
/**
@@ -271,12 +222,13 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
271
222
static int phy_mc_vsc8541_get_speed (const struct device * dev , struct phy_link_state * state )
272
223
{
273
224
int ret ;
274
- uint32_t status ;
225
+ uint32_t aux_status ;
275
226
uint32_t link10_status ;
276
227
uint32_t link100_status ;
277
228
uint32_t link1000_status ;
229
+ bool is_duplex ;
278
230
279
- ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_BMSR , & status );
231
+ ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_EXT_DEV_AUX , & aux_status );
280
232
if (ret ) {
281
233
return ret ;
282
234
}
@@ -296,41 +248,41 @@ static int phy_mc_vsc8541_get_speed(const struct device *dev, struct phy_link_st
296
248
return ret ;
297
249
}
298
250
299
- if ((status & (1 << 2 )) == 0 ) {
300
- /* no link */
301
- state -> speed = LINK_HALF_10BASE ;
302
- }
303
-
304
- if ((status & (1 << 5 )) == 0 ) {
305
- /* auto negotiation not yet complete */
306
- state -> speed = LINK_HALF_10BASE ;
307
- }
251
+ is_duplex = (aux_status & PHY_REG_PAGE0_EXT_DEV_AUX_DUPLEX ) != 0 ;
308
252
309
253
if ((link1000_status & (1 << 12 ))) {
310
- state -> speed = LINK_FULL_1000BASE ;
254
+ state -> speed = is_duplex ? LINK_FULL_1000BASE : LINK_HALF_1000BASE ;
311
255
}
312
256
if (link100_status & (1 << 12 )) {
313
- state -> speed = LINK_FULL_100BASE ;
257
+ state -> speed = is_duplex ? LINK_FULL_100BASE : LINK_HALF_100BASE ;
314
258
}
315
259
if (link10_status & (1 << 6 )) {
316
- state -> speed = LINK_FULL_10BASE ;
260
+ state -> speed = is_duplex ? LINK_FULL_10BASE : LINK_HALF_10BASE ;
317
261
}
318
262
319
263
return 0 ;
320
264
}
321
265
266
+ static int phy_mc_vsc8541_cfg_link (const struct device * dev , enum phy_link_speed adv_speeds ,
267
+ enum phy_cfg_link_flag flags )
268
+ {
269
+ if (flags & PHY_FLAG_AUTO_NEGOTIATION_DISABLED ) {
270
+ LOG_ERR ("Disabling auto-negotiation is not supported by this driver" );
271
+ return - ENOTSUP ;
272
+ }
273
+
274
+ return phy_mii_cfg_link_autoneg (dev , adv_speeds , true);
275
+ }
276
+
322
277
/**
323
278
* @brief Initializes the phy and starts the link monitor
324
279
*
325
280
*/
326
281
static int phy_mc_vsc8541_init (const struct device * dev )
327
282
{
328
283
struct mc_vsc8541_data * data = dev -> data ;
284
+ struct mc_vsc8541_config * cfg = dev -> config ;
329
285
330
- data -> cb = NULL ;
331
- data -> cb_data = NULL ;
332
- data -> state .is_up = false;
333
- data -> state .speed = LINK_HALF_10BASE ;
334
286
data -> active_page = -1 ;
335
287
336
288
/* Reset PHY */
@@ -349,6 +301,8 @@ static int phy_mc_vsc8541_init(const struct device *dev)
349
301
350
302
k_thread_name_set (& data -> link_monitor_thread , "phy-link-mon" );
351
303
304
+ phy_mc_vsc8541_cfg_link (dev , cfg -> default_speeds , 0 );
305
+
352
306
return 0 ;
353
307
}
354
308
@@ -363,37 +317,35 @@ static int phy_mc_vsc8541_get_link(const struct device *dev, struct phy_link_sta
363
317
int ret ;
364
318
uint32_t reg_sr ;
365
319
uint32_t reg_cr ;
320
+ bool hasLink ;
321
+ bool auto_negotiation_finished = true;
366
322
367
- ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_BMSR , & reg_sr );
323
+ ret = phy_mc_vsc8541_read (dev , MII_BMSR , & reg_sr );
368
324
if (ret ) {
369
325
return ret ;
370
326
}
371
327
372
- ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_BMCR , & reg_cr );
328
+ ret = phy_mc_vsc8541_read (dev , MII_BMCR , & reg_cr );
373
329
if (ret ) {
374
330
return ret ;
375
331
}
376
332
377
- uint32_t hasLink = reg_sr & ( 1 << 2 ) ? 1 : 0 ;
333
+ hasLink = ( reg_sr & MII_BMSR_LINK_STATUS ) != 0 ;
378
334
379
- uint32_t auto_negotiation_finished ;
380
-
381
- if (reg_cr & (BMCR_ANENABLE )) {
335
+ if (reg_cr & MII_BMCR_AUTONEG_ENABLE ) {
382
336
/* auto negotiation active; update status */
383
- auto_negotiation_finished = reg_sr & (1 << 5 ) ? 1 : 0 ;
384
- } else {
385
- auto_negotiation_finished = 1 ;
337
+ auto_negotiation_finished = (reg_sr & MII_BMSR_AUTONEG_COMPLETE ) != 0 ;
386
338
}
387
339
388
340
if (hasLink & auto_negotiation_finished ) {
389
- state -> is_up = 1 ;
341
+ state -> is_up = true ;
390
342
ret = phy_mc_vsc8541_get_speed (dev , state );
391
343
if (ret ) {
392
344
return ret ;
393
345
}
394
346
} else {
395
- state -> is_up = 0 ;
396
- state -> speed = LINK_HALF_10BASE ;
347
+ state -> is_up = false ;
348
+ state -> speed = 0 ;
397
349
}
398
350
399
351
return 0 ;
@@ -556,6 +508,7 @@ static DEVICE_API(ethphy, mc_vsc8541_phy_api) = {
556
508
.microchip_interface_type = DT_INST_ENUM_IDX(n, microchip_interface_type), \
557
509
.rgmii_rx_clk_delay = DT_INST_PROP(n, microchip_rgmii_rx_clk_delay), \
558
510
.rgmii_tx_clk_delay = DT_INST_PROP(n, microchip_rgmii_tx_clk_delay), \
511
+ .default_speeds = PHY_INST_GENERATE_DEFAULT_SPEEDS(n), \
559
512
RESET_GPIO(n) INTERRUPT_GPIO(n)}; \
560
513
\
561
514
static struct mc_vsc8541_data mc_vsc8541_##n##_data; \
0 commit comments