1 /*
2  * Copyright (c) 2024 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 /*---------------------------------------------------------------------
9  * Includes
10  *---------------------------------------------------------------------
11  */
12 #include "hpm_enet_drv.h"
13 #include "hpm_lan8720_regs.h"
14 #include "hpm_lan8720.h"
15 
16 /*---------------------------------------------------------------------
17  * Internal API
18  *---------------------------------------------------------------------
19  */
lan8720_check_id(ENET_Type * ptr)20 static bool lan8720_check_id(ENET_Type *ptr)
21 {
22     uint16_t id1, id2;
23 
24     id1 = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_PHYID1);
25     id2 = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_PHYID2);
26 
27     if (LAN8720_PHYID1_OUI_MSB_GET(id1) == LAN8720_ID1 && LAN8720_PHYID2_OUI_LSB_GET(id2) == LAN8720_ID2) {
28         return true;
29     } else {
30         return false;
31     }
32 }
33 
34 /*---------------------------------------------------------------------
35  * API
36  *---------------------------------------------------------------------
37  */
lan8720_reset(ENET_Type * ptr)38 void lan8720_reset(ENET_Type *ptr)
39 {
40     uint16_t data;
41 
42     /* PHY reset */
43     enet_write_phy(ptr, LAN8720_ADDR, LAN8720_BMCR, LAN8720_BMCR_RESET_SET(1));
44 
45     /* wait until the reset is completed */
46     do {
47         data = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_BMCR);
48     } while (LAN8720_BMCR_RESET_GET(data));
49 }
50 
lan8720_basic_mode_default_config(ENET_Type * ptr,lan8720_config_t * config)51 void lan8720_basic_mode_default_config(ENET_Type *ptr, lan8720_config_t *config)
52 {
53     config->loopback         = false;                        /* Disable PCS loopback mode */
54     #if defined(__DISABLE_AUTO_NEGO) && __DISABLE_AUTO_NEGO
55     config->auto_negotiation = false;                        /* Disable Auto-Negotiation */
56     config->speed            = enet_phy_port_speed_100mbps;
57     config->duplex           = enet_phy_duplex_full;
58     #else
59     config->auto_negotiation = true;                         /* Enable Auto-Negotiation */
60     #endif
61 }
62 
lan8720_basic_mode_init(ENET_Type * ptr,lan8720_config_t * config)63 bool lan8720_basic_mode_init(ENET_Type *ptr, lan8720_config_t *config)
64 {
65     uint16_t data = 0;
66 
67     data |= LAN8720_BMCR_RESET_SET(0)                        /* Normal operation */
68          |  LAN8720_BMCR_LOOPBACK_SET(config->loopback)      /* configure PCS loopback mode */
69          |  LAN8720_BMCR_ANE_SET(config->auto_negotiation)   /* configure Auto-Negotiation */
70          |  LAN8720_BMCR_PWD_SET(0)                          /* Normal operation */
71          |  LAN8720_BMCR_ISOLATE_SET(0)                      /* Normal operation */
72          |  LAN8720_BMCR_RESTART_AN_SET(0);                  /* Normal operation (ignored when Auto-Negotiation is disabled) */
73 
74     if (config->auto_negotiation == 0) {
75         data |= LAN8720_BMCR_SPEED_SET(config->speed);      /* Set port speed */
76         data |= LAN8720_BMCR_DUPLEX_SET(config->duplex);     /* Set duplex mode */
77     }
78 
79     /* check the id of lan8720 */
80     if (lan8720_check_id(ptr) == false) {
81         return false;
82     }
83 
84     enet_write_phy(ptr, LAN8720_ADDR, LAN8720_BMCR, data);
85 
86     return true;
87 }
88 
lan8720_get_phy_status(ENET_Type * ptr,enet_phy_status_t * status)89 void lan8720_get_phy_status(ENET_Type *ptr, enet_phy_status_t *status)
90 {
91     uint16_t data;
92 
93     data = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_BMSR);
94     status->enet_phy_link = LAN8720_BMSR_LINK_STATUS_GET(data);
95 
96     data = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_PSCSR);
97     status->enet_phy_speed = LAN8720_PSCSR_SPEED_GET(data) == 1 ? enet_phy_port_speed_10mbps : enet_phy_port_speed_100mbps;
98     status->enet_phy_duplex = LAN8720_PSCSR_DUPLEX_GET(data);
99 }
100