1 /*
2 * Copyright (c) 2021 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_dp83867_regs.h"
14 #include "hpm_dp83867.h"
15 #include "board.h"
16
17 /*---------------------------------------------------------------------
18 * Interal API
19 *---------------------------------------------------------------------
20 */
dp83867_id_check(ENET_Type * ptr)21 bool dp83867_id_check(ENET_Type *ptr)
22 {
23 uint16_t id1, id2;
24
25 id1 = enet_read_phy(ptr, PHY_ADDR, DP83867_REG_PHYID1);
26 id2 = enet_read_phy(ptr, PHY_ADDR, DP83867_REG_PHYID2);
27
28 if (DP83867_PHYID1_OUI_MSB_GET(id1) == PHY_ID1 && DP83867_PHYID2_OUI_MSB_GET(id2) == PHY_ID2) {
29 return true;
30 } else {
31 return false;
32 }
33 }
34
dp83867_phy_write_ext(ENET_Type * ptr,uint32_t phy_addr,uint32_t addr,uint32_t data)35 static void dp83867_phy_write_ext(ENET_Type *ptr, uint32_t phy_addr, uint32_t addr, uint32_t data)
36 {
37 /* set the control register for register address */
38 enet_write_phy(ptr, phy_addr, DP83867_EXT_REG_REGCR, DP83867_REGCR_FUNCTION_ADDR | DP83867_REGCR_DEVAD);
39
40 /* write the specified register address */
41 enet_write_phy(ptr, phy_addr, DP83867_EXT_REG_ADDAR, addr);
42
43 /* set the control register for register data */
44 enet_write_phy(ptr, phy_addr, DP83867_EXT_REG_REGCR, DP83867_REGCR_FUNCTION_DATA | DP83867_REGCR_DEVAD);
45
46 /* write the specified register data */
47 enet_write_phy(ptr, phy_addr, DP83867_EXT_REG_ADDAR, data);
48 }
49
dp83867_phy_read_ext(ENET_Type * ptr,uint32_t phy_addr,uint32_t addr)50 static uint16_t dp83867_phy_read_ext(ENET_Type *ptr, uint32_t phy_addr, uint32_t addr)
51 {
52 /* set the control register for register address */
53 enet_write_phy(ptr, phy_addr, DP83867_EXT_REG_REGCR, DP83867_REGCR_FUNCTION_ADDR | DP83867_REGCR_DEVAD);
54
55 /* write the specified register address */
56 enet_write_phy(ptr, phy_addr, DP83867_EXT_REG_ADDAR, addr);
57
58 /* set the control register for register data */
59 enet_write_phy(ptr, phy_addr, DP83867_EXT_REG_REGCR, DP83867_REGCR_FUNCTION_DATA | DP83867_REGCR_DEVAD);
60
61 /* read the specified register data */
62 return enet_read_phy(ptr, phy_addr, DP83867_EXT_REG_ADDAR);
63 }
64 /*---------------------------------------------------------------------
65 * API
66 *---------------------------------------------------------------------
67 */
DP83867_REGister_check(ENET_Type * ptr,uint32_t addr)68 uint16_t DP83867_REGister_check(ENET_Type *ptr, uint32_t addr)
69 {
70 return enet_read_phy(ptr, PHY_ADDR, addr);
71 }
72
dp83867_reset(ENET_Type * ptr)73 void dp83867_reset(ENET_Type *ptr)
74 {
75 uint16_t data;
76
77 /* PHY reset */
78 enet_write_phy(ptr, PHY_ADDR, DP83867_REG_BMCR, DP83867_BMCR_RESET_SET(1));
79
80 /* wait until the reset is completed */
81 do {
82 data = enet_read_phy(ptr, PHY_ADDR, DP83867_REG_BMCR);
83 } while (DP83867_BMCR_RESET_GET(data));
84 }
85
dp83867_basic_mode_default_config(ENET_Type * ptr,dp83867_config_t * config)86 void dp83867_basic_mode_default_config(ENET_Type *ptr, dp83867_config_t *config)
87 {
88 config->loopback = 0; /* Enable PCS loopback mode */
89 config->speed = 2; /* 3: reserved; 2: 1000mbps; 1: 100mbps; 0: 10mbps */
90 config->auto_negotiation = 1; /* Enable Auto-Negotiation */
91 config->duplex_mode = 1; /* Full duplex mode */
92 }
93
dp83867_basic_mode_init(ENET_Type * ptr,dp83867_config_t * config)94 bool dp83867_basic_mode_init(ENET_Type *ptr, dp83867_config_t *config)
95 {
96 uint16_t para = 0;
97
98 para |= DP83867_BMCR_RESET_SET(0) /* Normal operation */
99 | DP83867_BMCR_LOOPBACK_SET(config->loopback) /* Configure PCS loopback mode */
100 | DP83867_BMCR_ANE_SET(config->auto_negotiation) /* Configure Auto-Negotiation */
101 | DP83867_BMCR_PWD_SET(0) /* Normal operation */
102 | DP83867_BMCR_ISOLATE_SET(0) /* Normal operation */
103 | DP83867_BMCR_RESTART_AN_SET(0) /* Normal operation (ignored when Auto-Negotiation is disabled) */
104 | DP83867_BMCR_DUPLEX_SET(config->duplex_mode) /* Config duplex mode */
105 | DP83867_BMCR_COLLISION_TEST_SET(0); /* Normal operation */
106
107 if (config->auto_negotiation == false) {
108 para |= DP83867_BMCR_SPEED0_SET(config->speed) | DP83867_BMCR_SPEED1_SET(config->speed >> 1);
109 }
110
111 /* check the id of dp83867 */
112 if (dp83867_id_check(ptr) == false) {
113 return false;
114 }
115
116 while (dp83867_get_phy_link_status(ptr) == 0) {
117
118 }
119
120 return true;
121 }
122
dp83867_init_auto_negotiation(void)123 void dp83867_init_auto_negotiation(void)
124 {
125
126 }
127
dp83867_get_phy_link_status(ENET_Type * ptr)128 uint16_t dp83867_get_phy_link_status(ENET_Type *ptr)
129 {
130 return DP83867_BMSR_LINK_STATUS_GET(enet_read_phy(ptr, PHY_ADDR, DP83867_REG_BMSR));
131 }
132
dp83867_set_rgmii_rx_delay(ENET_Type * ptr,uint32_t phy_addr,uint8_t delay)133 void dp83867_set_rgmii_rx_delay(ENET_Type *ptr, uint32_t phy_addr, uint8_t delay)
134 {
135 dp83867_phy_write_ext(ptr, phy_addr, DP83867_EXT_REG_RGMIIDCTL, delay);
136 }
137
dp83867_get_rgmii_rx_delay(ENET_Type * ptr,uint32_t phy_addr)138 uint16_t dp83867_get_rgmii_rx_delay(ENET_Type *ptr, uint32_t phy_addr)
139 {
140 uint16_t temp = 0;
141
142 temp = dp83867_phy_read_ext(ptr, phy_addr, DP83867_EXT_REG_RGMIIDCTL);
143
144 return temp;
145 }
146
dp83867_set_rx_clk_delay(ENET_Type * ptr)147 void dp83867_set_rx_clk_delay(ENET_Type *ptr)
148 {
149 uint16_t para = 0;
150
151 para = dp83867_phy_read_ext(ptr, PHY_ADDR, DP83867_EXT_REG_RGMIICTL);
152 dp83867_phy_write_ext(ptr, PHY_ADDR, DP83867_EXT_REG_RGMIICTL, para | 1);
153 }
154
dp83867_enable_crc_check(ENET_Type * ptr)155 void dp83867_enable_crc_check(ENET_Type *ptr)
156 {
157 uint16_t para = 0;
158
159 para = dp83867_phy_read_ext(ptr, PHY_ADDR, DP83867_EXT_REG_RXFCFG);
160 dp83867_phy_write_ext(ptr, PHY_ADDR, DP83867_EXT_REG_RXFCFG, para | (1 << 7));
161 }
162
dp83867_enable_rmii_inf(ENET_Type * ptr)163 void dp83867_enable_rmii_inf(ENET_Type *ptr)
164 {
165 uint16_t para = 0;
166
167 para = dp83867_phy_read_ext(ptr, PHY_ADDR, DP83867_EXT_REG_RGMIICTL);
168 dp83867_phy_write_ext(ptr, PHY_ADDR, DP83867_EXT_REG_RGMIICTL, para | (1 << 7));
169 }
170