Skip to content

Commit 62e692e

Browse files
committed
drivers: ethernet: phy: microchip_vsc8541: use default speeds
- use default speeds - implement configure link - support half duplex - use defines from mii.h Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
1 parent 0a2ddba commit 62e692e

File tree

2 files changed

+48
-91
lines changed

2 files changed

+48
-91
lines changed

drivers/ethernet/phy/phy_microchip_vsc8541.c

Lines changed: 44 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL);
1616
#include <zephyr/sys/util_macro.h>
1717
#include <zephyr/drivers/gpio.h>
1818

19+
#include "phy_mii.h"
20+
#include "phy_common.h"
21+
1922
/* phy page selectors */
2023
#define PHY_PAGE_0 0x00 /* main registers space active */
2124
#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);
2629
#define PHY_REG(page, reg) ((page << 8) | (reg << 0))
2730

2831
/* 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
4132
#define PHY_REG_PAGE0_STAT100 PHY_REG(PHY_PAGE_0, 0x10)
4233
#define PHY_REG_PAGE0_STAT1000_EXT2 PHY_REG(PHY_PAGE_0, 0x11)
4334
#define PHY_REG_AUX_CTRL 0x12
4435
#define PHY_REG_PAGE0_ERROR_COUNTER_1 PHY_REG(0, 0x13)
4536
#define PHY_REG_PAGE0_ERROR_COUNTER_2 PHY_REG(0, 0x14)
4637
#define PHY_REG_PAGE0_EXT_CTRL_STAT PHY_REG(PHY_PAGE_0, 0x16)
4738
#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)
4840
#define PHY_REG_LED_MODE 0x1d
4941

5042
#define PHY_REG_PAGE_SELECTOR 0x1F
@@ -54,19 +46,7 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL);
5446
#define PHY_REG_PAGE2_RGMII_CONTROL PHY_REG(PHY_PAGE_2, 0x14)
5547
#define PHY_REG_PAGE2_MAC_IF_CONTROL PHY_REG(PHY_PAGE_2, 0x1b)
5648

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)
7050

7151
enum vsc8541_interface {
7252
VSC8541_MII,
@@ -85,6 +65,7 @@ struct mc_vsc8541_config {
8565
uint8_t addr;
8666
const struct device *mdio_dev;
8767
enum vsc8541_interface microchip_interface_type;
68+
enum phy_link_speed default_speeds;
8869
uint8_t rgmii_rx_clk_delay;
8970
uint8_t rgmii_tx_clk_delay;
9071
#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)
123104
uint16_t phy_id_1;
124105
uint16_t phy_id_2;
125106

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)) {
127108
return -EINVAL;
128109
}
129110

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)) {
131112
return -EINVAL;
132113
}
133114

@@ -210,7 +191,7 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
210191
}
211192

212193
/* 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);
214195
if (ret) {
215196
return ret;
216197
}
@@ -219,47 +200,17 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
219200
uint32_t reg = 0;
220201

221202
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);
230205

231206
/* configure the RGMII clk delay */
232207
reg = 0x0;
233208
/* RX_CLK delay */
234209
reg |= (cfg->rgmii_rx_clk_delay << 4);
235210
/* TX_CLK delay */
236211
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-
}
255212

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);
263214
}
264215

