@@ -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 ;
224304err :
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 );
339422err :
0 commit comments