Skip to content

Commit 6d6034f

Browse files
committed
Port the ENC28J60 PHY to the IDF 5.x autonego_ctrl vtable
1 parent 299a964 commit 6d6034f

2 files changed

Lines changed: 174 additions & 8 deletions

File tree

ESP32/TLS13-ENC28J60-client/main/esp_eth_phy_enc28j60.c

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ static const char *TAG = "enc28j60";
3333

3434
/***************Vendor Specific Register***************/
3535

36+
/**
37+
* @brief PHCON1(PHY Control Register 1)
38+
*
39+
*/
40+
typedef union {
41+
struct {
42+
uint32_t reserved_7_0 : 8; // Reserved
43+
uint32_t pdpxmd : 1; // PHY Duplex Mode
44+
uint32_t reserved_10_9: 2; // Reserved
45+
uint32_t ppwrsv: 1; // PHY Power-Down
46+
uint32_t reserved_13_12: 2; // Reserved
47+
uint32_t ploopbk: 1; // PHY Loopback
48+
uint32_t prst: 1; // PHY Software Reset
49+
};
50+
uint32_t val;
51+
} phcon1_reg_t;
52+
#define ETH_PHY_PHCON1_REG_ADDR (0x00)
53+
3654
/**
3755
* @brief PHCON2(PHY Control Register 2)
3856
*
@@ -208,7 +226,8 @@ static esp_err_t enc28j60_reset_hw(esp_eth_phy_t *phy)
208226
return ESP_OK;
209227
}
210228

211-
static esp_err_t enc28j60_negotiate(esp_eth_phy_t *phy)
229+
static esp_err_t enc28j60_autonego_ctrl(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd,
230+
bool *autoneg_en_stat)
212231
{
213232
/**
214233
* ENC28J60 does not support automatic duplex negotiation.
@@ -217,9 +236,70 @@ static esp_err_t enc28j60_negotiate(esp_eth_phy_t *phy)
217236
* To communicate in Full-Duplex mode, ENC28J60 and the remote node
218237
* must be manually configured for full-duplex operation.
219238
*/
239+
switch (cmd) {
240+
case ESP_ETH_PHY_AUTONEGO_RESTART:
241+
/* Fallthrough */
242+
case ESP_ETH_PHY_AUTONEGO_EN:
243+
return ESP_ERR_NOT_SUPPORTED;
244+
case ESP_ETH_PHY_AUTONEGO_DIS:
245+
/* Fallthrough */
246+
case ESP_ETH_PHY_AUTONEGO_G_STAT:
247+
*autoneg_en_stat = false;
248+
break;
249+
default:
250+
return ESP_ERR_INVALID_ARG;
251+
}
252+
return ESP_OK;
253+
}
254+
255+
static esp_err_t enc28j60_set_link(esp_eth_phy_t *phy, eth_link_t link)
256+
{
220257
phy_enc28j60_t *enc28j60 = __containerof(phy, phy_enc28j60_t, parent);
221-
/* Updata information about link, speed, duplex */
222-
PHY_CHECK(enc28j60_update_link_duplex_speed(enc28j60) == ESP_OK, "update link duplex speed failed", err);
258+
esp_eth_mediator_t *eth = enc28j60->eth;
259+
260+
if (enc28j60->link_status != link) {
261+
enc28j60->link_status = link;
262+
PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK,
263+
"change link failed", err);
264+
}
265+
return ESP_OK;
266+
err:
267+
return ESP_FAIL;
268+
}
269+
270+
static esp_err_t enc28j60_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
271+
{
272+
/* ENC28J60 supports only 10Mbps */
273+
if (speed == ETH_SPEED_10M) {
274+
return ESP_OK;
275+
}
276+
return ESP_ERR_NOT_SUPPORTED;
277+
}
278+
279+
static esp_err_t enc28j60_set_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
280+
{
281+
phy_enc28j60_t *enc28j60 = __containerof(phy, phy_enc28j60_t, parent);
282+
esp_eth_mediator_t *eth = enc28j60->eth;
283+
phcon1_reg_t phcon1;
284+
285+
/* the link is being reconfigured, so report it down until the driver restarts */
286+
enc28j60->link_status = ETH_LINK_DOWN;
287+
288+
PHY_CHECK(eth->phy_reg_read(eth, enc28j60->addr, ETH_PHY_PHCON1_REG_ADDR, &(phcon1.val)) == ESP_OK,
289+
"read PHCON1 failed", err);
290+
switch (duplex) {
291+
case ETH_DUPLEX_HALF:
292+
phcon1.pdpxmd = 0;
293+
break;
294+
case ETH_DUPLEX_FULL:
295+
phcon1.pdpxmd = 1;
296+
break;
297+
default:
298+
PHY_CHECK(false, "unknown duplex", err);
299+
break;
300+
}
301+
PHY_CHECK(eth->phy_reg_write(eth, enc28j60->addr, ETH_PHY_PHCON1_REG_ADDR, phcon1.val) == ESP_OK,
302+
"write PHCON1 failed", err);
223303
return ESP_OK;
224304
err:
225305
return ESP_FAIL;
@@ -329,11 +409,14 @@ esp_eth_phy_t *esp_eth_phy_new_enc28j60(const eth_phy_config_t *config)
329409
enc28j60->parent.init = enc28j60_init;
330410
enc28j60->parent.deinit = enc28j60_deinit;
331411
enc28j60->parent.set_mediator = enc28j60_set_mediator;
332-
enc28j60->parent.negotiate = enc28j60_negotiate;
412+
enc28j60->parent.autonego_ctrl = enc28j60_autonego_ctrl;
333413
enc28j60->parent.get_link = enc28j60_get_link;
414+
enc28j60->parent.set_link = enc28j60_set_link;
334415
enc28j60->parent.pwrctl = enc28j60_pwrctl;
335416
enc28j60->parent.get_addr = enc28j60_get_addr;
336417
enc28j60->parent.set_addr = enc28j60_set_addr;
418+
enc28j60->parent.set_speed = enc28j60_set_speed;
419+
enc28j60->parent.set_duplex = enc28j60_set_duplex;
337420
enc28j60->parent.del = enc28j60_del;
338421
return &(enc28j60->parent);
339422
err:

ESP32/TLS13-ENC28J60-server/main/esp_eth_phy_enc28j60.c

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ static const char *TAG = "enc28j60";
3333

3434
/***************Vendor Specific Register***************/
3535

36+
/**
37+
* @brief PHCON1(PHY Control Register 1)
38+
*
39+
*/
40+
typedef union {
41+
struct {
42+
uint32_t reserved_7_0 : 8; // Reserved
43+
uint32_t pdpxmd : 1; // PHY Duplex Mode
44+
uint32_t reserved_10_9: 2; // Reserved
45+
uint32_t ppwrsv: 1; // PHY Power-Down
46+
uint32_t reserved_13_12: 2; // Reserved
47+
uint32_t ploopbk: 1; // PHY Loopback
48+
uint32_t prst: 1; // PHY Software Reset
49+
};
50+
uint32_t val;
51+
} phcon1_reg_t;
52+
#define ETH_PHY_PHCON1_REG_ADDR (0x00)
53+
3654
/**
3755
* @brief PHCON2(PHY Control Register 2)
3856
*
@@ -208,7 +226,8 @@ static esp_err_t enc28j60_reset_hw(esp_eth_phy_t *phy)
208226
return ESP_OK;
209227
}
210228

211-
static esp_err_t enc28j60_negotiate(esp_eth_phy_t *phy)
229+
static esp_err_t enc28j60_autonego_ctrl(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd,
230+
bool *autoneg_en_stat)
212231
{
213232
/**
214233
* ENC28J60 does not support automatic duplex negotiation.
@@ -217,9 +236,70 @@ static esp_err_t enc28j60_negotiate(esp_eth_phy_t *phy)
217236
* To communicate in Full-Duplex mode, ENC28J60 and the remote node
218237
* must be manually configured for full-duplex operation.
219238
*/
239+
switch (cmd) {
240+
case ESP_ETH_PHY_AUTONEGO_RESTART:
241+
/* Fallthrough */
242+
case ESP_ETH_PHY_AUTONEGO_EN:
243+
return ESP_ERR_NOT_SUPPORTED;
244+
case ESP_ETH_PHY_AUTONEGO_DIS:
245+
/* Fallthrough */
246+
case ESP_ETH_PHY_AUTONEGO_G_STAT:
247+
*autoneg_en_stat = false;
248+
break;
249+
default:
250+
return ESP_ERR_INVALID_ARG;
251+
}
252+
return ESP_OK;
253+
}
254+
255+
static esp_err_t enc28j60_set_link(esp_eth_phy_t *phy, eth_link_t link)
256+
{
220257
phy_enc28j60_t *enc28j60 = __containerof(phy, phy_enc28j60_t, parent);
221-
/* Updata information about link, speed, duplex */
222-
PHY_CHECK(enc28j60_update_link_duplex_speed(enc28j60) == ESP_OK, "update link duplex speed failed", err);
258+
esp_eth_mediator_t *eth = enc28j60->eth;
259+
260+
if (enc28j60->link_status != link) {
261+
enc28j60->link_status = link;
262+
PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK,
263+
"change link failed", err);
264+
}
265+
return ESP_OK;
266+
err:
267+
return ESP_FAIL;
268+
}
269+
270+
static esp_err_t enc28j60_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
271+
{
272+
/* ENC28J60 supports only 10Mbps */
273+
if (speed == ETH_SPEED_10M) {
274+
return ESP_OK;
275+
}
276+
return ESP_ERR_NOT_SUPPORTED;
277+
}
278+
279+
static esp_err_t enc28j60_set_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
280+
{
281+
phy_enc28j60_t *enc28j60 = __containerof(phy, phy_enc28j60_t, parent);
282+
esp_eth_mediator_t *eth = enc28j60->eth;
283+
phcon1_reg_t phcon1;
284+
285+
/* the link is being reconfigured, so report it down until the driver restarts */
286+
enc28j60->link_status = ETH_LINK_DOWN;
287+
288+
PHY_CHECK(eth->phy_reg_read(eth, enc28j60->addr, ETH_PHY_PHCON1_REG_ADDR, &(phcon1.val)) == ESP_OK,
289+
"read PHCON1 failed", err);
290+
switch (duplex) {
291+
case ETH_DUPLEX_HALF:
292+
phcon1.pdpxmd = 0;
293+
break;
294+
case ETH_DUPLEX_FULL:
295+
phcon1.pdpxmd = 1;
296+
break;
297+
default:
298+
PHY_CHECK(false, "unknown duplex", err);
299+
break;
300+
}
301+
PHY_CHECK(eth->phy_reg_write(eth, enc28j60->addr, ETH_PHY_PHCON1_REG_ADDR, phcon1.val) == ESP_OK,
302+
"write PHCON1 failed", err);
223303
return ESP_OK;
224304
err:
225305
return ESP_FAIL;
@@ -329,11 +409,14 @@ esp_eth_phy_t *esp_eth_phy_new_enc28j60(const eth_phy_config_t *config)
329409
enc28j60->parent.init = enc28j60_init;
330410
enc28j60->parent.deinit = enc28j60_deinit;
331411
enc28j60->parent.set_mediator = enc28j60_set_mediator;
332-
enc28j60->parent.negotiate = enc28j60_negotiate;
412+
enc28j60->parent.autonego_ctrl = enc28j60_autonego_ctrl;
333413
enc28j60->parent.get_link = enc28j60_get_link;
414+
enc28j60->parent.set_link = enc28j60_set_link;
334415
enc28j60->parent.pwrctl = enc28j60_pwrctl;
335416
enc28j60->parent.get_addr = enc28j60_get_addr;
336417
enc28j60->parent.set_addr = enc28j60_set_addr;
418+
enc28j60->parent.set_speed = enc28j60_set_speed;
419+
enc28j60->parent.set_duplex = enc28j60_set_duplex;
337420
enc28j60->parent.del = enc28j60_del;
338421
return &(enc28j60->parent);
339422
err:

0 commit comments

Comments
 (0)