1 /*
2 * Copyright (c) 2022 HPMicro
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include "lwip/tcpip.h"
18 #include "ohos_init.h"
19 #include "hpm_lwip.h"
20 #include "ethernetif.h"
21 #include "lwip/tcpip.h"
22 #include <los_task.h>
23
24
25 static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_DESC_ADDR_ALIGNMENT)
26 __RW enet_rx_desc_t rxDescTab0[ENET_RX_BUFF_COUNT] ; /* Ethernet Rx DMA Descriptor */
27
28 static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_DESC_ADDR_ALIGNMENT)
29 __RW enet_tx_desc_t txDescTab0[ENET_TX_BUFF_COUNT] ; /* Ethernet Tx DMA Descriptor */
30
31 static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_BUFF_ADDR_ALIGNMENT)
32 __RW uint8_t rxBuff0[ENET_RX_BUFF_COUNT][ENET_RX_BUFF_SIZE]; /* Ethernet Receive Buffer */
33
34 static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_BUFF_ADDR_ALIGNMENT)
35 __RW uint8_t txBuff0[ENET_TX_BUFF_COUNT][ENET_TX_BUFF_SIZE]; /* Ethernet Transmit Buffer */
36
37 static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_DESC_ADDR_ALIGNMENT)
38 __RW enet_rx_desc_t rxDescTab1[ENET_RX_BUFF_COUNT] ; /* Ethernet Rx DMA Descriptor */
39
40 static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_DESC_ADDR_ALIGNMENT)
41 __RW enet_tx_desc_t txDescTab1[ENET_TX_BUFF_COUNT] ; /* Ethernet Tx DMA Descriptor */
42
43 static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_BUFF_ADDR_ALIGNMENT)
44 __RW uint8_t rxBuff1[ENET_RX_BUFF_COUNT][ENET_RX_BUFF_SIZE]; /* Ethernet Receive Buffer */
45
46 static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_BUFF_ADDR_ALIGNMENT)
47 __RW uint8_t txBuff1[ENET_TX_BUFF_COUNT][ENET_TX_BUFF_SIZE]; /* Ethernet Transmit Buffer */
48
49
50 struct HpmEnetDevice enetDev[1] = {
51 [0] = {
52 .isEnable = 1,
53 .isDefault = 1,
54 .name = "eth",
55 .base = BOARD_ENET_RMII,
56 .irqNum = IRQn_ENET0,
57 .infType = enet_inf_rmii,
58 .macAddr = {0x98, 0x2C, 0xBC, 0xB1, 0x9F, 0x17},
59 .ip = {10, 10, 10, 224},
60 .netmask = {255, 255, 255, 0},
61 .gw = {10, 10, 10, 1},
62 .desc = {
63 .tx_desc_list_head = txDescTab1,
64 .rx_desc_list_head = rxDescTab1,
65 .tx_buff_cfg = {
66 .buffer = (uint32_t)txBuff1,
67 .count = ENET_TX_BUFF_COUNT,
68 .size = ENET_TX_BUFF_SIZE,
69 },
70 .rx_buff_cfg = {
71 .buffer = (uint32_t)rxBuff1,
72 .count = ENET_RX_BUFF_COUNT,
73 .size = ENET_RX_BUFF_SIZE,
74 },
75 },
76 },
77 };
78
79
enetDevInit(struct HpmEnetDevice * dev)80 void enetDevInit(struct HpmEnetDevice *dev)
81 {
82 if (!dev->isEnable) {
83 return 0;
84 }
85
86 board_init_enet_pins(dev->base);
87
88 if (dev->infType == enet_inf_rmii) {
89 board_init_enet_rmii_reference_clock(dev->base, BOARD_ENET_RMII_INT_REF_CLK);
90 }
91
92 memset(dev->desc.rx_desc_list_head, 0x00, sizeof(enet_rx_desc_t) * dev->desc.rx_buff_cfg.count);
93 memset(dev->desc.tx_desc_list_head, 0x00, sizeof(enet_tx_desc_t) * dev->desc.tx_buff_cfg.count);
94
95 enet_mac_config_t macCfg;
96 macCfg.mac_addr_high[0] = dev->macAddr[5];
97 macCfg.mac_addr_high[0] <<= 8;
98 macCfg.mac_addr_high[0] |= dev->macAddr[4];
99
100 macCfg.mac_addr_low[0] = dev->macAddr[3];
101 macCfg.mac_addr_low[0] <<= 8;
102 macCfg.mac_addr_low[0] |= dev->macAddr[2];
103 macCfg.mac_addr_low[0] <<= 8;
104 macCfg.mac_addr_low[0] |= dev->macAddr[1];
105 macCfg.mac_addr_low[0] <<= 8;
106 macCfg.mac_addr_low[0] |= dev->macAddr[0];
107 macCfg.valid_max_count = 1;
108
109 /* Set DMA PBL */
110 macCfg.dma_pbl = enet_pbl_32;
111 /* Set SARC */
112 macCfg.sarc = enet_sarc_replace_mac0;
113 macCfg.valid_max_count = 1;
114
115 enet_int_config_t int_config = {.int_enable = 0, .int_mask = 0};
116
117 /* Set the interrupt enable mask */
118 int_config.int_enable = enet_normal_int_sum_en /* Enable normal interrupt summary */
119 | enet_receive_int_en; /* Enable receive interrupt */
120 int_config.int_mask = enet_rgsmii_int_mask; /* Disable RGSMII interrupt */
121 int_config.mmc_intr_mask_rx = 0x03ffffff; /* Disable all mmc rx interrupt events */
122 int_config.mmc_intr_mask_tx = 0x03ffffff; /* Disable all mmc tx interrupt events */
123
124 enet_tx_control_config_t enet_tx_control_config;
125
126 /*Get a default control config for tx descriptor */
127 enet_get_default_tx_control_config(dev->base, &enet_tx_control_config);
128
129 /* Set the control config for tx descriptor */
130 memcpy(&dev->desc.tx_control_config, &enet_tx_control_config, sizeof(enet_tx_control_config_t));
131
132 /* Initialize enet controller */
133 enet_controller_init(dev->base, dev->infType, &dev->desc, &macCfg, &int_config);
134 /* Disable LPI interrupt */
135 enet_disable_lpi_interrupt(dev->base);
136
137 if (dev->infType == enet_inf_rgmii) {
138 rtl8211_config_t phyConfig;
139 rtl8211_reset(dev->base);
140 rtl8211_basic_mode_default_config(dev->base, &phyConfig);
141 rtl8211_basic_mode_init(dev->base, &phyConfig);
142 }
143
144 if (dev->infType == enet_inf_rmii) {
145 rtl8201_config_t phyConfig;
146 rtl8201_reset(dev->base);
147 rtl8201_basic_mode_default_config(dev->base, &phyConfig);
148 rtl8201_basic_mode_init(dev->base, &phyConfig);
149 }
150
151 ip_addr_t ipaddr;
152 ip_addr_t netmask;
153 ip_addr_t gw;
154
155 IP_ADDR4(&ipaddr, dev->ip[0], dev->ip[1], dev->ip[2], dev->ip[3]);
156 IP_ADDR4(&netmask, dev->netmask[0], dev->netmask[1], dev->netmask[2], dev->netmask[3]);
157 IP_ADDR4(&gw, dev->gw[0], dev->gw[1], dev->gw[2], dev->gw[3]);
158
159 netif_add(&dev->netif, &ipaddr, &netmask, &gw, dev, ethernetif_init, tcpip_input);
160
161 if (dev->isDefault) {
162 netif_set_default(&dev->netif);
163 }
164
165 netif_set_up(&dev->netif);
166 }
167
168 void ethernetif_phy_adaptive_thread_start(void);
169
HpmLwipInit(void)170 void HpmLwipInit(void)
171 {
172 printf("HpmLwipInit...\n");
173
174 tcpip_init(NULL, NULL);
175
176 enetDevInit(&enetDev[0]);
177 ethernetif_phy_adaptive_thread_start();
178 }
179
enet_self_adaptive_port_speed(struct HpmEnetDevice * dev)180 void enet_self_adaptive_port_speed(struct HpmEnetDevice *dev)
181 {
182 enet_phy_status_t status = {0};
183 enet_phy_status_t *last_status = &dev->last_status;
184
185 enet_line_speed_t line_speed[] = {enet_line_speed_10mbps, enet_line_speed_100mbps, enet_line_speed_1000mbps};
186 char *speed_str[] = {"10Mbps", "100Mbps", "1000Mbps"};
187 char *duplex_str[] = {"Half duplex", "Full duplex"};
188
189 if (!dev->isEnable)
190 return;
191
192 if (dev->infType == enet_inf_rmii)
193 rtl8201_get_phy_status(dev->base, &status);
194
195 if (memcmp(last_status, &status, sizeof(enet_phy_status_t)) != 0) {
196 memcpy(last_status, &status, sizeof(enet_phy_status_t));
197 if (status.enet_phy_link) {
198 printf("Link Status: Up\n");
199 printf("Link Speed: %s\n", speed_str[status.enet_phy_speed]);
200 printf("Link Duplex: %s\n", duplex_str[status.enet_phy_duplex]);
201 enet_set_line_speed(dev->base, line_speed[status.enet_phy_speed]);
202 enet_set_duplex_mode(dev->base, status.enet_phy_duplex);
203 } else {
204 printf("Link Status: Down\n");
205 }
206 }
207 }
208
ethernetif_phy_adaptive_thread(UINT32 arg)209 static VOID *ethernetif_phy_adaptive_thread(UINT32 arg)
210 {
211 struct netif *netif = (struct netif *)arg;
212 struct HpmEnetDevice *devs = (struct netif *)arg;
213 printf("ethernetif_adaptive_thread run...\n");
214
215 while (1) {
216 enet_self_adaptive_port_speed(&devs[0]);
217 sleep(1);
218 }
219 }
220
ethernetif_phy_adaptive_thread_start(void)221 void ethernetif_phy_adaptive_thread_start(void)
222 {
223 UINT32 taskID = LOS_ERRNO_TSK_ID_INVALID;
224 UINT32 ret;
225 TSK_INIT_PARAM_S task = {0};
226 /* Create host Task */
227 task.pfnTaskEntry = (TSK_ENTRY_FUNC)ethernetif_phy_adaptive_thread;
228 task.uwStackSize = 4096;
229 task.pcName = "phy";
230 task.usTaskPrio = 3;
231 task.uwArg = (UINTPTR)enetDev;
232 task.uwResved = LOS_TASK_STATUS_DETACHED;
233 ret = LOS_TaskCreate(&taskID, &task);
234 if (ret != LOS_OK) {
235 LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: LOS_TaskCreate error %u\n", ret));
236 return -1;
237 }
238 }
239
240 APP_SERVICE_INIT(HpmLwipInit);
241