@@ -16,6 +16,8 @@ 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
+
19
21
/* phy page selectors */
20
22
#define PHY_PAGE_0 0x00 /* main registers space active */
21
23
#define PHY_PAGE_1 0x01 /* reg 16 - 30 will be redirected to ext. register space 1 */
@@ -26,25 +28,14 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL);
26
28
#define PHY_REG (page , reg ) ((page << 8) | (reg << 0))
27
29
28
30
/* 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
31
#define PHY_REG_PAGE0_STAT100 PHY_REG(PHY_PAGE_0, 0x10)
42
32
#define PHY_REG_PAGE0_STAT1000_EXT2 PHY_REG(PHY_PAGE_0, 0x11)
43
33
#define PHY_REG_AUX_CTRL 0x12
44
34
#define PHY_REG_PAGE0_ERROR_COUNTER_1 PHY_REG(0, 0x13)
45
35
#define PHY_REG_PAGE0_ERROR_COUNTER_2 PHY_REG(0, 0x14)
46
36
#define PHY_REG_PAGE0_EXT_CTRL_STAT PHY_REG(PHY_PAGE_0, 0x16)
47
37
#define PHY_REG_PAGE0_EXT_CONTROL_1 PHY_REG(PHY_PAGE_0, 0x17)
38
+ #define PHY_REG_PAGE0_EXT_DEV_AUX PHY_REG(PHY_PAGE_0, 0x1C)
48
39
#define PHY_REG_LED_MODE 0x1d
49
40
50
41
#define PHY_REG_PAGE_SELECTOR 0x1F
@@ -54,19 +45,7 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL);
54
45
#define PHY_REG_PAGE2_RGMII_CONTROL PHY_REG(PHY_PAGE_2, 0x14)
55
46
#define PHY_REG_PAGE2_MAC_IF_CONTROL PHY_REG(PHY_PAGE_2, 0x1b)
56
47
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)
48
+ #define PHY_REG_PAGE0_EXT_DEV_AUX_DUPLEX BIT(5)
70
49
71
50
enum vsc8541_interface {
72
51
VSC8541_MII ,
@@ -123,11 +102,11 @@ static int phy_mc_vsc8541_verify_phy_id(const struct device *dev)
123
102
uint16_t phy_id_1 ;
124
103
uint16_t phy_id_2 ;
125
104
126
- if (0 != phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_ID1 , (uint32_t * )& phy_id_1 )) {
105
+ if (phy_mc_vsc8541_read (dev , MII_PHYID1R , (uint32_t * )& phy_id_1 ) < 0 ) {
127
106
return - EINVAL ;
128
107
}
129
108
130
- if (0 != phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_ID2 , (uint32_t * )& phy_id_2 )) {
109
+ if (phy_mc_vsc8541_read (dev , MII_PHYID2R , (uint32_t * )& phy_id_2 ) < 0 ) {
131
110
return - EINVAL ;
132
111
}
133
112
@@ -153,6 +132,8 @@ static int phy_mc_vsc8541_verify_phy_id(const struct device *dev)
153
132
static int phy_mc_vsc8541_reset (const struct device * dev )
154
133
{
155
134
const struct mc_vsc8541_config * cfg = dev -> config ;
135
+ int ret ;
136
+ uint32_t reg = 0U ;
156
137
157
138
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
158
139
@@ -162,16 +143,15 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
162
143
}
163
144
164
145
/* configure the reset pin */
165
- int ret = gpio_pin_configure_dt (& cfg -> reset_gpio , GPIO_OUTPUT_ACTIVE );
166
-
167
- if (ret ) {
146
+ ret = gpio_pin_configure_dt (& cfg -> reset_gpio , GPIO_OUTPUT_ACTIVE );
147
+ if (ret < 0 ) {
168
148
return ret ;
169
149
}
170
150
171
151
for (uint32_t i = 0 ; i < 2 ; i ++ ) {
172
152
/* Start reset */
173
153
ret = gpio_pin_set_dt (& cfg -> reset_gpio , 0 );
174
- if (ret ) {
154
+ if (ret < 0 ) {
175
155
LOG_WRN ("failed to set reset gpio" );
176
156
return - EINVAL ;
177
157
}
@@ -194,7 +174,7 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
194
174
195
175
#if CONFIG_PHY_VERIFY_DEVICE_IDENTIFICATION
196
176
/* confirm phy organizationally unique identifier, if enabled */
197
- if (0 != phy_mc_vsc8541_verify_phy_id (dev )) {
177
+ if (phy_mc_vsc8541_verify_phy_id (dev ) < 0 ) {
198
178
LOG_ERR ("failed to verify phy id" );
199
179
return - EINVAL ;
200
180
}
@@ -204,62 +184,30 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
204
184
if (cfg -> microchip_interface_type == VSC8541_RGMII ) {
205
185
ret = phy_mc_vsc8541_write (dev , PHY_REG_PAGE0_EXT_CONTROL_1 ,
206
186
(0x0 << 13 ) | (0x2 << 11 ));
207
- if (ret ) {
187
+ if (ret < 0 ) {
208
188
return ret ;
209
189
}
210
190
}
211
191
212
192
/* software reset */
213
- ret = phy_mc_vsc8541_write (dev , PHY_REG_PAGE0_BMCR , MII_BMCR_RESET );
214
- if (ret ) {
193
+ ret = phy_mc_vsc8541_write (dev , MII_BMCR , MII_BMCR_RESET );
194
+ if (ret < 0 ) {
215
195
return ret ;
216
196
}
217
197
218
198
/* wait for phy finished software reset */
219
- uint32_t reg = 0 ;
220
-
221
199
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
- }
200
+ phy_mc_vsc8541_read (dev , MII_BMCR , & reg );
201
+ } while (reg & MII_BMCR_RESET );
230
202
231
203
/* configure the RGMII clk delay */
232
204
reg = 0x0 ;
233
205
/* RX_CLK delay */
234
206
reg |= (cfg -> rgmii_rx_clk_delay << 4 );
235
207
/* TX_CLK delay */
236
208
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
-
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
209
262
- return ret ;
210
+ return phy_mc_vsc8541_write ( dev , PHY_REG_PAGE2_RGMII_CONTROL , reg ) ;
263
211
}
264
212
265
213
/**
@@ -271,72 +219,79 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
271
219
static int phy_mc_vsc8541_get_speed (const struct device * dev , struct phy_link_state * state )
272
220
{
273
221
int ret ;
274
- uint32_t status ;
222
+ uint32_t aux_status ;
275
223
uint32_t link10_status ;
276
224
uint32_t link100_status ;
277
225
uint32_t link1000_status ;
226
+ bool is_duplex ;
278
227
279
- ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_BMSR , & status );
280
- if (ret ) {
228
+ ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_EXT_DEV_AUX , & aux_status );
229
+ if (ret < 0 ) {
281
230
return ret ;
282
231
}
283
232
284
- ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_EXT_CTRL_STAT , & link10_status );
285
- if (ret ) {
233
+ is_duplex = (aux_status & PHY_REG_PAGE0_EXT_DEV_AUX_DUPLEX ) != 0 ;
234
+
235
+ ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_STAT1000_EXT2 , & link1000_status );
236
+ if (ret < 0 ) {
286
237
return ret ;
287
238
}
288
239
289
- ret = phy_mc_vsc8541_read ( dev , PHY_REG_PAGE0_STAT100 , & link100_status );
290
- if ( ret ) {
291
- return ret ;
240
+ if (( link1000_status & BIT ( 12 ))) {
241
+ state -> speed = is_duplex ? LINK_FULL_1000BASE : LINK_HALF_1000BASE ;
242
+ return 0 ; /* no need to check lower speeds */
292
243
}
293
244
294
- ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_STAT1000_EXT2 , & link1000_status );
295
- if (ret ) {
245
+ ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_STAT100 , & link100_status );
246
+ if (ret < 0 ) {
296
247
return ret ;
297
248
}
298
249
299
- if (( status & ( 1 << 2 )) == 0 ) {
300
- /* no link */
301
- state -> speed = LINK_HALF_10BASE ;
250
+ if (link100_status & BIT ( 12 ) ) {
251
+ state -> speed = is_duplex ? LINK_FULL_100BASE : LINK_HALF_100BASE ;
252
+ return 0 ; /* no need to check lower speeds */
302
253
}
303
254
304
- if (( status & ( 1 << 5 )) == 0 ) {
305
- /* auto negotiation not yet complete */
306
- state -> speed = LINK_HALF_10BASE ;
255
+ ret = phy_mc_vsc8541_read ( dev , PHY_REG_PAGE0_EXT_CTRL_STAT , & link10_status );
256
+ if ( ret < 0 ) {
257
+ return ret ;
307
258
}
308
259
309
- if ((link1000_status & (1 << 12 ))) {
310
- state -> speed = LINK_FULL_1000BASE ;
311
- }
312
- if (link100_status & (1 << 12 )) {
313
- state -> speed = LINK_FULL_100BASE ;
314
- }
315
- if (link10_status & (1 << 6 )) {
316
- state -> speed = LINK_FULL_10BASE ;
260
+ if (link10_status & BIT (6 )) {
261
+ state -> speed = is_duplex ? LINK_FULL_10BASE : LINK_HALF_10BASE ;
262
+ } else {
263
+ state -> speed = 0 ; /* no link */
317
264
}
318
265
319
266
return 0 ;
320
267
}
321
268
269
+ static int phy_mc_vsc8541_cfg_link (const struct device * dev , enum phy_link_speed adv_speeds ,
270
+ enum phy_cfg_link_flag flags )
271
+ {
272
+ if (flags & PHY_FLAG_AUTO_NEGOTIATION_DISABLED ) {
273
+ LOG_ERR ("Disabling auto-negotiation is not supported by this driver" );
274
+ return - ENOTSUP ;
275
+ }
276
+
277
+ return phy_mii_cfg_link_autoneg (dev , adv_speeds , true);
278
+ }
279
+
322
280
/**
323
281
* @brief Initializes the phy and starts the link monitor
324
282
*
325
283
*/
326
284
static int phy_mc_vsc8541_init (const struct device * dev )
327
285
{
328
286
struct mc_vsc8541_data * data = dev -> data ;
287
+ struct mc_vsc8541_config * cfg = dev -> config ;
288
+ int ret ;
329
289
330
- data -> cb = NULL ;
331
- data -> cb_data = NULL ;
332
- data -> state .is_up = false;
333
- data -> state .speed = LINK_HALF_10BASE ;
334
290
data -> active_page = -1 ;
335
291
336
292
/* Reset PHY */
337
- int ret = phy_mc_vsc8541_reset (dev );
338
-
339
- if (ret ) {
293
+ ret = phy_mc_vsc8541_reset (dev );
294
+ if (ret < 0 ) {
340
295
LOG_ERR ("initialize failed" );
341
296
return ret ;
342
297
}
@@ -363,37 +318,35 @@ static int phy_mc_vsc8541_get_link(const struct device *dev, struct phy_link_sta
363
318
int ret ;
364
319
uint32_t reg_sr ;
365
320
uint32_t reg_cr ;
321
+ bool hasLink ;
322
+ bool auto_negotiation_finished = true;
366
323
367
- ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_BMSR , & reg_sr );
368
- if (ret ) {
324
+ ret = phy_mc_vsc8541_read (dev , MII_BMSR , & reg_sr );
325
+ if (ret < 0 ) {
369
326
return ret ;
370
327
}
371
328
372
- ret = phy_mc_vsc8541_read (dev , PHY_REG_PAGE0_BMCR , & reg_cr );
373
- if (ret ) {
329
+ ret = phy_mc_vsc8541_read (dev , MII_BMCR , & reg_cr );
330
+ if (ret < 0 ) {
374
331
return ret ;
375
332
}
376
333
377
- uint32_t hasLink = reg_sr & ( 1 << 2 ) ? 1 : 0 ;
334
+ hasLink = ( reg_sr & MII_BMSR_LINK_STATUS ) != 0 ;
378
335
379
- uint32_t auto_negotiation_finished ;
380
-
381
- if (reg_cr & (BMCR_ANENABLE )) {
336
+ if (reg_cr & MII_BMCR_AUTONEG_ENABLE ) {
382
337
/* auto negotiation active; update status */
383
- auto_negotiation_finished = reg_sr & (1 << 5 ) ? 1 : 0 ;
384
- } else {
385
- auto_negotiation_finished = 1 ;
338
+ auto_negotiation_finished = (reg_sr & MII_BMSR_AUTONEG_COMPLETE ) != 0 ;
386
339
}
387
340
388
- if (hasLink & auto_negotiation_finished ) {
389
- state -> is_up = 1 ;
341
+ if (hasLink && auto_negotiation_finished ) {
342
+ state -> is_up = true ;
390
343
ret = phy_mc_vsc8541_get_speed (dev , state );
391
- if (ret ) {
344
+ if (ret < 0 ) {
392
345
return ret ;
393
346
}
394
347
} else {
395
- state -> is_up = 0 ;
396
- state -> speed = LINK_HALF_10BASE ;
348
+ state -> is_up = false ;
349
+ state -> speed = 0 ;
397
350
}
398
351
399
352
return 0 ;
0 commit comments