diff --git a/boards/renesas/ek_ra8d1/Kconfig.defconfig b/boards/renesas/ek_ra8d1/Kconfig.defconfig new file mode 100644 index 00000000000000..d99c0d945ba15b --- /dev/null +++ b/boards/renesas/ek_ra8d1/Kconfig.defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_EK_RA8D1 + +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + +endif # BOARD_EK_RA8D1 diff --git a/boards/renesas/ek_ra8d1/doc/index.rst b/boards/renesas/ek_ra8d1/doc/index.rst index 20c887373c8ee3..bed54638bd279c 100644 --- a/boards/renesas/ek_ra8d1/doc/index.rst +++ b/boards/renesas/ek_ra8d1/doc/index.rst @@ -112,6 +112,18 @@ The below features are currently supported on Zephyr OS for EK-RA8D1 board: +--------------+------------+------------------+ | I2C | on-chip | i2c | +--------------+------------+------------------+ +| ETHERNET | on-chip | ethernet | ++--------------+------------+------------------+ + +**Note:** for using Ethernet on RA8D1 board please set switch SW1 as following configuration: + ++-------------+-------------+--------------+------------+------------+------------+-------------+-----------+ +| SW1-1 PMOD1 | SW1-2 TRACE | SW1-3 CAMERA | SW1-4 ETHA | SW1-5 ETHB | SW1-6 GLCD | SW1-7 SDRAM | SW1-8 I3C | ++-------------+-------------+--------------+------------+------------+------------+-------------+-----------+ +| OFF | OFF | OFF | OFF | ON | OFF | OFF | OFF | ++-------------+-------------+--------------+------------+------------+------------+-------------+-----------+ + +**CAUTION:** Do not enable SW1-4 and SW1-5 together Other hardware features are currently not supported by the port. diff --git a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi index b450f9c3393192..a96d4d225f2113 100644 --- a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi +++ b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi @@ -19,10 +19,10 @@ spi0_default: spi0_default { group1 { /* MISO MOSI RSPCK SSL */ - psels = , - , - , - ; + psels = , + , + , + ; }; }; @@ -53,4 +53,21 @@ drive-strength = "medium"; }; }; + + ether_default: ether_default { + group1 { + psels = , /* ET0_MDC */ + , /* ET0_MDIO */ + , /* ET0_LINKSTA */ + , /* RMII0_TXD_EN_B */ + , /* RMII0_TXD1_BR */ + , /* RMII0_TXD0_B */ + , /* REF50CK0_B */ + , /* RMII0_RXD0_B */ + , /* RMII0_RXD1_B */ + , /* RMII0_RX_ER_B */ + ; /* RMII0_CRS_DV_B */ + drive-strength = "high"; + }; + }; }; diff --git a/boards/renesas/ek_ra8d1/ek_ra8d1.dts b/boards/renesas/ek_ra8d1/ek_ra8d1.dts index 82eb5f3b43e5bb..6ef2af8b46bd40 100644 --- a/boards/renesas/ek_ra8d1/ek_ra8d1.dts +++ b/boards/renesas/ek_ra8d1/ek_ra8d1.dts @@ -160,3 +160,21 @@ pinctrl-0 = <&iic1_default>; pinctrl-names = "default"; }; + +ð { + local-mac-address = [74 90 50 B0 5D E9]; + status = "okay"; + phy-handle = <&phy>; +}; + +&mdio { + pinctrl-0 = <ðer_default>; + pinctrl-names = "default"; + status = "okay"; + + phy: ethernet-phy@5 { + compatible = "ethernet-phy"; + reg = <5>; + status = "okay"; + }; +}; diff --git a/boards/renesas/ek_ra8m1/Kconfig.defconfig b/boards/renesas/ek_ra8m1/Kconfig.defconfig new file mode 100644 index 00000000000000..7f10ef8232f438 --- /dev/null +++ b/boards/renesas/ek_ra8m1/Kconfig.defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_EK_RA8M1 + +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + +endif # BOARD_EK_RA8M1 diff --git a/boards/renesas/ek_ra8m1/doc/index.rst b/boards/renesas/ek_ra8m1/doc/index.rst index 09d36befe02dcd..d62ed9c3937ed6 100644 --- a/boards/renesas/ek_ra8m1/doc/index.rst +++ b/boards/renesas/ek_ra8m1/doc/index.rst @@ -112,6 +112,10 @@ The below features are currently supported on Zephyr OS for EK-RA8M1 board: +-----------+------------+----------------------+ | CAN | on-chip | canfd | +-----------+------------+----------------------+ +| ETHERNET | on-chip | ethernet | ++-----------+------------+----------------------+ + +**Note:** For using Ethernet module on EK-RA8M1, remove jumper J61 to enable Ethernet B Other hardware features are currently not supported by the port. diff --git a/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi b/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi index e1cf5623feccf3..cac279265a1331 100644 --- a/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi +++ b/boards/renesas/ek_ra8m1/ek_ra8m1-pinctrl.dtsi @@ -97,4 +97,21 @@ drive-strength = "high"; }; }; + + ether_default: ether_default { + group1 { + psels = , /* ET0_MDC */ + , /* ET0_MDIO */ + , /* ET0_LINKSTA */ + , /* RMII0_TXD_EN_B */ + , /* RMII0_TXD1_BR */ + , /* RMII0_TXD0_B */ + , /* REF50CK0_B */ + , /* RMII0_RXD0_B */ + , /* RMII0_RXD1_B */ + , /* RMII0_RX_ER_B */ + ; /* RMII0_CRS_DV_B */ + drive-strength = "high"; + }; + }; }; diff --git a/boards/renesas/ek_ra8m1/ek_ra8m1.dts b/boards/renesas/ek_ra8m1/ek_ra8m1.dts index 354e53298f8a1b..4b36ca5c9b6d9c 100644 --- a/boards/renesas/ek_ra8m1/ek_ra8m1.dts +++ b/boards/renesas/ek_ra8m1/ek_ra8m1.dts @@ -285,3 +285,21 @@ pmod2_serial: &uart2 {}; pmod_serial: &pmod1_serial {}; pmod_header: &pmod1_header {}; + +ð { + local-mac-address = [74 90 50 B0 6D 5A]; + status = "okay"; + phy-handle = <&phy>; +}; + +&mdio { + pinctrl-0 = <ðer_default>; + pinctrl-names = "default"; + status = "okay"; + + phy: ethernet-phy@5 { + compatible = "ethernet-phy"; + reg = <5>; + status = "okay"; + }; +}; diff --git a/boards/renesas/mck_ra8t1/Kconfig.defconfig b/boards/renesas/mck_ra8t1/Kconfig.defconfig new file mode 100644 index 00000000000000..37c1586dbb1ccb --- /dev/null +++ b/boards/renesas/mck_ra8t1/Kconfig.defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_MCK_RA8T1 + +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + +endif # BOARD_MCK_RA8T1 diff --git a/boards/renesas/mck_ra8t1/doc/index.rst b/boards/renesas/mck_ra8t1/doc/index.rst index eeda35fceaf011..999767e0bc2b8a 100644 --- a/boards/renesas/mck_ra8t1/doc/index.rst +++ b/boards/renesas/mck_ra8t1/doc/index.rst @@ -110,6 +110,8 @@ The below features are currently supported on Zephyr OS for MCB-RA8T1 board: +--------------+------------+----------------------+ | I2C | on-chip | i2c | +--------------+------------+----------------------+ +| ETHERNET | on-chip | ethernet | ++--------------+------------+----------------------+ Other hardware features are currently not supported by the port. diff --git a/boards/renesas/mck_ra8t1/mck_ra8t1-pinctrl.dtsi b/boards/renesas/mck_ra8t1/mck_ra8t1-pinctrl.dtsi index 63903204f44818..2f13bbbf4c242f 100644 --- a/boards/renesas/mck_ra8t1/mck_ra8t1-pinctrl.dtsi +++ b/boards/renesas/mck_ra8t1/mck_ra8t1-pinctrl.dtsi @@ -53,4 +53,21 @@ drive-strength = "medium"; }; }; + + ether_default: ether_default { + group1 { + psels = , /* ET0_MDC */ + , /* ET0_MDIO */ + , /* ET0_LINKSTA */ + , /* RMII0_TXD_EN_B */ + , /* RMII0_TXD1_BR */ + , /* RMII0_TXD0_B */ + , /* REF50CK0_B */ + , /* RMII0_RXD0_B */ + , /* RMII0_RXD1_B */ + , /* RMII0_RX_ER_B */ + ; /* RMII0_CRS_DV_B */ + drive-strength = "high"; + }; + }; }; diff --git a/boards/renesas/mck_ra8t1/mck_ra8t1.dts b/boards/renesas/mck_ra8t1/mck_ra8t1.dts index 19f46abcddce42..a0e4387e60c178 100644 --- a/boards/renesas/mck_ra8t1/mck_ra8t1.dts +++ b/boards/renesas/mck_ra8t1/mck_ra8t1.dts @@ -153,3 +153,21 @@ pinctrl-0 = <&iic1_default>; pinctrl-names = "default"; }; + +ð { + local-mac-address = [74 90 50 6D 81 75]; + status = "okay"; + phy-handle = <&phy>; +}; + +&mdio { + pinctrl-0 = <ðer_default>; + pinctrl-names = "default"; + status = "okay"; + + phy: ethernet-phy@5 { + compatible = "ethernet-phy"; + reg = <5>; + status = "okay"; + }; +}; diff --git a/drivers/ethernet/CMakeLists.txt b/drivers/ethernet/CMakeLists.txt index 545187a6b2cf11..abab18562e15cd 100644 --- a/drivers/ethernet/CMakeLists.txt +++ b/drivers/ethernet/CMakeLists.txt @@ -41,6 +41,7 @@ zephyr_library_sources_ifdef(CONFIG_ETH_ADIN2111 eth_adin2111.c) zephyr_library_sources_ifdef(CONFIG_ETH_LAN865X eth_lan865x.c oa_tc6.c) zephyr_library_sources_ifdef(CONFIG_ETH_XMC4XXX eth_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_ETH_TEST eth_test.c) +zephyr_library_sources_ifdef(CONFIG_ETH_RENESAS_RA eth_renesas_ra.c) if(CONFIG_ETH_NXP_S32_NETC) zephyr_library_sources(eth_nxp_s32_netc.c) diff --git a/drivers/ethernet/Kconfig b/drivers/ethernet/Kconfig index 178733bd24792f..7164189b1aac77 100644 --- a/drivers/ethernet/Kconfig +++ b/drivers/ethernet/Kconfig @@ -82,6 +82,7 @@ source "drivers/ethernet/dwc_xgmac/Kconfig" source "drivers/ethernet/phy/Kconfig" source "drivers/ethernet/nxp_enet/Kconfig" +source "drivers/ethernet/Kconfig.renesas_ra" endif # "Ethernet Drivers" diff --git a/drivers/ethernet/Kconfig.renesas_ra b/drivers/ethernet/Kconfig.renesas_ra new file mode 100644 index 00000000000000..a6c04e9392b173 --- /dev/null +++ b/drivers/ethernet/Kconfig.renesas_ra @@ -0,0 +1,36 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config ETH_RENESAS_RA + bool "Renesas RA Ethernet" + default y + depends on DT_HAS_RENESAS_RA_ETHERNET_ENABLED + select USE_RA_FSP_ETHER + select MDIO + help + Enable Renesas RA Ethernet Driver. + +if ETH_RENESAS_RA + +config ETH_RA_RX_THREAD_STACK_SIZE + int "Stack size for internal incoming packet handler" + default 1500 + help + Size of the stack used for internal thread which is ran for + incoming packet processing. + +config ETH_RA_RX_THREAD_PRIORITY + int "Renesas RA Ethernet receive thread priority" + default 2 + +config ETH_RENESAS_TX_BUF_NUM + int "Number of Transmit buffer" + default 4 + range 1 8 + +config ETH_RENESAS_RX_BUF_NUM + int "Number of Receive buffer" + default 4 + range 1 8 + +endif diff --git a/drivers/ethernet/eth_renesas_ra.c b/drivers/ethernet/eth_renesas_ra.c new file mode 100644 index 00000000000000..c4e7d4064d37d9 --- /dev/null +++ b/drivers/ethernet/eth_renesas_ra.c @@ -0,0 +1,495 @@ +/* + * Copyright (c) 2024 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_ra_ethernet + +/* Renesas RA ethernet driver */ + +#define LOG_MODULE_NAME eth_ra_ethernet +#define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL + +/* Additional configurations to use with hal_renesas */ +#define ETHER_DEFAULT NULL +#define ETHER_CHANNEL0 0 +#define ETHER_BUF_SIZE 1536 +#define ETHER_PADDING_OFFSET 1 +#define ETHER_BROADCAST_FILTER 0 +#define ETHER_TOTAL_BUF_NUM (CONFIG_ETH_RENESAS_TX_BUF_NUM + CONFIG_ETH_RENESAS_RX_BUF_NUM) + +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "r_ether.h" +#include "r_ether_phy.h" + +void ether_eint_isr(void); +void renesas_ra_eth_callback(ether_callback_args_t *p_args); +static void renesas_ra_eth_buffer_init(const struct device *dev); + +extern void ether_init_buffers(ether_instance_ctrl_t *const p_instance_ctrl); +extern void ether_configure_mac(ether_instance_ctrl_t *const p_instance_ctrl, + const uint8_t mac_addr[], const uint8_t mode); +extern void ether_do_link(ether_instance_ctrl_t *const p_instance_ctrl, const uint8_t mode); + +uint8_t g_ether0_mac_address[6] = DT_INST_PROP(0, local_mac_address); +struct renesas_ra_eth_context { + struct net_if *iface; + uint8_t mac[6]; + + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ETH_RA_RX_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem rx_sem; + ether_instance_ctrl_t ctrl; + /** pinctrl configs */ + const struct pinctrl_dev_config *pcfg; +}; + +struct renesas_ra_eth_config { + const ether_cfg_t *p_cfg; + const struct device *phy_dev; +}; + +#define ETHER_ISR_EE_RECEIVE_EVENT_MASK (0x01070000) + +#if ((ETHER_TOTAL_BUF_NUM) >= 2) +static __aligned(32) uint8_t g_ether0_ether_buffer0[ETHER_BUF_SIZE]; +static __aligned(32) uint8_t g_ether0_ether_buffer1[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 3) +static __aligned(32) uint8_t g_ether0_ether_buffer2[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 4) +static __aligned(32) uint8_t g_ether0_ether_buffer3[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 5) +static __aligned(32) uint8_t g_ether0_ether_buffer4[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 6) +static __aligned(32) uint8_t g_ether0_ether_buffer5[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 7) +static __aligned(32) uint8_t g_ether0_ether_buffer6[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 8) +static __aligned(32) uint8_t g_ether0_ether_buffer7[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 9) +static __aligned(32) uint8_t g_ether0_ether_buffer8[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 10) +static __aligned(32) uint8_t g_ether0_ether_buffer9[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 11) +static __aligned(32) uint8_t g_ether0_ether_buffer10[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 12) +static __aligned(32) uint8_t g_ether0_ether_buffer11[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 13) +static __aligned(32) uint8_t g_ether0_ether_buffer12[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 14) +static __aligned(32) uint8_t g_ether0_ether_buffer13[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 15) +static __aligned(32) uint8_t g_ether0_ether_buffer14[ETHER_BUF_SIZE]; +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 16) +static __aligned(32) uint8_t g_ether0_ether_buffer15[ETHER_BUF_SIZE]; +#endif + +uint8_t *pp_g_ether0_ether_buffers[ETHER_TOTAL_BUF_NUM] = { +#if ((ETHER_TOTAL_BUF_NUM) >= 2) + (uint8_t *)&g_ether0_ether_buffer0[0], (uint8_t *)&g_ether0_ether_buffer1[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 3) + (uint8_t *)&g_ether0_ether_buffer2[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 4) + (uint8_t *)&g_ether0_ether_buffer3[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 5) + (uint8_t *)&g_ether0_ether_buffer4[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 6) + (uint8_t *)&g_ether0_ether_buffer5[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 7) + (uint8_t *)&g_ether0_ether_buffer6[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 8) + (uint8_t *)&g_ether0_ether_buffer7[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 9) + (uint8_t *)&g_ether0_ether_buffer8[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 10) + (uint8_t *)&g_ether0_ether_buffer9[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 11) + (uint8_t *)&g_ether0_ether_buffer10[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 12) + (uint8_t *)&g_ether0_ether_buffer11[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 13) + (uint8_t *)&g_ether0_ether_buffer12[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 14) + (uint8_t *)&g_ether0_ether_buffer13[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 15) + (uint8_t *)&g_ether0_ether_buffer14[0], +#endif +#if ((ETHER_TOTAL_BUF_NUM) >= 16) + (uint8_t *)&g_ether0_ether_buffer15[0], +#endif + +}; + +static __aligned(16) ether_instance_descriptor_t + g_ether0_tx_descriptors[CONFIG_ETH_RENESAS_TX_BUF_NUM]; +static __aligned(16) ether_instance_descriptor_t + g_ether0_rx_descriptors[CONFIG_ETH_RENESAS_RX_BUF_NUM]; + +const ether_extended_cfg_t g_ether0_extended_cfg_t = { + .p_rx_descriptors = g_ether0_rx_descriptors, + .p_tx_descriptors = g_ether0_tx_descriptors, +}; + +/* Dummy configuration for ether phy as hal layer require */ +const ether_phy_extended_cfg_t g_ether_phy0_extended_cfg = { + .p_target_init = ETHER_DEFAULT, .p_target_link_partner_ability_get = ETHER_DEFAULT}; + +const ether_phy_cfg_t g_ether_phy0_cfg; + +ether_phy_instance_ctrl_t g_ether_phy0_ctrl; + +const ether_phy_instance_t g_ether_phy0 = {.p_ctrl = &g_ether_phy0_ctrl, + .p_cfg = &g_ether_phy0_cfg, + .p_api = &g_ether_phy_on_ether_phy}; + +const ether_cfg_t g_ether0_cfg = { + .channel = ETHER_CHANNEL0, + .zerocopy = ETHER_ZEROCOPY_DISABLE, + .multicast = ETHER_MULTICAST_ENABLE, + .promiscuous = ETHER_PROMISCUOUS_DISABLE, + .flow_control = ETHER_FLOW_CONTROL_DISABLE, + .padding = ETHER_PADDING_DISABLE, + .padding_offset = ETHER_PADDING_OFFSET, + .broadcast_filter = ETHER_BROADCAST_FILTER, + .p_mac_address = g_ether0_mac_address, + .num_tx_descriptors = CONFIG_ETH_RENESAS_TX_BUF_NUM, + .num_rx_descriptors = CONFIG_ETH_RENESAS_RX_BUF_NUM, + .pp_ether_buffers = pp_g_ether0_ether_buffers, + .ether_buffer_size = ETHER_BUF_SIZE, + .irq = DT_INST_IRQN(0), + .interrupt_priority = DT_INST_IRQ(0, priority), + .p_callback = ETHER_DEFAULT, + .p_ether_phy_instance = &g_ether_phy0, + .p_context = ETHER_DEFAULT, + .p_extend = &g_ether0_extended_cfg_t, +}; + +static struct renesas_ra_eth_config eth_0_config = { + .p_cfg = &g_ether0_cfg, .phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, phy_handle))}; + +/* Driver functions */ +static enum ethernet_hw_caps renesas_ra_eth_get_capabilities(const struct device *dev) +{ + ARG_UNUSED(dev); + + return ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T; +} + +void renesas_ra_eth_callback(ether_callback_args_t *p_args) +{ + struct device *dev = (struct device *)p_args->p_context; + struct renesas_ra_eth_context *ctx = dev->data; + + if (p_args->status_eesr & ETHER_ISR_EE_RECEIVE_EVENT_MASK) { + k_sem_give(&ctx->rx_sem); + } +} + +static void renesas_ra_eth_buffer_init(const struct device *dev) +{ + struct renesas_ra_eth_context *ctx = dev->data; + ether_extended_cfg_t *p_ether_extended_cfg = + (ether_extended_cfg_t *)ctx->ctrl.p_ether_cfg->p_extend; + /* Initialize the transmit and receive descriptor */ + memset(p_ether_extended_cfg->p_rx_descriptors, 0x00, + sizeof(ether_instance_descriptor_t) * ctx->ctrl.p_ether_cfg->num_rx_descriptors); + memset(p_ether_extended_cfg->p_tx_descriptors, 0x00, + sizeof(ether_instance_descriptor_t) * ctx->ctrl.p_ether_cfg->num_tx_descriptors); + + ether_init_buffers(&ctx->ctrl); +} + +static void phy_link_state_changed(const struct device *pdev, struct phy_link_state *state, + void *user_data) +{ + const struct device *dev = (struct device *)user_data; + struct renesas_ra_eth_context *ctx = dev->data; + R_ETHERC0_Type *p_reg_etherc; + + p_reg_etherc = (R_ETHERC0_Type *)ctx->ctrl.p_reg_etherc; + + ARG_UNUSED(pdev); + + if (state->is_up) { + + ctx->ctrl.link_change = ETHER_LINK_CHANGE_LINK_UP; + ctx->ctrl.previous_link_status = ETHER_PREVIOUS_LINK_STATUS_UP; + + renesas_ra_eth_buffer_init(dev); + + /* + * ETHERC and EDMAC are set after ETHERC and EDMAC are reset in software + * and sending and receiving is permitted. + */ + ether_configure_mac(&ctx->ctrl, ctx->ctrl.p_ether_cfg->p_mac_address, 0); + + switch (state->speed) { + /* Half duplex link */ + case LINK_HALF_100BASE_T: { + ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_100H; + break; + } + + case LINK_HALF_10BASE_T: { + ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_10H; + break; + } + + /* Full duplex link */ + case LINK_FULL_100BASE_T: { + ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_100F; + break; + } + + case LINK_FULL_10BASE_T: { + ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_10F; + break; + } + + default: { + ctx->ctrl.link_speed_duplex = ETHER_PHY_LINK_SPEED_100F; + break; + } + } + + ether_do_link(&ctx->ctrl, 0); + ctx->ctrl.link_change = ETHER_LINK_CHANGE_LINK_UP; + ctx->ctrl.previous_link_status = ETHER_PREVIOUS_LINK_STATUS_UP; + ctx->ctrl.link_establish_status = ETHER_LINK_ESTABLISH_STATUS_UP; + LOG_DBG("Link up"); + net_eth_carrier_on(ctx->iface); + } else { + ctx->ctrl.link_change = ETHER_LINK_CHANGE_LINK_DOWN; + ctx->ctrl.previous_link_status = ETHER_PREVIOUS_LINK_STATUS_DOWN; + ctx->ctrl.link_establish_status = ETHER_LINK_ESTABLISH_STATUS_DOWN; + net_eth_carrier_off(ctx->iface); + } +} + +static void renesas_ra_eth_initialize(struct net_if *iface) +{ + fsp_err_t err; + const struct device *dev = net_if_get_device(iface); + struct renesas_ra_eth_context *ctx = dev->data; + const struct renesas_ra_eth_config *cfg = dev->config; + + LOG_DBG("eth_initialize"); + + net_if_set_link_addr(iface, ctx->mac, sizeof(ctx->mac), NET_LINK_ETHERNET); + + if (ctx->iface == NULL) { + ctx->iface = iface; + } + + ethernet_init(iface); + + const char *phy_connection_type = DT_INST_PROP_OR(0, phy_connection_type, "rmii"); + + R_PMISC->PFENET = (uint8_t)(0x0 << R_PMISC_PFENET_PHYMODE0_Pos); + /* Handle for phy-connection-type is different from default (rmmi) */ + if (strcmp(phy_connection_type, "rmii") != 0) { + if (strcmp(phy_connection_type, "mii") == 0) { + /* Configure pins for MII or RMII. Set PHYMODE0 if MII is selected. */ + R_PMISC->PFENET = (uint8_t)(0x1 << R_PMISC_PFENET_PHYMODE0_Pos); + } else { + LOG_ERR("Failed to init ether - phy-connection-type not support"); + } + } + + err = R_ETHER_Open(&ctx->ctrl, cfg->p_cfg); + + if (err != FSP_SUCCESS) { + LOG_ERR("Failed to init ether - R_ETHER_Open fail"); + } + + err = R_ETHER_CallbackSet(&ctx->ctrl, renesas_ra_eth_callback, dev, NULL); + + if (err != FSP_SUCCESS) { + LOG_ERR("Failed to init ether - R_ETHER_CallbackSet fail"); + } + + phy_link_callback_set(cfg->phy_dev, &phy_link_state_changed, (void *)dev); + /* Do not start the interface until PHY link is up */ + net_if_carrier_off(ctx->iface); +} + +static int renesas_ra_eth_tx(const struct device *dev, struct net_pkt *pkt) +{ + fsp_err_t err = FSP_SUCCESS; + struct renesas_ra_eth_context *ctx = dev->data; + uint16_t len = net_pkt_get_len(pkt); + static uint8_t tx_buf[NET_ETH_MAX_FRAME_SIZE] __aligned(4); + + if (net_pkt_read(pkt, tx_buf, len)) { + goto error; + } + + /* Check if packet length is less than minimum Ethernet frame size */ + if (len < NET_ETH_MINIMAL_FRAME_SIZE) { + /* Add padding to meet the minimum frame size */ + memset(tx_buf + len, 0, NET_ETH_MINIMAL_FRAME_SIZE - len); + len = NET_ETH_MINIMAL_FRAME_SIZE; + } + + err = R_ETHER_Write(&ctx->ctrl, tx_buf, len); + if (err != FSP_SUCCESS) { + goto error; + } + + return 0; + +error: + LOG_ERR("Writing to FIFO failed"); + return -1; +} + +static const struct ethernet_api api_funcs = { + .iface_api.init = renesas_ra_eth_initialize, + .get_capabilities = renesas_ra_eth_get_capabilities, + .send = renesas_ra_eth_tx, +}; + +static void renesas_ra_eth_isr(const struct device *dev) +{ + ARG_UNUSED(dev); + ether_eint_isr(); +} + +static struct net_pkt *renesas_ra_eth_rx(const struct device *dev) +{ + fsp_err_t err = FSP_SUCCESS; + struct renesas_ra_eth_context *ctx; + struct net_pkt *pkt = NULL; + uint32_t len = 0; + static uint8_t rx_buf[NET_ETH_MAX_FRAME_SIZE] __aligned(4); + + __ASSERT_NO_MSG(dev != NULL); + ctx = dev->data; + __ASSERT_NO_MSG(ctx != NULL); + + err = R_ETHER_Read(&ctx->ctrl, rx_buf, &len); + if ((err != FSP_SUCCESS) && (err != FSP_ERR_ETHER_ERROR_NO_DATA)) { + LOG_ERR("Failed to read packets"); + goto out; + } + + pkt = net_pkt_rx_alloc_with_buffer(ctx->iface, len, AF_UNSPEC, 0, K_MSEC(100)); + if (!pkt) { + LOG_ERR("Failed to obtain RX buffer"); + goto out; + } + + if (net_pkt_write(pkt, rx_buf, len)) { + LOG_ERR("Failed to append RX buffer to context buffer"); + net_pkt_unref(pkt); + pkt = NULL; + goto out; + } + +out: + if (!pkt) { + eth_stats_update_errors_rx(ctx->iface); + } + + return pkt; +} + +static void renesas_ra_eth_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + const struct device *dev = p1; + struct net_if *iface; + int res; + struct net_pkt *pkt = NULL; + struct renesas_ra_eth_context *ctx = dev->data; + + while (true) { + res = k_sem_take(&ctx->rx_sem, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); + if (res == 0) { + pkt = renesas_ra_eth_rx(dev); + + if (pkt != NULL) { + iface = net_pkt_iface(pkt); + res = net_recv_data(iface, pkt); + if (res < 0) { + net_pkt_unref(pkt); + } + } + } + } +} + +#define ELC_EVENT_EDMAC_EINT(channel) ELC_EVENT_EDMAC##channel##_EINT + +/* Bindings to the platform */ +int renesas_ra_eth_init(const struct device *dev) +{ + struct renesas_ra_eth_context *ctx = dev->data; + + R_ICU->IELSR[DT_INST_IRQN(0)] = ELC_EVENT_EDMAC_EINT(0); + + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), renesas_ra_eth_isr, + DEVICE_DT_INST_GET(0), 0); + + k_thread_create(&ctx->thread, ctx->thread_stack, CONFIG_ETH_RA_RX_THREAD_STACK_SIZE, + renesas_ra_eth_thread, (void *)dev, NULL, NULL, + K_PRIO_COOP(CONFIG_ETH_RA_RX_THREAD_PRIORITY), 0, K_NO_WAIT); + + irq_enable(DT_INST_IRQN(0)); + + return 0; +} + +#define ETHER_RA_INIT(idx) \ + PINCTRL_DT_INST_DEFINE(0); \ + static struct renesas_ra_eth_context eth_0_context = { \ + .mac = DT_INST_PROP(0, local_mac_address), \ + .rx_sem = Z_SEM_INITIALIZER(eth_0_context.rx_sem, 0, UINT_MAX), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), \ + }; \ + \ + ETH_NET_DEVICE_DT_INST_DEFINE(0, renesas_ra_eth_init, NULL, ð_0_context, ð_0_config, \ + CONFIG_ETH_INIT_PRIORITY, &api_funcs, NET_ETH_MTU /*MTU*/); + +DT_INST_FOREACH_STATUS_OKAY(ETHER_RA_INIT); diff --git a/drivers/ethernet/phy/phy_mii.c b/drivers/ethernet/phy/phy_mii.c index 6d51e9f94a2432..66b421e534a5ef 100644 --- a/drivers/ethernet/phy/phy_mii.c +++ b/drivers/ethernet/phy/phy_mii.c @@ -204,6 +204,14 @@ static int update_link_state(const struct device *dev) k_sleep(K_MSEC(100)); + /* On some PHY chips, the BMSR bits are latched, so the first read may + * show incorrect status. A second read ensures correct values. + */ + if (reg_read(dev, MII_BMSR, &bmsr_reg) < 0) { + return -EIO; + } + + /* Second read, clears the latched bits and gives the correct status */ if (reg_read(dev, MII_BMSR, &bmsr_reg) < 0) { return -EIO; } diff --git a/drivers/mdio/CMakeLists.txt b/drivers/mdio/CMakeLists.txt index 640919c1037b15..779ba7ed5ef30d 100644 --- a/drivers/mdio/CMakeLists.txt +++ b/drivers/mdio/CMakeLists.txt @@ -16,3 +16,4 @@ zephyr_library_sources_ifdef(CONFIG_MDIO_ST_STM32_HAL mdio_stm32_hal.c) zephyr_library_sources_ifdef(CONFIG_MDIO_INFINEON_XMC4XXX mdio_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_ENET_QOS mdio_nxp_enet_qos.c) zephyr_library_sources_ifdef(CONFIG_MDIO_DWCXGMAC mdio_dwcxgmac.c) +zephyr_library_sources_ifdef(CONFIG_MDIO_RENESAS_RA mdio_renesas_ra.c) diff --git a/drivers/mdio/Kconfig b/drivers/mdio/Kconfig index 3c001237a8f59a..77dc4d34111716 100644 --- a/drivers/mdio/Kconfig +++ b/drivers/mdio/Kconfig @@ -37,6 +37,7 @@ source "drivers/mdio/Kconfig.stm32_hal" source "drivers/mdio/Kconfig.xmc4xxx" source "drivers/mdio/Kconfig.nxp_enet_qos" source "drivers/mdio/Kconfig.dwcxgmac" +source "drivers/mdio/Kconfig.renesas_ra" config MDIO_INIT_PRIORITY int "Init priority" diff --git a/drivers/mdio/Kconfig.renesas_ra b/drivers/mdio/Kconfig.renesas_ra new file mode 100644 index 00000000000000..9702bf9b2b4651 --- /dev/null +++ b/drivers/mdio/Kconfig.renesas_ra @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config MDIO_RENESAS_RA + bool "RENESAS MDIO controller driver" + default y + depends on DT_HAS_RENESAS_RA_MDIO_ENABLED + select PINCTRL + select USE_RA_FSP_ETHER_PHY + help + Enable RENESAS MDIO support. diff --git a/drivers/mdio/mdio_renesas_ra.c b/drivers/mdio/mdio_renesas_ra.c new file mode 100644 index 00000000000000..7971dd393585d8 --- /dev/null +++ b/drivers/mdio/mdio_renesas_ra.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2024 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "r_ether_phy.h" + +#include + +LOG_MODULE_REGISTER(renesas_ra_mdio, CONFIG_MDIO_LOG_LEVEL); + +#define DT_DRV_COMPAT renesas_ra_mdio + +struct renesas_ra_mdio_config { + const struct pinctrl_dev_config *pincfg; + uint8_t instance; +}; + +struct renesas_ra_mdio_data { + struct k_mutex rw_mutex; + struct st_ether_phy_cfg ether_phy_cfg; + struct st_ether_phy_instance_ctrl ether_phy_ctrl; +}; + +static int renesas_ra_mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad, + uint16_t *data) +{ + struct renesas_ra_mdio_data *dev_data = dev->data; + uint32_t read; + fsp_err_t err; + + dev_data->ether_phy_ctrl.phy_lsi_address = prtad; + + k_mutex_lock(&dev_data->rw_mutex, K_FOREVER); + + err = R_ETHER_PHY_Read(&dev_data->ether_phy_ctrl, regad, &read); + + k_mutex_unlock(&dev_data->rw_mutex); + + if (err != FSP_SUCCESS) { + return -EIO; + } + + *data = read & UINT16_MAX; + + return 0; +} + +static int renesas_ra_mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad, + uint16_t data) +{ + struct renesas_ra_mdio_data *dev_data = dev->data; + fsp_err_t err; + + dev_data->ether_phy_ctrl.phy_lsi_address = prtad; + + k_mutex_lock(&dev_data->rw_mutex, K_FOREVER); + + err = R_ETHER_PHY_Write(&dev_data->ether_phy_ctrl, regad, data); + + k_mutex_unlock(&dev_data->rw_mutex); + + if (err != FSP_SUCCESS) { + return -EIO; + } + + return 0; +} + +static int renesas_ra_mdio_initialize(const struct device *dev) +{ + struct renesas_ra_mdio_data *data = dev->data; + const struct renesas_ra_mdio_config *cfg = dev->config; + int err; + fsp_err_t fsp_err; + + err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT); + if (err != 0) { + return err; + } + + fsp_err = R_ETHER_PHY_Open(&data->ether_phy_ctrl, &data->ether_phy_cfg); + + if (fsp_err != FSP_SUCCESS) { + LOG_ERR("Failed to init mdio driver - R_ETHER_PHY_Open fail"); + } + + k_mutex_init(&data->rw_mutex); + + return 0; +} + +static const struct mdio_driver_api renesas_ra_mdio_api = { + .read = renesas_ra_mdio_read, + .write = renesas_ra_mdio_write, +}; + +#define RENSAS_RA_MDIO_INSTANCE_DEFINE(node) \ + PINCTRL_DT_INST_DEFINE(node); \ + static struct renesas_ra_mdio_data renesas_ra_mdio##node##_data = { \ + .ether_phy_cfg = { \ + .channel = 0, \ + .phy_reset_wait_time = 0x00020000, \ + .mii_bit_access_wait_time = 8, \ + .phy_lsi_type = ETHER_PHY_LSI_TYPE_CUSTOM, \ + .flow_control = ETHER_PHY_FLOW_CONTROL_DISABLE, \ + }}; \ + static const struct renesas_ra_mdio_config renesas_ra_mdio##node##_cfg = { \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(node)}; \ + DEVICE_DT_INST_DEFINE(node, &renesas_ra_mdio_initialize, NULL, \ + &renesas_ra_mdio##node##_data, &renesas_ra_mdio##node##_cfg, \ + POST_KERNEL, CONFIG_MDIO_INIT_PRIORITY, &renesas_ra_mdio_api); + +DT_INST_FOREACH_STATUS_OKAY(RENSAS_RA_MDIO_INSTANCE_DEFINE) diff --git a/dts/arm/renesas/ra/ra8/ra8x1.dtsi b/dts/arm/renesas/ra/ra8/ra8x1.dtsi index 96d493e25e4d62..3d9ad95ec08aa3 100644 --- a/dts/arm/renesas/ra/ra8/ra8x1.dtsi +++ b/dts/arm/renesas/ra/ra8/ra8x1.dtsi @@ -557,6 +557,22 @@ status = "disabled"; }; }; + + eth: ethernet@40354100 { + compatible = "renesas,ra-ethernet"; + reg = <0x40354100 0xfc>; + interrupts = <42 0>; + local-mac-address = [00 11 22 33 44 55]; + phy-connection-type = "rmii"; + status = "disabled"; + }; + + mdio: mdio { + compatible = "renesas,ra-mdio"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; }; diff --git a/dts/bindings/ethernet/renesas,ra-ethernet.yaml b/dts/bindings/ethernet/renesas,ra-ethernet.yaml new file mode 100644 index 00000000000000..002510e9c6698f --- /dev/null +++ b/dts/bindings/ethernet/renesas,ra-ethernet.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA Ethernet + +compatible: "renesas,ra-ethernet" + +include: [ethernet-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + phy-handle: + required: true diff --git a/dts/bindings/mdio/renesas,ra-mdio.yaml b/dts/bindings/mdio/renesas,ra-mdio.yaml new file mode 100644 index 00000000000000..51971c9e8a977c --- /dev/null +++ b/dts/bindings/mdio/renesas,ra-mdio.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA External MDIO controller + +compatible: "renesas,ra-mdio" + +include: [mdio-controller.yaml, pinctrl-device.yaml] + +properties: + pinctrl-0: + required: true + + pinctrl-names: + required: true diff --git a/modules/Kconfig.renesas_fsp b/modules/Kconfig.renesas_fsp index 9e8de7afed86f3..1d525c8282709b 100644 --- a/modules/Kconfig.renesas_fsp +++ b/modules/Kconfig.renesas_fsp @@ -76,4 +76,14 @@ config USE_RA_FSP_CANFD help Enable RA FSP CANFD driver +config USE_RA_FSP_ETHER_PHY + bool + help + Enable RA FSP Ethernet phy driver + +config USE_RA_FSP_ETHER + bool + help + Enable RA FSP Ethernet driver + endif # HAS_RENESAS_RA_FSP diff --git a/samples/net/cloud/aws_iot_mqtt/src/main.c b/samples/net/cloud/aws_iot_mqtt/src/main.c index 5e52d70187f30a..c03f250bcaa21f 100644 --- a/samples/net/cloud/aws_iot_mqtt/src/main.c +++ b/samples/net/cloud/aws_iot_mqtt/src/main.c @@ -126,6 +126,7 @@ static int publish_message(const char *topic, size_t topic_len, uint8_t *payload struct mqtt_publish_param msg; msg.retain_flag = 0u; + msg.dup_flag = 0u; msg.message.topic.topic.utf8 = topic; msg.message.topic.topic.size = topic_len; msg.message.topic.qos = CONFIG_AWS_QOS; diff --git a/west.yml b/west.yml index 87287fb39ac7cc..b2ead88e50c456 100644 --- a/west.yml +++ b/west.yml @@ -214,7 +214,7 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: 10326518701e25bf336a2eaeb8b5820110e4e6a3 + revision: pull/34/head groups: - hal - name: hal_rpi_pico