1 /*
2 * Copyright (c) 2024 Renesas Electronics Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT renesas_ra_ethernet
8
9 /* Renesas RA ethernet driver */
10
11 #define LOG_MODULE_NAME eth_ra_ethernet
12 #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
13
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
16
17 #include <soc.h>
18 #include <errno.h>
19 #include <zephyr/device.h>
20 #include <zephyr/irq.h>
21 #include <zephyr/net/net_pkt.h>
22 #include <zephyr/net/ethernet.h>
23 #include <ethernet/eth_stats.h>
24 #include <zephyr/drivers/pinctrl.h>
25 #include <zephyr/net/phy.h>
26 #include "r_ether.h"
27 #include "r_ether_phy.h"
28
29 /* Additional configurations to use with hal_renesas */
30 #define ETHER_DEFAULT NULL
31 #define ETHER_CHANNEL0 0
32 #define ETHER_BUF_SIZE 1536
33 #define ETHER_PADDING_OFFSET 1
34 #define ETHER_BROADCAST_FILTER 0
35 #define ETHER_TOTAL_BUF_NUM (CONFIG_ETH_RENESAS_TX_BUF_NUM + CONFIG_ETH_RENESAS_RX_BUF_NUM)
36 #define ETHER_EE_RECEIVE_EVENT_MASK (0x01070000)
37
38 void ether_eint_isr(void);
39 void renesas_ra_eth_callback(ether_callback_args_t *p_args);
40 static void renesas_ra_eth_buffer_init(const struct device *dev);
41
42 extern void ether_init_buffers(ether_instance_ctrl_t *const p_instance_ctrl);
43 extern void ether_configure_mac(ether_instance_ctrl_t *const p_instance_ctrl,
44 const uint8_t mac_addr[], const uint8_t mode);
45 extern void ether_do_link(ether_instance_ctrl_t *const p_instance_ctrl, const uint8_t mode);
46
47 uint8_t g_ether0_mac_address[6] = DT_INST_PROP(0, local_mac_address);
48 struct renesas_ra_eth_context {
49 struct net_if *iface;
50 uint8_t mac[6];
51
52 K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ETH_RA_RX_THREAD_STACK_SIZE);
53 struct k_thread thread;
54 struct k_sem rx_sem;
55 ether_instance_ctrl_t ctrl;
56 /** pinctrl configs */
57 const struct pinctrl_dev_config *pcfg;
58 };
59
60 struct renesas_ra_eth_config {
61 const ether_cfg_t *p_cfg;
62 const struct device *phy_dev;
63 };
64
65 #define DECLARE_ETHER_RX_BUFFER(idx, _) \
66 static __aligned(32) uint8_t g_ether0_ether_rx_buffer##idx[ETHER_BUF_SIZE];
67
68 #define DECLARE_ETHER_TX_BUFFER(idx, _) \
69 static __aligned(32) uint8_t g_ether0_ether_tx_buffer##idx[ETHER_BUF_SIZE];
70
71 #define DECLARE_ETHER_RX_BUFFER_PTR(idx, _) (uint8_t *)&g_ether0_ether_rx_buffer##idx[0]
72
73 #define DECLARE_ETHER_TX_BUFFER_PTR(idx, _) (uint8_t *)&g_ether0_ether_tx_buffer##idx[0]
74
75 LISTIFY(CONFIG_ETH_RENESAS_RX_BUF_NUM, DECLARE_ETHER_RX_BUFFER, (;));
76 LISTIFY(CONFIG_ETH_RENESAS_TX_BUF_NUM, DECLARE_ETHER_TX_BUFFER, (;));
77
78 uint8_t *pp_g_ether0_ether_buffers[ETHER_TOTAL_BUF_NUM] = {
79 LISTIFY(CONFIG_ETH_RENESAS_RX_BUF_NUM, DECLARE_ETHER_RX_BUFFER_PTR, (,)),
80 LISTIFY(CONFIG_ETH_RENESAS_TX_BUF_NUM, DECLARE_ETHER_TX_BUFFER_PTR, (,))
81 };
82
83 static __aligned(16) ether_instance_descriptor_t
84 g_ether0_tx_descriptors[CONFIG_ETH_RENESAS_TX_BUF_NUM];
85 static __aligned(16) ether_instance_descriptor_t
86 g_ether0_rx_descriptors[CONFIG_ETH_RENESAS_RX_BUF_NUM];
87
88 const ether_extended_cfg_t g_ether0_extended_cfg_t = {
89 .p_rx_descriptors = g_ether0_rx_descriptors,
90 .p_tx_descriptors = g_ether0_tx_descriptors,
91 };
92
93 /* Dummy configuration for ether phy as hal layer require */
94 const ether_phy_extended_cfg_t g_ether_phy0_extended_cfg = {
95 .p_target_init = ETHER_DEFAULT, .p_target_link_partner_ability_get = ETHER_DEFAULT};
96
97 const ether_phy_cfg_t g_ether_phy0_cfg;
98
99 ether_phy_instance_ctrl_t g_ether_phy0_ctrl;
100
101 const ether_phy_instance_t g_ether_phy0 = {.p_ctrl = &g_ether_phy0_ctrl,
102 .p_cfg = &g_ether_phy0_cfg,
103 .p_api = &g_ether_phy_on_ether_phy};
104
105 const ether_cfg_t g_ether0_cfg = {
106 .channel = ETHER_CHANNEL0,
107 .zerocopy = ETHER_ZEROCOPY_DISABLE,
108 .multicast = ETHER_MULTICAST_ENABLE,
109 .promiscuous = ETHER_PROMISCUOUS_DISABLE,
110 .flow_control = ETHER_FLOW_CONTROL_DISABLE,
111 .padding = ETHER_PADDING_DISABLE,
112 .padding_offset = ETHER_PADDING_OFFSET,
113 .broadcast_filter = ETHER_BROADCAST_FILTER,
114 .p_mac_address = g_ether0_mac_address,
115 .num_tx_descriptors = CONFIG_ETH_RENESAS_TX_BUF_NUM,
116 .num_rx_descriptors = CONFIG_ETH_RENESAS_RX_BUF_NUM,
117 .pp_ether_buffers = pp_g_ether0_ether_buffers,
118 .ether_buffer_size = ETHER_BUF_SIZE,
119 .irq = DT_INST_IRQN(0),
120 .interrupt_priority = DT_INST_IRQ(0, priority),
121 .p_callback = ETHER_DEFAULT,
122 .p_ether_phy_instance = &g_ether_phy0,
123 .p_context = ETHER_DEFAULT,
124 .p_extend = &g_ether0_extended_cfg_t,
125 };
126
127 static struct renesas_ra_eth_config eth_0_config = {
128 .p_cfg = &g_ether0_cfg, .phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, phy_handle))};
129
130 /* Driver functions */
renesas_ra_eth_get_capabilities(const struct device * dev)131 static enum ethernet_hw_caps renesas_ra_eth_get_capabilities(const struct device *dev)
132 {
133 ARG_UNUSED(dev);
134
135 return ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T;
136 }
137
renesas_ra_eth_callback(ether_callback_args_t * p_args)138 void renesas_ra_eth_callback(ether_callback_args_t *p_args)
139 {
140 struct device *dev = (struct device *)p_args->p_context;
141 struct renesas_ra_eth_context *ctx = dev->data;
142
143 if (p_args->status_eesr & ETHER_EE_RECEIVE_EVENT_MASK) {
144 k_sem_give(&ctx->rx_sem);
145 }
146 }
147
renesas_ra_eth_buffer_init(const struct device * dev)148 static void renesas_ra_eth_buffer_init(const struct device *dev)
149 {
150 struct renesas_ra_eth_context *ctx = dev->data;
151 ether_extended_cfg_t *p_ether_extended_cfg =
152 (ether_extended_cfg_t *)ctx->ctrl.p_ether_cfg->p_extend;
153 /* Initialize the transmit and receive descriptor */
154 memset(p_ether_extended_cfg->p_rx_descriptors, 0x00,
155 sizeof(ether_instance_descriptor_t) * ctx->ctrl.p_ether_cfg->num_rx_descriptors);
156 memset(p_ether_extended_cfg->p_tx_descriptors, 0x00,
157 sizeof(ether_instance_descriptor_t) * ctx->ctrl.p_ether_cfg->num_tx_descriptors);
158
159 ether_init_buffers(&ctx->ctrl);
160 }
161
phy_link_state_changed(const struct device * pdev,struct phy_link_state * state,void * user_data)162 static void phy_link_state_changed(const struct device *pdev, struct phy_link_state *state,
163 void *user_data)
164 {
165 const struct device *dev = (struct device *)user_data;
166 struct renesas_ra_eth_context *ctx = dev->data;
167 R_ETHERC0_Type *p_reg_etherc;
168
169 p_reg_etherc = (R_ETHERC0_Type *)ctx->ctrl.p_reg_etherc;
170
171 ARG_UNUSED(pdev);
172
173 if (state->is_up) {
174
175 ctx->ctrl.link_change = ETHER_LINK_CHANGE_LINK_UP;
176 ctx->ctrl.previous_link_status = ETHER_PREVIOUS_LINK_STATUS_UP;
177
178 renesas_ra_eth_buffer_init(dev);
179
180 /*
181 * ETHERC and EDMAC are set after ETHERC and EDMAC are reset in software
182 * and sending and receiving is permitted.
183 */
184 ether_configure_mac(&ctx->ctrl, ctx->ctrl.p_ether_cfg->p_mac_address, 0);
185
186 switch (state->speed) {
187 /* Half duplex link */
188 case LINK_HALF_100BASE_T: {
189 ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_100H;
190 break;
191 }
192
193 case LINK_HALF_10BASE_T: {
194 ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_10H;
195 break;
196 }
197
198 /* Full duplex link */
199 case LINK_FULL_100BASE_T: {
200 ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_100F;
201 break;
202 }
203
204 case LINK_FULL_10BASE_T: {
205 ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_10F;
206 break;
207 }
208
209 default: {
210 ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_100F;
211 break;
212 }
213 }
214
215 ether_do_link(&ctx->ctrl, 0);
216 ctx->ctrl.link_change = ETHER_LINK_CHANGE_LINK_UP;
217 ctx->ctrl.previous_link_status = ETHER_PREVIOUS_LINK_STATUS_UP;
218 ctx->ctrl.link_establish_status = ETHER_LINK_ESTABLISH_STATUS_UP;
219 LOG_DBG("Link up");
220 net_eth_carrier_on(ctx->iface);
221 } else {
222 ctx->ctrl.link_change = ETHER_LINK_CHANGE_LINK_DOWN;
223 ctx->ctrl.previous_link_status = ETHER_PREVIOUS_LINK_STATUS_DOWN;
224 ctx->ctrl.link_establish_status = ETHER_LINK_ESTABLISH_STATUS_DOWN;
225 net_eth_carrier_off(ctx->iface);
226 }
227 }
228
renesas_ra_eth_initialize(struct net_if * iface)229 static void renesas_ra_eth_initialize(struct net_if *iface)
230 {
231 fsp_err_t err;
232 const struct device *dev = net_if_get_device(iface);
233 struct renesas_ra_eth_context *ctx = dev->data;
234 const struct renesas_ra_eth_config *cfg = dev->config;
235 const char *phy_connection_type = DT_INST_PROP_OR(0, phy_connection_type, "rmii");
236
237 LOG_DBG("eth_initialize");
238
239 net_if_set_link_addr(iface, ctx->mac, sizeof(ctx->mac), NET_LINK_ETHERNET);
240
241 if (ctx->iface == NULL) {
242 ctx->iface = iface;
243 }
244
245 ethernet_init(iface);
246
247 R_PMISC->PFENET = (uint8_t)(0x0 << R_PMISC_PFENET_PHYMODE0_Pos);
248
249 if (strstr(phy_connection_type, "mii") != NULL) {
250 /* Configure pins for MII or RMII. Set PHYMODE0 if MII is selected. */
251 R_PMISC->PFENET = (uint8_t)(0x1 << R_PMISC_PFENET_PHYMODE0_Pos);
252 } else {
253 LOG_ERR("Failed to init ether - phy-connection-type not support");
254 }
255
256 err = R_ETHER_Open(&ctx->ctrl, cfg->p_cfg);
257
258 if (err != FSP_SUCCESS) {
259 LOG_ERR("Failed to init ether - R_ETHER_Open fail");
260 }
261
262 err = R_ETHER_CallbackSet(&ctx->ctrl, renesas_ra_eth_callback, dev, NULL);
263
264 if (err != FSP_SUCCESS) {
265 LOG_ERR("Failed to init ether - R_ETHER_CallbackSet fail");
266 }
267
268 phy_link_callback_set(cfg->phy_dev, &phy_link_state_changed, (void *)dev);
269 /* Do not start the interface until PHY link is up */
270 net_if_carrier_off(ctx->iface);
271 }
272
renesas_ra_eth_tx(const struct device * dev,struct net_pkt * pkt)273 static int renesas_ra_eth_tx(const struct device *dev, struct net_pkt *pkt)
274 {
275 fsp_err_t err = FSP_SUCCESS;
276 struct renesas_ra_eth_context *ctx = dev->data;
277 uint16_t len = net_pkt_get_len(pkt);
278 static uint8_t tx_buf[NET_ETH_MAX_FRAME_SIZE];
279
280 if (net_pkt_read(pkt, tx_buf, len)) {
281 goto error;
282 }
283
284 /* Check if packet length is less than minimum Ethernet frame size */
285 if (len < NET_ETH_MINIMAL_FRAME_SIZE) {
286 /* Add padding to meet the minimum frame size */
287 memset(tx_buf + len, 0, NET_ETH_MINIMAL_FRAME_SIZE - len);
288 len = NET_ETH_MINIMAL_FRAME_SIZE;
289 }
290
291 err = R_ETHER_Write(&ctx->ctrl, tx_buf, len);
292 if (err != FSP_SUCCESS) {
293 goto error;
294 }
295
296 return 0;
297
298 error:
299 LOG_ERR("Writing to FIFO failed");
300 return -1;
301 }
302
303 static const struct ethernet_api api_funcs = {
304 .iface_api.init = renesas_ra_eth_initialize,
305 .get_capabilities = renesas_ra_eth_get_capabilities,
306 .send = renesas_ra_eth_tx,
307 };
308
renesas_ra_eth_isr(const struct device * dev)309 static void renesas_ra_eth_isr(const struct device *dev)
310 {
311 ARG_UNUSED(dev);
312 ether_eint_isr();
313 }
314
renesas_ra_eth_rx(const struct device * dev)315 static struct net_pkt *renesas_ra_eth_rx(const struct device *dev)
316 {
317 fsp_err_t err = FSP_SUCCESS;
318 struct renesas_ra_eth_context *ctx;
319 struct net_pkt *pkt = NULL;
320 uint32_t len = 0;
321 static uint8_t rx_buf[NET_ETH_MAX_FRAME_SIZE];
322
323 __ASSERT_NO_MSG(dev != NULL);
324 ctx = dev->data;
325 __ASSERT_NO_MSG(ctx != NULL);
326
327 err = R_ETHER_Read(&ctx->ctrl, rx_buf, &len);
328 if ((err != FSP_SUCCESS) && (err != FSP_ERR_ETHER_ERROR_NO_DATA)) {
329 LOG_ERR("Failed to read packets");
330 goto out;
331 }
332
333 pkt = net_pkt_rx_alloc_with_buffer(ctx->iface, len, AF_UNSPEC, 0, K_MSEC(100));
334 if (!pkt) {
335 LOG_ERR("Failed to obtain RX buffer");
336 goto out;
337 }
338
339 if (net_pkt_write(pkt, rx_buf, len)) {
340 LOG_ERR("Failed to append RX buffer to context buffer");
341 net_pkt_unref(pkt);
342 pkt = NULL;
343 goto out;
344 }
345
346 out:
347 if (pkt == NULL) {
348 eth_stats_update_errors_rx(ctx->iface);
349 }
350
351 return pkt;
352 }
353
renesas_ra_eth_thread(void * p1,void * p2,void * p3)354 static void renesas_ra_eth_thread(void *p1, void *p2, void *p3)
355 {
356 ARG_UNUSED(p2);
357 ARG_UNUSED(p3);
358
359 const struct device *dev = p1;
360 struct net_if *iface;
361 int res;
362 struct net_pkt *pkt = NULL;
363 struct renesas_ra_eth_context *ctx = dev->data;
364
365 while (true) {
366 res = k_sem_take(&ctx->rx_sem, K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
367 if (res == 0) {
368 pkt = renesas_ra_eth_rx(dev);
369
370 if (pkt != NULL) {
371 iface = net_pkt_iface(pkt);
372 res = net_recv_data(iface, pkt);
373 if (res < 0) {
374 net_pkt_unref(pkt);
375 }
376 }
377 }
378 }
379 }
380
381 #define ELC_EVENT_EDMAC_EINT(channel) ELC_EVENT_EDMAC##channel##_EINT
382
383 /* Bindings to the platform */
renesas_ra_eth_init(const struct device * dev)384 int renesas_ra_eth_init(const struct device *dev)
385 {
386 struct renesas_ra_eth_context *ctx = dev->data;
387
388 R_ICU->IELSR[DT_INST_IRQN(0)] = ELC_EVENT_EDMAC_EINT(0);
389
390 IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), renesas_ra_eth_isr,
391 DEVICE_DT_INST_GET(0), 0);
392
393 k_thread_create(&ctx->thread, ctx->thread_stack, CONFIG_ETH_RA_RX_THREAD_STACK_SIZE,
394 renesas_ra_eth_thread, (void *)dev, NULL, NULL,
395 K_PRIO_COOP(CONFIG_ETH_RA_RX_THREAD_PRIORITY), 0, K_NO_WAIT);
396
397 irq_enable(DT_INST_IRQN(0));
398
399 return 0;
400 }
401
402 #define ETHER_RA_INIT(idx) \
403 PINCTRL_DT_INST_DEFINE(0); \
404 static struct renesas_ra_eth_context eth_0_context = { \
405 .mac = DT_INST_PROP(0, local_mac_address), \
406 .rx_sem = Z_SEM_INITIALIZER(eth_0_context.rx_sem, 0, UINT_MAX), \
407 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), \
408 }; \
409 \
410 ETH_NET_DEVICE_DT_INST_DEFINE(0, renesas_ra_eth_init, NULL, ð_0_context, ð_0_config, \
411 CONFIG_ETH_INIT_PRIORITY, &api_funcs, NET_ETH_MTU /*MTU*/);
412
413 DT_INST_FOREACH_STATUS_OKAY(ETHER_RA_INIT);
414