• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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_rtl8201_regs.h"
14 #include "hpm_rtl8201.h"
15 #include "board.h"
16 
17 /*---------------------------------------------------------------------
18  * Internal API
19  *---------------------------------------------------------------------
20  */
rtl8201_check_id(ENET_Type * ptr)21 static bool rtl8201_check_id(ENET_Type *ptr)
22 {
23     uint16_t id1, id2;
24 
25     id1 = enet_read_phy(ptr, RTL8201_ADDR, RTL8201_PHYID1);
26     id2 = enet_read_phy(ptr, RTL8201_ADDR, RTL8201_PHYID2);
27 
28     if (RTL8201_PHYID1_OUI_MSB_GET(id1) == RTL8201_ID1 && RTL8201_PHYID2_OUI_LSB_GET(id2) == RTL8201_ID2) {
29         return true;
30     } else {
31         return false;
32     }
33 }
34 
35 /*---------------------------------------------------------------------
36  * API
37  *---------------------------------------------------------------------
38  */
rtl8201_reset(ENET_Type * ptr)39 void rtl8201_reset(ENET_Type *ptr)
40 {
41     uint16_t data;
42 
43     /* PHY reset */
44     enet_write_phy(ptr, RTL8201_ADDR, RTL8201_BMCR, RTL8201_BMCR_RESET_SET(1));
45 
46     /* wait until the reset is completed */
47     do {
48         data = enet_read_phy(ptr, RTL8201_ADDR, RTL8201_BMCR);
49     } while (RTL8201_BMCR_RESET_GET(data));
50 }
51 
rtl8201_basic_mode_default_config(ENET_Type * ptr,rtl8201_config_t * config)52 void rtl8201_basic_mode_default_config(ENET_Type *ptr, rtl8201_config_t *config)
53 {
54     (void)ptr;
55 
56     config->loopback         = 0;                            /* Disable PCS loopback mode */
57     #if defined(__DISABLE_AUTO_NEGO) && (__DISABLE_AUTO_NEGO)
58     config->auto_negotiation = false;                        /* Disable Auto-Negotiation */
59     config->speed            = enet_phy_port_speed_100mbps;
60     config->duplex           = enet_phy_duplex_full;
61     #else
62     config->auto_negotiation = 1;                            /* Enable Auto-Negotiation */
63     #endif
64     config->txc_input        = true;                         /* Set TXC as input mode */
65 }
66 
rtl8201_basic_mode_init(ENET_Type * ptr,rtl8201_config_t * config)67 bool rtl8201_basic_mode_init(ENET_Type *ptr, rtl8201_config_t *config)
68 {
69     uint16_t data = 0;
70 
71     data |= RTL8201_BMCR_RESET_SET(0)                        /* Normal operation */
72          |  RTL8201_BMCR_LOOPBACK_SET(config->loopback)      /* configure PCS loopback mode */
73          |  RTL8201_BMCR_ANE_SET(config->auto_negotiation)   /* configure Auto-Negotiation */
74          |  RTL8201_BMCR_PWD_SET(0)                          /* Normal operation */
75          |  RTL8201_BMCR_ISOLATE_SET(0)                      /* Normal operation */
76          |  RTL8201_BMCR_RESTART_AN_SET(0)                   /* Normal operation (ignored when Auto-Negotiation is disabled) */
77          |  RTL8201_BMCR_COLLISION_TEST_SET(0);              /* Normal operation */
78 
79     if (config->auto_negotiation == 0) {
80         data |= RTL8201_BMCR_SPEED0_SET(config->speed);      /* Set port speed */
81         data |= RTL8201_BMCR_DUPLEX_SET(config->duplex);     /* Set duplex mode */
82     }
83 
84     /* check the id of rtl8201 */
85     if (rtl8201_check_id(ptr) == false) {
86         return false;
87     }
88 
89     enet_write_phy(ptr, RTL8201_ADDR, RTL8201_BMCR, data);
90 
91     /* select page 7 */
92     enet_write_phy(ptr, RTL8201_ADDR, RTL8201_PAGESEL, 7);
93 
94     /* set txc direction */
95     data = enet_read_phy(ptr, RTL8201_ADDR, RTL8201_RMSR_P7);
96     data &= ~RTL8201_RMSR_P7_RG_RMII_CLKDIR_MASK;
97     data |= RTL8201_RMSR_P7_RG_RMII_CLKDIR_SET(config->txc_input);
98     enet_write_phy(ptr, RTL8201_ADDR, RTL8201_RMSR_P7, data);
99 
100     return true;
101 }
102 
rtl8201_get_phy_status(ENET_Type * ptr,enet_phy_status_t * status)103 void rtl8201_get_phy_status(ENET_Type *ptr, enet_phy_status_t *status)
104 {
105     uint16_t data;
106 
107     data = enet_read_phy(ptr, RTL8201_ADDR, RTL8201_BMSR);
108     status->enet_phy_link = RTL8201_BMSR_LINK_STATUS_GET(data);
109 
110     data = enet_read_phy(ptr, RTL8201_ADDR, RTL8201_BMCR);
111     status->enet_phy_speed = RTL8201_BMCR_SPEED0_GET(data) == 0 ? enet_phy_port_speed_10mbps : enet_phy_port_speed_100mbps;
112     status->enet_phy_duplex = RTL8201_BMCR_DUPLEX_GET(data);
113 }
114