265216
/**
@@ -271,12 +222,13 @@ static int phy_mc_vsc8541_reset(const struct device *dev)
271222
static int phy_mc_vsc8541_get_speed(const struct device *dev, struct phy_link_state *state)
272223
{
273224
int ret;
274-
uint32_t status;
225+
uint32_t aux_status;
275226
uint32_t link10_status;
276227
uint32_t link100_status;
277228
uint32_t link1000_status;
229+
bool is_duplex;
278230

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);
280232
if (ret) {
281233
return ret;
282234
}
@@ -296,41 +248,41 @@ static int phy_mc_vsc8541_get_speed(const struct device *dev, struct phy_link_st
296248
return ret;
297249
}
298250

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;
308252

309253
if ((link1000_status & (1 << 12))) {
310-
state->speed = LINK_FULL_1000BASE;
254+
state->speed = is_duplex ? LINK_FULL_1000BASE : LINK_HALF_1000BASE;
311255
}
312256
if (link100_status & (1 << 12)) {
313-
state->speed = LINK_FULL_100BASE;
257+
state->speed = is_duplex ? LINK_FULL_100BASE : LINK_HALF_100BASE;
314258
}
315259
if (link10_status & (1 << 6)) {
316-
state->speed = LINK_FULL_10BASE;
260+
state->speed = is_duplex ? LINK_FULL_10BASE : LINK_HALF_10BASE;
317261
}
318262

319263
return 0;
320264
}
321265

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+
322277
/**
323278
* @brief Initializes the phy and starts the link monitor
324279
*
325280
*/
326281
static int phy_mc_vsc8541_init(const struct device *dev)
327282
{
328283
struct mc_vsc8541_data *data = dev->data;
284+
struct mc_vsc8541_config *cfg = dev->config;
329285

330-
data->cb = NULL;
331-
data->cb_data = NULL;
332-
data->state.is_up = false;
333-
data->state.speed = LINK_HALF_10BASE;
334286
data->active_page = -1;
335287

336288
/* Reset PHY */
@@ -349,6 +301,8 @@ static int phy_mc_vsc8541_init(const struct device *dev)
349301

350302
k_thread_name_set(&data->link_monitor_thread, "phy-link-mon");
351303

304+
phy_mc_vsc8541_cfg_link(dev, cfg->default_speeds, 0);
305+
352306
return 0;
353307
}
354308

@@ -363,37 +317,35 @@ static int phy_mc_vsc8541_get_link(const struct device *dev, struct phy_link_sta
363317
int ret;
364318
uint32_t reg_sr;
365319
uint32_t reg_cr;
320+
bool hasLink;
321+
bool auto_negotiation_finished = true;
366322

367-
ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_BMSR, &reg_sr);
323+
ret = phy_mc_vsc8541_read(dev, MII_BMSR, &reg_sr);
368324
if (ret) {
369325
return ret;
370326
}
371327

372-
ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_BMCR, &reg_cr);
328+
ret = phy_mc_vsc8541_read(dev, MII_BMCR, &reg_cr);
373329
if (ret) {
374330
return ret;
375331
}
376332

377-
uint32_t hasLink = reg_sr & (1 << 2) ? 1 : 0;
333+
hasLink = (reg_sr & MII_BMSR_LINK_STATUS) != 0;
378334

379-
uint32_t auto_negotiation_finished;
380-
381-
if (reg_cr & (BMCR_ANENABLE)) {
335+
if (reg_cr & MII_BMCR_AUTONEG_ENABLE) {
382336
/* 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;
386338
}
387339

388340
if (hasLink & auto_negotiation_finished) {
389-
state->is_up = 1;
341+
state->is_up = true;
390342
ret = phy_mc_vsc8541_get_speed(dev, state);
391343
if (ret) {
392344
return ret;
393345
}
394346
} else {
395-
state->is_up = 0;
396-
state->speed = LINK_HALF_10BASE;
347+
state->is_up = false;
348+
state->speed = 0;
397349
}
398350

399351
return 0;
@@ -556,6 +508,7 @@ static DEVICE_API(ethphy, mc_vsc8541_phy_api) = {
556508
.microchip_interface_type = DT_INST_ENUM_IDX(n, microchip_interface_type), \
557509
.rgmii_rx_clk_delay = DT_INST_PROP(n, microchip_rgmii_rx_clk_delay), \
558510
.rgmii_tx_clk_delay = DT_INST_PROP(n, microchip_rgmii_tx_clk_delay), \
511+
.default_speeds = PHY_INST_GENERATE_DEFAULT_SPEEDS(n), \
559512
RESET_GPIO(n) INTERRUPT_GPIO(n)}; \
560513
\
561514
static struct mc_vsc8541_data mc_vsc8541_##n##_data; \

dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,7 @@ properties:
4242
description: |
4343
Used to configure the TX clock delay for RGMII interface. The value can be
4444
0 to 7. Refer to the datasheet for more details on the delay settings.
45+
46+
default-speeds:
47+
default: ["10BASE Half-Duplex", "10BASE Full-Duplex", "100BASE Half-Duplex",
48+
"100BASE Full-Duplex", "1000BASE Half-Duplex", "1000BASE Full-Duplex"]

0 commit comments

Comments
 (0)