From 67f404dcb300fdd6bd74f42f40e25c5e83943e5a Mon Sep 17 00:00:00 2001 From: Thao Luong Date: Thu, 29 Aug 2024 00:19:05 +0700 Subject: [PATCH] hal: ra: Update Ethernet driver for RA board Initial support for Ethernet and Ethernet phy driver Signed-off-by: Duy Phuong Hoang. Nguyen Signed-off-by: Thao Luong --- drivers/ra/CMakeLists.txt | 10 + drivers/ra/fsp/inc/api/r_ether_api.h | 245 ++ drivers/ra/fsp/inc/api/r_ether_phy_api.h | 187 ++ drivers/ra/fsp/inc/instances/r_ether.h | 212 ++ drivers/ra/fsp/inc/instances/r_ether_phy.h | 107 + drivers/ra/fsp/src/r_ether/r_ether.c | 2017 +++++++++++++++++ drivers/ra/fsp/src/r_ether_phy/r_ether_phy.c | 1112 +++++++++ .../DP83620/r_ether_phy_target_dp83620.c | 94 + .../ICS1894/r_ether_phy_target_ics1894.c | 110 + .../KSZ8041/r_ether_phy_target_ksz8041.c | 91 + .../r_ether_phy_target_ksz8091rnb.c | 105 + zephyr/ra/ra_cfg/fsp_cfg/r_ether_cfg.h | 20 + zephyr/ra/ra_cfg/fsp_cfg/r_ether_phy_cfg.h | 50 + 13 files changed, 4360 insertions(+) create mode 100644 drivers/ra/fsp/inc/api/r_ether_api.h create mode 100644 drivers/ra/fsp/inc/api/r_ether_phy_api.h create mode 100644 drivers/ra/fsp/inc/instances/r_ether.h create mode 100644 drivers/ra/fsp/inc/instances/r_ether_phy.h create mode 100644 drivers/ra/fsp/src/r_ether/r_ether.c create mode 100644 drivers/ra/fsp/src/r_ether_phy/r_ether_phy.c create mode 100644 drivers/ra/fsp/src/r_ether_phy/targets/DP83620/r_ether_phy_target_dp83620.c create mode 100644 drivers/ra/fsp/src/r_ether_phy/targets/ICS1894/r_ether_phy_target_ics1894.c create mode 100644 drivers/ra/fsp/src/r_ether_phy/targets/KSZ8041/r_ether_phy_target_ksz8041.c create mode 100644 drivers/ra/fsp/src/r_ether_phy/targets/KSZ8091RNB/r_ether_phy_target_ksz8091rnb.c create mode 100644 zephyr/ra/ra_cfg/fsp_cfg/r_ether_cfg.h create mode 100644 zephyr/ra/ra_cfg/fsp_cfg/r_ether_phy_cfg.h diff --git a/drivers/ra/CMakeLists.txt b/drivers/ra/CMakeLists.txt index 4e02d30f..cc64964e 100644 --- a/drivers/ra/CMakeLists.txt +++ b/drivers/ra/CMakeLists.txt @@ -68,3 +68,13 @@ if(CONFIG_USE_RA_FSP_SCE) zephyr_sources(${rsip7_srcs}) endif() endif() + +zephyr_library_sources_ifdef(CONFIG_USE_RA_FSP_ETHER + fsp/src/r_ether/r_ether.c) + +if (CONFIG_USE_RA_FSP_ETHER) + file(GLOB ether_phy_srcs + "fsp/src/r_ether_phy/r_ether_phy.c" + "fsp/src/r_ether_phy/targets/*/*.c") + zephyr_sources(${ether_phy_srcs}) +endif() diff --git a/drivers/ra/fsp/inc/api/r_ether_api.h b/drivers/ra/fsp/inc/api/r_ether_api.h new file mode 100644 index 00000000..cb023175 --- /dev/null +++ b/drivers/ra/fsp/inc/api/r_ether_api.h @@ -0,0 +1,245 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @ingroup RENESAS_NETWORKING_INTERFACES + * @defgroup ETHER_API Ethernet Interface + * @brief Interface for Ethernet functions. + * + * @section ETHER_API_Summary Summary + * The Ethernet interface provides Ethernet functionality. + * The Ethernet interface supports the following features: + * - Transmit/receive processing (Blocking and Non-Blocking) + * - Callback function with returned event code + * - Magic packet detection mode support + * - Auto negotiation support + * - Flow control support + * - Multicast filtering support + * + * + * @{ + **********************************************************************************************************************/ + +#ifndef R_ETHER_API_H +#define R_ETHER_API_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Register definitions, common services and error codes. */ +#include "bsp_api.h" +#include "r_ether_phy_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** Wake on LAN */ +typedef enum e_ether_wake_on_lan +{ + ETHER_WAKE_ON_LAN_DISABLE = 0, ///< Disable Wake on LAN + ETHER_WAKE_ON_LAN_ENABLE = 1, ///< Enable Wake on LAN +} ether_wake_on_lan_t; + +/** Flow control functionality */ +typedef enum e_ether_flow_control +{ + ETHER_FLOW_CONTROL_DISABLE = 0, ///< Disable flow control functionality + ETHER_FLOW_CONTROL_ENABLE = 1, ///< Enable flow control functionality with pause frames +} ether_flow_control_t; + +/** Multicast Filter */ +typedef enum e_ether_multicast +{ + ETHER_MULTICAST_DISABLE = 0, ///< Disable reception of multicast frames + ETHER_MULTICAST_ENABLE = 1, ///< Enable reception of multicast frames +} ether_multicast_t; + +/** Promiscuous Mode */ +typedef enum e_ether_promiscuous +{ + ETHER_PROMISCUOUS_DISABLE = 0, ///< Only receive packets with current MAC address, multicast, and broadcast + ETHER_PROMISCUOUS_ENABLE = 1, ///< Receive all packets +} ether_promiscuous_t; + +/** Zero copy */ +typedef enum e_ether_zerocopy +{ + ETHER_ZEROCOPY_DISABLE = 0, ///< Disable zero copy in Read/Write function + ETHER_ZEROCOPY_ENABLE = 1, ///< Enable zero copy in Read/Write function +} ether_zerocopy_t; + +typedef enum e_ether_padding +{ + ETHER_PADDING_DISABLE = 0, + ETHER_PADDING_1BYTE = 1, + ETHER_PADDING_2BYTE = 2, + ETHER_PADDING_3BYTE = 3, +} ether_padding_t; + +#ifndef BSP_OVERRIDE_ETHER_EVENT_T + +/** Event code of callback function */ +typedef enum e_ether_event +{ + ETHER_EVENT_WAKEON_LAN, ///< Magic packet detection event + ETHER_EVENT_LINK_ON, ///< Link up detection event + ETHER_EVENT_LINK_OFF, ///< Link down detection event + ETHER_EVENT_INTERRUPT, ///< Interrupt event +} ether_event_t; +#endif + +#ifndef BSP_OVERRIDE_ETHER_CALLBACK_ARGS_T + +/** Callback function parameter data */ +typedef struct st_ether_callback_args +{ + uint32_t channel; ///< Device channel number + ether_event_t event; ///< Event code + uint32_t status_ecsr; ///< ETHERC status register for interrupt handler + uint32_t status_eesr; ///< ETHERC/EDMAC status register for interrupt handler + + void const * p_context; ///< Placeholder for user data. Set in @ref ether_api_t::open function in @ref ether_cfg_t. +} ether_callback_args_t; +#endif + +/** Control block. Allocate an instance specific control block to pass into the API calls. + */ +typedef void ether_ctrl_t; + +/** Configuration parameters. */ +typedef struct st_ether_cfg +{ + uint8_t channel; ///< Channel + ether_zerocopy_t zerocopy; ///< Zero copy enable or disable in Read/Write function + ether_multicast_t multicast; ///< Multicast enable or disable + ether_promiscuous_t promiscuous; ///< Promiscuous mode enable or disable + ether_flow_control_t flow_control; ///< Flow control functionally enable or disable + ether_padding_t padding; ///< Padding length inserted into the received Ethernet frame. + uint32_t padding_offset; ///< Offset of the padding inserted into the received Ethernet frame. + uint32_t broadcast_filter; ///< Limit of the number of broadcast frames received continuously + uint8_t * p_mac_address; ///< Pointer of MAC address + + uint8_t num_tx_descriptors; ///< Number of transmission descriptor + uint8_t num_rx_descriptors; ///< Number of receive descriptor + + uint8_t ** pp_ether_buffers; ///< Transmit and receive buffer + + uint32_t ether_buffer_size; ///< Size of transmit and receive buffer + + IRQn_Type irq; ///< Interrupt number + uint32_t interrupt_priority; ///< Interrupt priority + + void (* p_callback)(ether_callback_args_t * p_args); ///< Callback provided when an ISR occurs. + + ether_phy_instance_t const * p_ether_phy_instance; ///< Pointer to ETHER_PHY instance + + /** Placeholder for user data. Passed to the user callback in ether_callback_args_t. */ + void const * p_context; ///< Placeholder for user data. + void const * p_extend; ///< Placeholder for user extension. +} ether_cfg_t; + +/** Functions implemented at the HAL layer will follow this API. */ +typedef struct st_ether_api +{ + /** Open driver. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to pin configuration structure. + */ + fsp_err_t (* open)(ether_ctrl_t * const p_ctrl, ether_cfg_t const * const p_cfg); + + /** Close driver. + * + * @param[in] p_ctrl Pointer to control structure. + */ + fsp_err_t (* close)(ether_ctrl_t * const p_ctrl); + + /** Read packet if data is available. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_buffer Pointer to where to store read data. + * @param[in] length_bytes Number of bytes in buffer + */ + fsp_err_t (* read)(ether_ctrl_t * const p_ctrl, void * const p_buffer, uint32_t * const length_bytes); + + /** Release rx buffer from buffer pool process in zero-copy read operation. + * + * @param[in] p_ctrl Pointer to control structure. + */ + fsp_err_t (* bufferRelease)(ether_ctrl_t * const p_ctrl); + + /** Update the buffer pointer in the current receive descriptor. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_buffer New address to write into the rx buffer descriptor. + */ + fsp_err_t (* rxBufferUpdate)(ether_ctrl_t * const p_ctrl, void * const p_buffer); + + /** Write packet. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_buffer Pointer to data to write. + * @param[in] frame_length Send ethernet frame size (without 4 bytes of CRC data size). + */ + fsp_err_t (* write)(ether_ctrl_t * const p_ctrl, void * const p_buffer, uint32_t const frame_length); + + /** Process link. + * + * @param[in] p_ctrl Pointer to control structure. + */ + fsp_err_t (* linkProcess)(ether_ctrl_t * const p_ctrl); + + /** Enable magic packet detection. + * + * @param[in] p_ctrl Pointer to control structure. + */ + fsp_err_t (* wakeOnLANEnable)(ether_ctrl_t * const p_ctrl); + + /** Get the address of the most recently sent buffer. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[out] p_buffer_address Pointer to the address of the most recently sent buffer. + */ + fsp_err_t (* txStatusGet)(ether_ctrl_t * const p_ctrl, void * const p_buffer_address); + + /** + * Specify callback function and optional context pointer and working memory pointer. + * + * @param[in] p_ctrl Pointer to the ETHER control block. + * @param[in] p_callback Callback function + * @param[in] p_context Pointer to send to callback function + * @param[in] p_working_memory Pointer to volatile memory where callback structure can be allocated. + * Callback arguments allocated here are only valid during the callback. + */ + fsp_err_t (* callbackSet)(ether_ctrl_t * const p_ctrl, void (* p_callback)(ether_callback_args_t *), + void const * const p_context, ether_callback_args_t * const p_callback_memory); +} ether_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_ether_instance +{ + ether_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + ether_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + ether_api_t const * p_api; ///< Pointer to the API structure for this instance +} ether_instance_t; + +/*******************************************************************************************************************//** + * @} (end defgroup ETHER_API) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif /* R_ETHERNET_API_H */ diff --git a/drivers/ra/fsp/inc/api/r_ether_phy_api.h b/drivers/ra/fsp/inc/api/r_ether_phy_api.h new file mode 100644 index 00000000..aa2dea64 --- /dev/null +++ b/drivers/ra/fsp/inc/api/r_ether_phy_api.h @@ -0,0 +1,187 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @ingroup RENESAS_NETWORKING_INTERFACES + * @defgroup ETHER_PHY_API Ethernet PHY Interface + * @brief Interface for Ethernet PHY functions. + * + * @section ETHER_PHY_API_Summary Summary + * The Ethernet PHY module (r_ether_phy) provides an API for standard Ethernet PHY communications applications that use + * the ETHERC peripheral. + * + * The Ethernet PHY interface supports the following features: + * - Auto negotiation support + * - Flow control support + * - Link status check support + * + * + * @{ + **********************************************************************************************************************/ + +#ifndef R_ETHER_PHY_API_H +#define R_ETHER_PHY_API_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Register definitions, common services and error codes. */ +#include "bsp_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +#ifndef BSP_OVERRIDE_ETHER_PHY_LSI_TYPE_T + +/** Phy LSI */ +typedef enum e_ether_phy_lsi_type +{ + ETHER_PHY_LSI_TYPE_DEFAULT = 0, ///< Select default configuration. This type dose not change Phy LSI default setting by strapping option. + ETHER_PHY_LSI_TYPE_KSZ8091RNB = 1, ///< Select configuration for KSZ8091RNB. + ETHER_PHY_LSI_TYPE_KSZ8041 = 2, ///< Select configuration for KSZ8041. + ETHER_PHY_LSI_TYPE_DP83620 = 3, ///< Select configuration for DP83620. + ETHER_PHY_LSI_TYPE_ICS1894 = 4, ///< Select configuration for ICS1894. + ETHER_PHY_LSI_TYPE_CUSTOM = 0xFFU, ///< Select configuration for User custom. +} ether_phy_lsi_type_t; +#endif + +/** Flow control functionality */ +typedef enum e_ether_phy_flow_control +{ + ETHER_PHY_FLOW_CONTROL_DISABLE = 0, ///< Disable flow control functionality + ETHER_PHY_FLOW_CONTROL_ENABLE = 1, ///< Enable flow control functionality with pause frames +} ether_phy_flow_control_t; + +/** Link speed */ +typedef enum e_ether_phy_link_speed +{ + ETHER_PHY_LINK_SPEED_NO_LINK = 0, ///< Link is not established + ETHER_PHY_LINK_SPEED_10H = 1, ///< Link status is 10Mbit/s and half duplex + ETHER_PHY_LINK_SPEED_10F = 2, ///< Link status is 10Mbit/s and full duplex + ETHER_PHY_LINK_SPEED_100H = 3, ///< Link status is 100Mbit/s and half duplex + ETHER_PHY_LINK_SPEED_100F = 4, ///< Link status is 100Mbit/s and full duplex + ETHER_PHY_LINK_SPEED_1000H = 5, ///< Link status is 1000Mbit/s and half duplex + ETHER_PHY_LINK_SPEED_1000F = 6 ///< Link status is 1000Mbit/s and full duplex +} ether_phy_link_speed_t; + +/** Media-independent interface */ +typedef enum e_ether_phy_mii_type +{ + ETHER_PHY_MII_TYPE_MII = 0, ///< MII + ETHER_PHY_MII_TYPE_RMII = 1, ///< RMII + ETHER_PHY_MII_TYPE_GMII = 2, ///< GMII + ETHER_PHY_MII_TYPE_RGMII = 3 ///< RGMII +} ether_phy_mii_type_t; + +/** Control block. Allocate an instance specific control block to pass into the API calls. + */ +typedef void ether_phy_ctrl_t; + +/** Configuration parameters. */ +typedef struct st_ether_phy_cfg +{ + uint8_t channel; ///< Channel + uint8_t phy_lsi_address; ///< Address of PHY-LSI + + uint32_t phy_reset_wait_time; ///< Wait time for PHY-LSI reboot + int32_t mii_bit_access_wait_time; ///< Wait time for MII/RMII access + ether_phy_lsi_type_t phy_lsi_type; ///< Phy LSI type + + ether_phy_flow_control_t flow_control; ///< Flow control functionally enable or disable + ether_phy_mii_type_t mii_type; ///< Interface type is MII or RMII + + /** Placeholder for user data. Passed to the user callback in ether_phy_callback_args_t. */ + void const * p_context; + void const * p_extend; ///< Placeholder for user extension. +} ether_phy_cfg_t; + +/** Functions implemented at the HAL layer will follow this API. */ +typedef struct st_ether_phy_api +{ + /** Open driver. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to pin configuration structure. + */ + fsp_err_t (* open)(ether_phy_ctrl_t * const p_ctrl, ether_phy_cfg_t const * const p_cfg); + + /** Close driver. + * + * @param[in] p_ctrl Pointer to control structure. + */ + fsp_err_t (* close)(ether_phy_ctrl_t * const p_ctrl); + + /** Initialize PHY-LSI. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to pin configuration structure. + */ + fsp_err_t (* chipInit)(ether_phy_ctrl_t * const p_ctrl, ether_phy_cfg_t const * const p_cfg); + + /** Read register value of PHY-LSI. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] reg_addr Register address. + * @param[out] p_data Pointer to the location to store read data. + */ + fsp_err_t (* read)(ether_phy_ctrl_t * const p_ctrl, uint32_t reg_addr, uint32_t * const p_data); + + /** Write data to register of PHY-LSI. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] reg_addr Register address. + * @param[in] data Data written to register. + */ + fsp_err_t (* write)(ether_phy_ctrl_t * const p_ctrl, uint32_t reg_addr, uint32_t data); + + /** Start auto negotiation. + * + * @param[in] p_ctrl Pointer to control structure. + */ + fsp_err_t (* startAutoNegotiate)(ether_phy_ctrl_t * const p_ctrl); + + /** Get the partner ability. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[out] p_line_speed_duplex Pointer to the location of both the line speed and the duplex. + * @param[out] p_local_pause Pointer to the location to store the local pause bits. + * @param[out] p_partner_pause Pointer to the location to store the partner pause bits. + */ + fsp_err_t (* linkPartnerAbilityGet)(ether_phy_ctrl_t * const p_ctrl, uint32_t * const p_line_speed_duplex, + uint32_t * const p_local_pause, uint32_t * const p_partner_pause); + + /** Get Link status from PHY-LSI interface. + * + * @param[in] p_ctrl Pointer to control structure. + */ + fsp_err_t (* linkStatusGet)(ether_phy_ctrl_t * const p_ctrl); +} ether_phy_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_ether_phy_instance +{ + ether_phy_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + ether_phy_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + ether_phy_api_t const * p_api; ///< Pointer to the API structure for this instance +} ether_phy_instance_t; + +/*******************************************************************************************************************//** + * @} (end defgroup ETHER_PHY_API) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif /* R_ETHER_PHY_API_H */ diff --git a/drivers/ra/fsp/inc/instances/r_ether.h b/drivers/ra/fsp/inc/instances/r_ether.h new file mode 100644 index 00000000..e934aec5 --- /dev/null +++ b/drivers/ra/fsp/inc/instances/r_ether.h @@ -0,0 +1,212 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup ETHER + * @{ + **********************************************************************************************************************/ + +#ifndef R_ETHER_H +#define R_ETHER_H + +#include "bsp_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_ether_cfg.h" +#include "r_ether_api.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ +typedef enum e_ether_previous_link_status +{ + ETHER_PREVIOUS_LINK_STATUS_DOWN = 0, ///< Previous link status is down + ETHER_PREVIOUS_LINK_STATUS_UP = 1, ///< Previous link status is up +} ether_previous_link_status_t; + +typedef enum e_ether_link_change +{ + ETHER_LINK_CHANGE_NO_CHANGE = 0, ///< Link status is no change + ETHER_LINK_CHANGE_LINK_DOWN = 1, ///< Link status changes to down + ETHER_LINK_CHANGE_LINK_UP = 2, ///< Link status changes to up +} ether_link_change_t; + +typedef enum e_ether_magic_packet +{ + ETHER_MAGIC_PACKET_NOT_DETECTED = 0, ///< Magic packet is not detected + ETHER_MAGIC_PACKET_DETECTED = 1, ///< Magic packet is detected +} ether_magic_packet_t; + +typedef enum e_ether_link_establish_status +{ + ETHER_LINK_ESTABLISH_STATUS_DOWN = 0, ///< Link establish status is down + ETHER_LINK_ESTABLISH_STATUS_UP = 1, ///< Link establish status is up +} ether_link_establish_status_t; + +/** EDMAC descriptor as defined in the hardware manual. + * Structure must be packed at 1 byte. + */ +typedef struct st_ether_instance_descriptor +{ + volatile uint32_t status; +#if ((defined(__GNUC__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || (defined(__ARMCC_VERSION) && \ + !defined(__ARM_BIG_ENDIAN)) || (defined(__ICCARM__) && (__LITTLE_ENDIAN__))) + + /* Little endian */ + volatile uint16_t size; + volatile uint16_t buffer_size; +#else + + /* Big endian */ + volatile uint16_t buffer_size; + volatile uint16_t size; +#endif + uint8_t * p_buffer; + struct st_ether_instance_descriptor * p_next; +} ether_instance_descriptor_t; + +/** ETHER extension configures the buffer descriptor for ETHER. */ +typedef struct st_ether_extended_cfg +{ + ether_instance_descriptor_t * p_rx_descriptors; ///< Receive descriptor buffer pool + ether_instance_descriptor_t * p_tx_descriptors; ///< Transmit descriptor buffer pool +} ether_extended_cfg_t; + +/** ETHER control block. DO NOT INITIALIZE. Initialization occurs when @ref ether_api_t::open is called. */ +typedef struct st_ether_instance_ctrl +{ + uint32_t open; ///< Used to determine if the channel is configured + + /* Configuration of ethernet module. */ + ether_cfg_t const * p_ether_cfg; ///< Pointer to initial configurations. + + /* Buffer of ethernet module. */ + ether_instance_descriptor_t * p_rx_descriptor; ///< Pointer to the currently referenced transmit descriptor + ether_instance_descriptor_t * p_tx_descriptor; ///< Pointer to the currently referenced receive descriptor + + /* Interface for PHY-LSI chip. */ + void * p_reg_etherc; ///< Base register of ethernet controller for this channel + void * p_reg_edmac; ///< Base register of EDMA controller for this channel + + /* Status of ethernet driver. */ + ether_previous_link_status_t previous_link_status; ///< Previous link status + ether_link_change_t link_change; ///< status of link change + ether_magic_packet_t magic_packet; ///< status of magic packet detection + ether_link_establish_status_t link_establish_status; ///< Current Link status + + /* Pointer to callback and optional working memory */ + void (* p_callback)(ether_callback_args_t *); + ether_callback_args_t * p_callback_memory; + + /* Pointer to context to be passed into callback function */ + void const * p_context; +} ether_instance_ctrl_t; + +/* + * PauseMaskE, PauseValE and pause_resolutionS are use to create + * PAUSE resolution Table 28B-3 in IEEE 802.3-2008 standard. + */ +typedef enum e_ether_pause_mask +{ + ETHER_PAUSE_MASK0, + ETHER_PAUSE_MASK1, + ETHER_PAUSE_MASK2, + ETHER_PAUSE_MASK3, + ETHER_PAUSE_MASK4, + ETHER_PAUSE_MASK5, + ETHER_PAUSE_MASK6, + ETHER_PAUSE_MASK7, + ETHER_PAUSE_MASK8, + ETHER_PAUSE_MASK9, + ETHER_PAUSE_MASKA, + ETHER_PAUSE_MASKB, + ETHER_PAUSE_MASKC, + ETHER_PAUSE_MASKD, + ETHER_PAUSE_MASKE, + ETHER_PAUSE_MASKF +} ether_pause_mask_t; + +typedef enum e_ether_pause_val +{ + ETHER_PAUSE_VAL0, + ETHER_PAUSE_VAL1, + ETHER_PAUSE_VAL2, + ETHER_PAUSE_VAL3, + ETHER_PAUSE_VAL4, + ETHER_PAUSE_VAL5, + ETHER_PAUSE_VAL6, + ETHER_PAUSE_VAL7, + ETHER_PAUSE_VAL8, + ETHER_PAUSE_VAL9, + ETHER_PAUSE_VALA, + ETHER_PAUSE_VALB, + ETHER_PAUSE_VALC, + ETHER_PAUSE_VALD, + ETHER_PAUSE_VALE, + ETHER_PAUSE_VALF +} ether_pause_val_t; + +typedef struct st_ether_pause_resolution +{ + ether_pause_mask_t mask; + ether_pause_val_t value; + uint8_t transmit; + uint8_t receive; +} ether_pause_resolution_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const ether_api_t g_ether_on_ether; + +/** @endcond */ + +/********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_ETHER_Open(ether_ctrl_t * const p_ctrl, ether_cfg_t const * const p_cfg); + +fsp_err_t R_ETHER_Close(ether_ctrl_t * const p_ctrl); + +fsp_err_t R_ETHER_Read(ether_ctrl_t * const p_ctrl, void * const p_buffer, uint32_t * const length_bytes); + +fsp_err_t R_ETHER_BufferRelease(ether_ctrl_t * const p_ctrl); + +fsp_err_t R_ETHER_RxBufferUpdate(ether_ctrl_t * const p_ctrl, void * const p_buffer); + +fsp_err_t R_ETHER_Write(ether_ctrl_t * const p_ctrl, void * const p_buffer, uint32_t const frame_length); + +fsp_err_t R_ETHER_LinkProcess(ether_ctrl_t * const p_ctrl); + +fsp_err_t R_ETHER_WakeOnLANEnable(ether_ctrl_t * const p_ctrl); + +fsp_err_t R_ETHER_TxStatusGet(ether_ctrl_t * const p_ctrl, void * const p_buffer_address); + +fsp_err_t R_ETHER_CallbackSet(ether_ctrl_t * const p_api_ctrl, + void ( * p_callback)(ether_callback_args_t *), + void const * const p_context, + ether_callback_args_t * const p_callback_memory); + +/*******************************************************************************************************************//** + * @} (end addtogroup ETHER) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif // R_ETHER_H diff --git a/drivers/ra/fsp/inc/instances/r_ether_phy.h b/drivers/ra/fsp/inc/instances/r_ether_phy.h new file mode 100644 index 00000000..ac6aa1df --- /dev/null +++ b/drivers/ra/fsp/inc/instances/r_ether_phy.h @@ -0,0 +1,107 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup ETHER_PHY + * @{ + **********************************************************************************************************************/ + +#ifndef R_ETHER_PHY_H +#define R_ETHER_PHY_H + +#include "bsp_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_ether_phy_cfg.h" +#include "r_ether_phy_api.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** Initialization state for read/write */ +typedef enum e_ether_phy_interface_status +{ + ETHER_PHY_INTERFACE_STATUS_UNINITIALIZED = 0, ///< ETHER PHY interface is uninitialized + ETHER_PHY_INTERFACE_STATUS_INITIALIZED = 1 ///< ETHER PHY interface is initialized +} ether_phy_interface_status_t; + +/** ETHER PHY control block. DO NOT INITIALIZE. Initialization occurs when @ref ether_phy_api_t::open is called. */ +typedef struct st_ether_phy_instance_ctrl +{ + uint32_t open; ///< Used to determine if the channel is configured + + /* Configuration of Ethernet PHY-LSI module. */ + ether_phy_cfg_t const * p_ether_phy_cfg; ///< Pointer to initial configurations. + + /* Interface for PHY-LSI chip. */ + volatile uint32_t * p_reg_pir; ///< Pointer to ETHERC peripheral registers. + + /* The capabilities of the local link as PHY data */ + uint32_t local_advertise; ///< Capabilities bitmap for local advertising. + ether_phy_interface_status_t interface_status; ///< Initialized status of ETHER PHY interface. +} ether_phy_instance_ctrl_t; + +/** ETHER PHY extended configuration. */ +typedef struct st_ether_phy_extended_cfg +{ + void (* p_target_init)(ether_phy_instance_ctrl_t * p_instance_ctrl); ///< Pointer to callback that is called to initialize the target. + bool (* p_target_link_partner_ability_get)(ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t line_speed_duplex); ///< Pointer to callback that is called to get the link partner ability. +} ether_phy_extended_cfg_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const ether_phy_api_t g_ether_phy_on_ether_phy; + +/** @endcond */ + +/*********************************************************************************************************************** + * Exported global functions (to be accessed by other files) + ***********************************************************************************************************************/ + +/********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_ETHER_PHY_Open(ether_phy_ctrl_t * const p_ctrl, ether_phy_cfg_t const * const p_cfg); + +fsp_err_t R_ETHER_PHY_Close(ether_phy_ctrl_t * const p_ctrl); + +fsp_err_t R_ETHER_PHY_ChipInit(ether_phy_ctrl_t * const p_ctrl, ether_phy_cfg_t const * const p_cfg); + +fsp_err_t R_ETHER_PHY_Read(ether_phy_ctrl_t * const p_ctrl, uint32_t reg_addr, uint32_t * const p_data); + +fsp_err_t R_ETHER_PHY_Write(ether_phy_ctrl_t * const p_ctrl, uint32_t reg_addr, uint32_t data); + +fsp_err_t R_ETHER_PHY_StartAutoNegotiate(ether_phy_ctrl_t * const p_ctrl); + +fsp_err_t R_ETHER_PHY_LinkPartnerAbilityGet(ether_phy_ctrl_t * const p_ctrl, + uint32_t * const p_line_speed_duplex, + uint32_t * const p_local_pause, + uint32_t * const p_partner_pause); + +fsp_err_t R_ETHER_PHY_LinkStatusGet(ether_phy_ctrl_t * const p_ctrl); + +/*******************************************************************************************************************//** + * @} (end addtogroup ETHER_PHY) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif // R_ETHER_PHY_H diff --git a/drivers/ra/fsp/src/r_ether/r_ether.c b/drivers/ra/fsp/src/r_ether/r_ether.c new file mode 100644 index 00000000..7ad57825 --- /dev/null +++ b/drivers/ra/fsp/src/r_ether/r_ether.c @@ -0,0 +1,2017 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + ***********************************************************************************************************************/ +#include +#include "r_ether.h" +#include "r_ether_phy.h" + +/*********************************************************************************************************************** + * Macro definitions + ***********************************************************************************************************************/ +#ifndef ETHER_ERROR_RETURN + + #define ETHER_ERROR_RETURN(a, err) FSP_ERROR_RETURN((a), (err)) +#endif + +#define ETHER_ETHERC_REG_SIZE (0x400UL) +#define ETHER_ETHERC_EDMAC_REG_SIZE (0x100UL) + +#define ETHER_ETHERC_INITIALIZATION_WAIT_CYCLE (0x64UL) + +/** "ETHE" in ASCII. Used to determine if the control block is open. */ +#define ETHER_OPEN (0x45544845U) + +/* Definition of the maximum / minimum number of data that can be sent at one time in the Ethernet */ +#define ETHER_MAXIMUM_FRAME_SIZE (1514U) /* Maximum number of transmitted data */ +#define ETHER_MINIMUM_FRAME_SIZE (60U) /* Minimum number of transmitted data */ + +/* Definition of the maximum padding offset */ +#define ETHER_MAXIMUM_PADDING_OFFSET (63U) + +/* Bit definition of Ethernet interrupt factor*/ +#define ETHER_ETHERC_INTERRUPT_FACTOR_ALL (0x00000037UL) + +#define ETHER_ETHERC_INTERRUPT_FACTOR_LCHNG (1UL << 2) +#define ETHER_ETHERC_INTERRUPT_FACTOR_MPD (1UL << 1) + +#define ETHER_EDMAC_INTERRUPT_FACTOR_ALL (0x47FF0F9FUL) + +#define ETHER_EDMAC_INTERRUPT_FACTOR_RFCOF (1UL << 24) +#define ETHER_EDMAC_INTERRUPT_FACTOR_ECI (1UL << 22) +#define ETHER_EDMAC_INTERRUPT_FACTOR_TC (1UL << 21) +#define ETHER_EDMAC_INTERRUPT_FACTOR_FR (1UL << 18) +#define ETHER_EDMAC_INTERRUPT_FACTOR_RDE (1UL << 17) +#define ETHER_EDMAC_INTERRUPT_FACTOR_RFOF (1UL << 16) + +/* Bit definition of Ethernet interrupt enable */ +#define ETHER_ETHERC_INTERRUPT_ENABLE_LCHNG (1UL << 2) +#define ETHER_ETHERC_INTERRUPT_ENABLE_MPD (1UL << 1) + +/* Bit definitions of status member of DescriptorS */ + +#define ETHER_TD0_TACT (0x80000000UL) +#define ETHER_TD0_TDLE (0x40000000UL) +#define ETHER_TD0_TFP1 (0x20000000UL) +#define ETHER_TD0_TFP0 (0x10000000UL) +#define ETHER_TD0_TFE (0x08000000UL) + +#define ETHER_TD0_TWBI (0x04000000UL) +#define ETHER_TD0_TFS8_TAD (0x00000100UL) +#define ETHER_TD0_TFS3_CND (0x00000008UL) +#define ETHER_TD0_TFS2_DLC (0x00000004UL) +#define ETHER_TD0_TFS1_CD (0x00000002UL) +#define ETHER_TD0_TFS0_TRO (0x00000001UL) + +#define ETHER_RD0_RACT (0x80000000UL) +#define ETHER_RD0_RDLE (0x40000000UL) +#define ETHER_RD0_RFP1 (0x20000000UL) +#define ETHER_RD0_RFP0 (0x10000000UL) +#define ETHER_RD0_RFE (0x08000000UL) + +#define ETHER_RD0_RFS9_RFOVER (0x00000200UL) +#define ETHER_RD0_RFS8_RAD (0x00000100UL) +#define ETHER_RD0_RFS7_RMAF (0x00000080UL) +#define ETHER_RD0_RFS4_RRF (0x00000010UL) +#define ETHER_RD0_RFS3_RTLF (0x00000008UL) +#define ETHER_RD0_RFS2_RTSF (0x00000004UL) +#define ETHER_RD0_RFS1_PRE (0x00000002UL) +#define ETHER_RD0_RFS0_CERF (0x00000001UL) + +/* Macro definitions of ETHERC/EDMAC configurations */ +#define ETHER_ETHERC_ECMR_MODE_CLEAR (0x00000000UL) +#define ETHER_ETHERC_RFLR_DEFAULT_VALUE (1518U) +#define ETHER_ETHERC_IPGR_DEFAULT_VALUE (0x00000014UL) +#define ETHER_ETHERC_APR_MAXIMUM_VALUE (0x0000FFFFUL) +#define ETHER_ETHERC_FCFTR_MINIMUM_VALUE (0x00000000UL) + +#define ETHER_EDMAC_TRSCER_MULTICAST_DISABLE (0x00000000UL) +#define ETHER_EDMAC_TRSCER_MULTICAST_ENABLE (0x00000080UL) +#define ETHER_EDMAC_RMCR_MULTIPLE_FRAMES_ENABLE (0x00000001UL) +#define ETHER_EDMAC_TFTR_STORE_AND_FORWARD_MODE (0x00000000UL) + +/* Macro definitions of EDMAC requests */ +#define ETHER_EDMAC_EDRRR_RECEIVE_REQUEST (0x00000001UL) +#define ETHER_EDMAC_EDTRR_TRANSMIT_REQUEST (0x00000001UL) + +/* Number of entries in PAUSE resolution table */ +#define ETHER_PAUSE_TABLE_ENTRIES (8) + +/* Local device and link partner PAUSE settings */ +#define ETHER_PAUSE_XMIT_OFF (0) /* The pause frame transmission is prohibited. */ +#define ETHER_PAUSE_RECV_OFF (0) /* The pause frame reception is prohibited. */ +#define ETHER_PAUSE_XMIT_ON (1) /* The pause frame transmission is permitted. */ +#define ETHER_PAUSE_RECV_ON (1) /* The pause frame reception is permitted. */ + +/* Macro definition for buffer alignment adjustment */ +#define ETHER_BUFFER_32BYTE_ALIGNMENT_MASK (0x1FUL) /* Mask for checking whether or not 32-bit alignment. */ + +/* PAUSE link mask and shift values */ + +/* + * The mask value and shift value which are for that shift the bits form a line and + * for comparing the bit information of PAUSE function which support the local device and + * Link partner with the assorted table(pause_resolution) which enable or disable the PAUSE frame. + */ +#define ETHER_LINK_RESOLUTION_ABILITY_MASK (3) +#define ETHER_LINK_RESOLUTION_LOCAL_ABILITY_BITSHIFT (2) + +/* Etherc mode */ +#define ETHER_NO_USE_MAGIC_PACKET_DETECT (0) +#define ETHER_USE_MAGIC_PACKET_DETECT (1) + +/* ETHER_NO_DATA is the return value that indicates that no received data. */ +#define ETHER_NO_DATA (0) + +/* PAUSE link mask and shift values */ + +/*********************************************************************************************************************** + * Typedef definitions + ***********************************************************************************************************************/ +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +typedef void (BSP_CMSE_NONSECURE_CALL * ether_prv_ns_callback)(ether_callback_args_t * p_args); +#elif defined(__GNUC__) +typedef BSP_CMSE_NONSECURE_CALL void (*volatile ether_prv_ns_callback)(ether_callback_args_t * p_args); +#endif + +/*********************************************************************************************************************** + * Exported global functions (to be accessed by other files) + ***********************************************************************************************************************/ +void ether_eint_isr(void); + +/*********************************************************************************************************************** + * Exported global variables (to be accessed by other files) + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) +static fsp_err_t ether_open_param_check(ether_instance_ctrl_t const * const p_instance_ctrl, + ether_cfg_t const * const p_cfg); + +#endif + +static void ether_enable_icu(ether_instance_ctrl_t * const p_instance_ctrl); +static void ether_disable_icu(ether_instance_ctrl_t * const p_instance_ctrl); +static void ether_reset_mac(R_ETHERC_EDMAC_Type * const p_reg); +static void ether_init_descriptors(ether_instance_ctrl_t * const p_instance_ctrl); +static void ether_init_buffers(ether_instance_ctrl_t * const p_instance_ctrl); +static fsp_err_t ether_buffer_get(ether_instance_ctrl_t * const p_instance_ctrl, + void ** const p_buffer, + uint32_t * p_buffer_size); +static void ether_config_ethernet(ether_instance_ctrl_t const * const p_instance_ctrl, const uint8_t mode); +static void ether_pause_resolution(uint32_t const local_ability, + uint32_t const partner_ability, + uint32_t * ptx_pause, + uint32_t * prx_pause); +static void ether_configure_mac(ether_instance_ctrl_t * const p_instance_ctrl, + const uint8_t mac_addr[], + const uint8_t mode); +static fsp_err_t ether_do_link(ether_instance_ctrl_t * const p_instance_ctrl, const uint8_t mode); +static fsp_err_t ether_link_status_check(ether_instance_ctrl_t const * const p_instance_ctrl); +static uint8_t ether_check_magic_packet_detection_bit(ether_instance_ctrl_t const * const p_instance_ctrl); +static void ether_configure_padding(ether_instance_ctrl_t * const p_instance_ctrl); +static void ether_call_callback(ether_instance_ctrl_t * p_instance_ctrl, ether_callback_args_t * p_callback_args); + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ + +/** Name of module used by error logger macro */ +#if BSP_CFG_ERROR_LOG != 0 +static const char g_module_name[] = "ether"; +#endif + +#if defined(__GNUC__) + +/* This structure is affected by warnings from a GCC compiler bug. This pragma suppresses the warnings in this + * structure only.*/ + + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +/** ETHER HAL API mapping for Ethernet Controller interface. */ +const ether_api_t g_ether_on_ether = +{ + .open = R_ETHER_Open, + .close = R_ETHER_Close, + .read = R_ETHER_Read, + .bufferRelease = R_ETHER_BufferRelease, + .rxBufferUpdate = R_ETHER_RxBufferUpdate, + .write = R_ETHER_Write, + .linkProcess = R_ETHER_LinkProcess, + .wakeOnLANEnable = R_ETHER_WakeOnLANEnable, + .txStatusGet = R_ETHER_TxStatusGet, + .callbackSet = R_ETHER_CallbackSet, +}; + +/* + * PAUSE Resolution as documented in IEEE 802.3-2008_section2 Annex + * 28B, Table 28B-3. The following table codify logic that + * determines how the PAUSE is configured for local transmitter + * and receiver and partner transmitter and receiver. + */ +static const ether_pause_resolution_t pause_resolution[ETHER_PAUSE_TABLE_ENTRIES] = +{ + {ETHER_PAUSE_MASKC, ETHER_PAUSE_VAL0, ETHER_PAUSE_XMIT_OFF, ETHER_PAUSE_RECV_OFF }, + {ETHER_PAUSE_MASKE, ETHER_PAUSE_VAL4, ETHER_PAUSE_XMIT_OFF, ETHER_PAUSE_RECV_OFF }, + {ETHER_PAUSE_MASKF, ETHER_PAUSE_VAL6, ETHER_PAUSE_XMIT_OFF, ETHER_PAUSE_RECV_OFF }, + {ETHER_PAUSE_MASKF, ETHER_PAUSE_VAL7, ETHER_PAUSE_XMIT_ON, ETHER_PAUSE_RECV_OFF }, + {ETHER_PAUSE_MASKE, ETHER_PAUSE_VAL8, ETHER_PAUSE_XMIT_OFF, ETHER_PAUSE_RECV_OFF }, + {ETHER_PAUSE_MASKA, ETHER_PAUSE_VALA, ETHER_PAUSE_XMIT_ON, ETHER_PAUSE_RECV_ON }, + {ETHER_PAUSE_MASKF, ETHER_PAUSE_VALC, ETHER_PAUSE_XMIT_OFF, ETHER_PAUSE_RECV_OFF }, + {ETHER_PAUSE_MASKF, ETHER_PAUSE_VALD, ETHER_PAUSE_XMIT_OFF, ETHER_PAUSE_RECV_ON } +}; + +/*******************************************************************************************************************//** + * @addtogroup ETHER + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/********************************************************************************************************************//** + * @brief After ETHERC, EDMAC and PHY-LSI are reset in software, an auto negotiation of PHY-LSI is begun. + * Afterwards, the link signal change interrupt is permitted. Implements @ref ether_api_t::open. + * + * @retval FSP_SUCCESS Channel opened successfully. + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block or configuration structure is NULL. + * @retval FSP_ERR_ALREADY_OPEN Control block has already been opened or channel is being used by another + * instance. Call close() then open() to reconfigure. + * @retval FSP_ERR_ETHER_ERROR_PHY_COMMUNICATION Initialization of PHY-LSI failed. + * @retval FSP_ERR_INVALID_CHANNEL Invalid channel number is given. + * @retval FSP_ERR_INVALID_POINTER Pointer to extend config structure or MAC address is NULL. + * @retval FSP_ERR_INVALID_ARGUMENT Interrupt is not enabled. + * @retval FSP_ERR_ETHER_PHY_ERROR_LINK Initialization of PHY-LSI failed. + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_Open (ether_ctrl_t * const p_ctrl, ether_cfg_t const * const p_cfg) +{ + fsp_err_t err = FSP_SUCCESS; + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) p_ctrl; + ether_extended_cfg_t * p_ether_extended_cfg; + R_ETHERC0_Type * p_reg_etherc; + R_ETHERC_EDMAC_Type * p_reg_edmac; + + fsp_err_t phy_ret; + +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + + /** Check parameters. */ + err = ether_open_param_check(p_instance_ctrl, p_cfg); /** check arguments */ + ETHER_ERROR_RETURN((FSP_SUCCESS == err), err); +#endif + ETHER_ERROR_RETURN((ETHER_OPEN != p_instance_ctrl->open), FSP_ERR_ALREADY_OPEN); + + p_ether_extended_cfg = (ether_extended_cfg_t *) p_cfg->p_extend; + + /** Make sure this channel exists. */ + p_instance_ctrl->p_reg_etherc = ((R_ETHERC0_Type *) (R_ETHERC0_BASE + (ETHER_ETHERC_REG_SIZE * p_cfg->channel))); + p_instance_ctrl->p_reg_edmac = + ((R_ETHERC_EDMAC_Type *) (R_ETHERC_EDMAC_BASE + (ETHER_ETHERC_EDMAC_REG_SIZE * p_cfg->channel))); + + p_reg_etherc = p_instance_ctrl->p_reg_etherc; + p_reg_edmac = p_instance_ctrl->p_reg_edmac; + + /* Initialize configuration of Ethernet module. */ + p_instance_ctrl->p_ether_cfg = p_cfg; + + /* Initialize the flags */ + p_instance_ctrl->link_establish_status = ETHER_LINK_ESTABLISH_STATUS_DOWN; + p_instance_ctrl->magic_packet = ETHER_MAGIC_PACKET_NOT_DETECTED; + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_NO_CHANGE; + p_instance_ctrl->previous_link_status = ETHER_PREVIOUS_LINK_STATUS_DOWN; + + /* Initialize the transmit and receive descriptor */ + memset(p_ether_extended_cfg->p_rx_descriptors, + 0x00, + sizeof(ether_instance_descriptor_t) * + p_instance_ctrl->p_ether_cfg->num_rx_descriptors); + memset(p_ether_extended_cfg->p_tx_descriptors, + 0x00, + sizeof(ether_instance_descriptor_t) * + p_instance_ctrl->p_ether_cfg->num_tx_descriptors); + + /* Initialize the Ethernet buffer */ + ether_init_buffers(p_instance_ctrl); + + /* Set callback and context pointers, if configured */ + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + R_BSP_MODULE_START(FSP_IP_ETHER, p_instance_ctrl->p_ether_cfg->channel); + + /* Software reset */ + ether_reset_mac(p_instance_ctrl->p_reg_edmac); + + /* Setting the padding function */ + ether_configure_padding(p_instance_ctrl); + + /* Software reset the PHY */ + phy_ret = p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_api->open( + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_ctrl, + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_cfg); + +#if !ETHER_PHY_CFG_INIT_PHY_LSI_AUTOMATIC + + /* Initialize the PHY */ + if (FSP_SUCCESS == phy_ret) + { + phy_ret = p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_api->chipInit( + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_ctrl, + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_cfg); + } +#endif + + if (FSP_SUCCESS == phy_ret) + { + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_api->startAutoNegotiate( + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_ctrl); + + /* Clear all ETHERC status BFR, PSRTO, LCHNG, MPD, ICD */ + p_reg_etherc->ECSR = ETHER_ETHERC_INTERRUPT_FACTOR_ALL; + + /* Clear all EDMAC status bits */ + p_reg_edmac->EESR = ETHER_EDMAC_INTERRUPT_FACTOR_ALL; + +#if (ETHER_CFG_USE_LINKSTA == 1) + + /* Enable interrupts of interest only. */ + p_reg_etherc->ECSIPR_b.LCHNGIP = 1; +#endif + + p_reg_edmac->EESIPR_b.ECIIP = 1; + + /* Set Ethernet interrupt level and enable */ + ether_enable_icu(p_instance_ctrl); + + p_instance_ctrl->open = ETHER_OPEN; + + err = FSP_SUCCESS; + } + else + { + if (FSP_ERR_ETHER_PHY_ERROR_LINK == phy_ret) + { + err = FSP_ERR_ETHER_ERROR_PHY_COMMUNICATION; + } + else + { + err = phy_ret; + } + } + + return err; +} /* End of function R_ETHER_Open() */ + +/********************************************************************************************************************//** + * @brief Disables interrupts. Removes power and releases hardware lock. Implements @ref ether_api_t::close. + * + * @retval FSP_SUCCESS Channel successfully closed. + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened + * + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_Close (ether_ctrl_t * const p_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) p_ctrl; + R_ETHERC0_Type * p_reg_etherc; + R_ETHERC_EDMAC_Type * p_reg_edmac; + +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN(ETHER_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + p_reg_etherc = (R_ETHERC0_Type *) p_instance_ctrl->p_reg_etherc; + p_reg_edmac = (R_ETHERC_EDMAC_Type *) p_instance_ctrl->p_reg_edmac; + + /* Disable Ethernet interrupt. */ + ether_disable_icu(p_instance_ctrl); + + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_api->close( + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_ctrl); + + p_reg_etherc->ECSIPR_b.LCHNGIP = 0; + p_reg_edmac->EESIPR_b.ECIIP = 0; + + /* Disable TE and RE */ + p_reg_etherc->ECMR = ETHER_ETHERC_ECMR_MODE_CLEAR; + + /* Initialize the flags */ + p_instance_ctrl->link_establish_status = ETHER_LINK_ESTABLISH_STATUS_DOWN; + p_instance_ctrl->magic_packet = ETHER_MAGIC_PACKET_NOT_DETECTED; + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_NO_CHANGE; +#if (ETHER_CFG_USE_LINKSTA == 0) + p_instance_ctrl->previous_link_status = ETHER_PREVIOUS_LINK_STATUS_DOWN; +#endif + + /** Remove power to the channel. */ + R_BSP_MODULE_STOP(FSP_IP_ETHER, p_instance_ctrl->p_ether_cfg->channel); + + /** Clear configure block parameters. */ + p_instance_ctrl->p_ether_cfg = NULL; + + /** Mark the channel not open so other APIs cannot use it. */ + p_instance_ctrl->open = 0U; + + return err; +} /* End of function R_ETHER_Close() */ + +/********************************************************************************************************************//** + * @brief Move to the next buffer in the circular receive buffer list. Implements @ref ether_api_t::bufferRelease. + * + * @retval FSP_SUCCESS Processing completed successfully. + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened + * @retval FSP_ERR_ETHER_ERROR_LINK Auto-negotiation is not completed, and reception is not enabled. + * @retval FSP_ERR_ETHER_ERROR_MAGIC_PACKET_MODE As a Magic Packet is being detected, transmission and reception is + * not enabled. + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_BufferRelease (ether_ctrl_t * const p_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) p_ctrl; + R_ETHERC_EDMAC_Type * p_reg_edmac; + + uint32_t status; + + /* Check argument */ +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN(ETHER_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* When the Link up processing is not completed, return error */ + ETHER_ERROR_RETURN(ETHER_LINK_ESTABLISH_STATUS_UP == p_instance_ctrl->link_establish_status, + FSP_ERR_ETHER_ERROR_LINK); + + /* In case of detection mode of magic packet, return error. */ + ETHER_ERROR_RETURN(0 == ether_check_magic_packet_detection_bit(p_instance_ctrl), + FSP_ERR_ETHER_ERROR_MAGIC_PACKET_MODE); + + /* When receive data exists */ + if (ETHER_RD0_RACT != (p_instance_ctrl->p_rx_descriptor->status & ETHER_RD0_RACT)) + { + /* Reset current descriptor */ + status = ETHER_RD0_RFP1; + status |= ETHER_RD0_RFP0; + status |= ETHER_RD0_RFE; + status |= ETHER_RD0_RFS9_RFOVER; + status |= ETHER_RD0_RFS8_RAD; + status |= ETHER_RD0_RFS7_RMAF; + status |= ETHER_RD0_RFS4_RRF; + status |= ETHER_RD0_RFS3_RTLF; + status |= ETHER_RD0_RFS2_RTSF; + status |= ETHER_RD0_RFS1_PRE; + status |= ETHER_RD0_RFS0_CERF; + + p_instance_ctrl->p_rx_descriptor->status &= (~status); + + /* Enable current descriptor */ + p_instance_ctrl->p_rx_descriptor->status |= ETHER_RD0_RACT; + + /* Move to next descriptor */ + p_instance_ctrl->p_rx_descriptor = p_instance_ctrl->p_rx_descriptor->p_next; + } + + p_reg_edmac = (R_ETHERC_EDMAC_Type *) p_instance_ctrl->p_reg_edmac; + + if (ETHER_EDMAC_EDRRR_RECEIVE_REQUEST != p_reg_edmac->EDRRR) + { + /* Restart if stopped */ + p_reg_edmac->EDRRR = ETHER_EDMAC_EDRRR_RECEIVE_REQUEST; + } + + err = FSP_SUCCESS; + + return err; +} /* End of function R_ETHER_BufferRelease() */ + +/********************************************************************************************************************//** + * @brief Change the buffer pointer of the current rx buffer descriptor. Implements @ref ether_api_t::rxBufferUpdate. + * + * @retval FSP_SUCCESS Processing completed successfully. + * @retval FSP_ERR_ASSERTION A pointer argument is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_INVALID_POINTER The pointer of buffer is NULL or not aligned on a 32-bit boundary. + * @retval FSP_ERR_INVALID_MODE Driver is configured to non zero copy mode. + * @retval FSP_ERR_ETHER_RECEIVE_BUFFER_ACTIVE All descriptor is active. + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_RxBufferUpdate (ether_ctrl_t * const p_ctrl, void * const p_buffer) +{ + fsp_err_t err = FSP_SUCCESS; + R_ETHERC_EDMAC_Type * p_reg_edmac; + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) p_ctrl; + uint32_t status; + + /* Check argument */ +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN(ETHER_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + ETHER_ERROR_RETURN(NULL != p_buffer, FSP_ERR_INVALID_POINTER); + ETHER_ERROR_RETURN(0 == ((uint32_t) p_buffer & (uint32_t) ETHER_BUFFER_32BYTE_ALIGNMENT_MASK), + FSP_ERR_INVALID_POINTER); + ETHER_ERROR_RETURN(ETHER_ZEROCOPY_ENABLE == p_instance_ctrl->p_ether_cfg->zerocopy, FSP_ERR_INVALID_MODE); +#endif + + if (ETHER_RD0_RACT != (p_instance_ctrl->p_rx_descriptor->status & ETHER_RD0_RACT)) + { + p_instance_ctrl->p_rx_descriptor->p_buffer = p_buffer; + + /* Reset current descriptor */ + status = ETHER_RD0_RFP1; + status |= ETHER_RD0_RFP0; + status |= ETHER_RD0_RFE; + status |= ETHER_RD0_RFS9_RFOVER; + status |= ETHER_RD0_RFS8_RAD; + status |= ETHER_RD0_RFS7_RMAF; + status |= ETHER_RD0_RFS4_RRF; + status |= ETHER_RD0_RFS3_RTLF; + status |= ETHER_RD0_RFS2_RTSF; + status |= ETHER_RD0_RFS1_PRE; + status |= ETHER_RD0_RFS0_CERF; + + p_instance_ctrl->p_rx_descriptor->status &= (~status); + + /* Enable current descriptor */ + p_instance_ctrl->p_rx_descriptor->status |= ETHER_RD0_RACT; + + /* Move to next descriptor */ + p_instance_ctrl->p_rx_descriptor = p_instance_ctrl->p_rx_descriptor->p_next; + + p_reg_edmac = (R_ETHERC_EDMAC_Type *) p_instance_ctrl->p_reg_edmac; + + if (ETHER_EDMAC_EDRRR_RECEIVE_REQUEST != p_reg_edmac->EDRRR) + { + /* Restart if stopped */ + p_reg_edmac->EDRRR = ETHER_EDMAC_EDRRR_RECEIVE_REQUEST; + } + } + else + { + err = FSP_ERR_ETHER_RECEIVE_BUFFER_ACTIVE; + } + + return err; +} + +/********************************************************************************************************************//** + * @brief The Link up processing, the Link down processing, and the magic packet detection processing are executed. + * Implements @ref ether_api_t::linkProcess. + * + * @retval FSP_SUCCESS Link is up. + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_ETHER_ERROR_LINK Link is down. + * @retval FSP_ERR_ETHER_ERROR_PHY_COMMUNICATION When reopening the PHY interface initialization of the PHY-LSI failed. + * @retval FSP_ERR_ALREADY_OPEN When reopening the PHY interface it was already opened. + * @retval FSP_ERR_INVALID_CHANNEL When reopening the PHY interface an invalid channel was passed. + * @retval FSP_ERR_INVALID_POINTER When reopening the PHY interface the MAC address pointer was NULL. + * @retval FSP_ERR_INVALID_ARGUMENT When reopening the PHY interface the interrupt was not enabled. + * @retval FSP_ERR_ETHER_PHY_ERROR_LINK Initialization of the PHY-LSI failed. + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_LinkProcess (ether_ctrl_t * const p_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) p_ctrl; + R_ETHERC0_Type * p_reg_etherc; + + ether_callback_args_t callback_arg; + ether_cfg_t const * p_ether_cfg; + volatile ether_previous_link_status_t previous_link_status; + ether_extended_cfg_t * p_ether_extended_cfg; + +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN(ETHER_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + p_ether_extended_cfg = (ether_extended_cfg_t *) p_instance_ctrl->p_ether_cfg->p_extend; + + /* When the magic packet is detected. */ + if (ETHER_MAGIC_PACKET_DETECTED == p_instance_ctrl->magic_packet) + { + p_instance_ctrl->magic_packet = ETHER_MAGIC_PACKET_NOT_DETECTED; + + /* If a callback is provided, then call it with callback argument. */ + if (NULL != p_instance_ctrl->p_callback) + { + callback_arg.channel = p_instance_ctrl->p_ether_cfg->channel; + callback_arg.event = ETHER_EVENT_WAKEON_LAN; + callback_arg.status_ecsr = 0; + callback_arg.status_eesr = 0; + callback_arg.p_context = p_instance_ctrl->p_ether_cfg->p_context; + ether_call_callback(p_instance_ctrl, &callback_arg); + } + + /* + * After the close function is called, the open function is called + * to have to set ETHERC to a usual operational mode + * to usually communicate after magic packet is detected. + *//* back up previous_link_status */ + previous_link_status = p_instance_ctrl->previous_link_status; + + p_ether_cfg = p_instance_ctrl->p_ether_cfg; + + err = R_ETHER_Close((ether_ctrl_t *) p_instance_ctrl); + ETHER_ERROR_RETURN(FSP_SUCCESS == err, err); + + err = R_ETHER_Open((ether_ctrl_t *) p_instance_ctrl, (ether_cfg_t *) p_ether_cfg); + ETHER_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* restore previous_link_status */ + p_instance_ctrl->previous_link_status = previous_link_status; + } + +#if (ETHER_CFG_USE_LINKSTA == 0) + err = ether_link_status_check(p_instance_ctrl); + + /* The state of the link status in PHY-LSI is confirmed and Link Up/Down is judged. */ + if (FSP_SUCCESS == err) + { + /* When becoming Link up */ + if (ETHER_PREVIOUS_LINK_STATUS_DOWN == p_instance_ctrl->previous_link_status) + { + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_LINK_UP; + + /* Update Link status */ + p_instance_ctrl->previous_link_status = ETHER_PREVIOUS_LINK_STATUS_UP; + } + } + else + { + /* When becoming Link down */ + if (ETHER_PREVIOUS_LINK_STATUS_UP == p_instance_ctrl->previous_link_status) + { + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_LINK_DOWN; + + /* Update Link status */ + p_instance_ctrl->previous_link_status = ETHER_PREVIOUS_LINK_STATUS_DOWN; + } + } +#endif + + /* When the link is up */ + if (ETHER_LINK_CHANGE_LINK_UP == p_instance_ctrl->link_change) + { +#if (ETHER_CFG_USE_LINKSTA == 1) + + /* + * The Link Up/Down is confirmed by the Link Status bit of PHY register1, + * because the LINK signal of PHY-LSI is used for LED indicator, and + * isn't used for notifing the Link Up/Down to external device. + */ + err = ether_link_status_check(p_instance_ctrl); + + if (FSP_SUCCESS == err) + { +#endif + + /* + * The status of the LINK signal became "link-up" even if PHY-LSI did not detect "link-up" + * after a reset. To avoid this wrong detection, processing in R_ETHER_LinkProcess has been modified to + * clear the flag after link-up is confirmed in R_ETHER_CheckLink_ZC. + */ +#if (ETHER_CFG_USE_LINKSTA == 1) + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_LINK_DOWN; +#elif (ETHER_CFG_USE_LINKSTA == 0) + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_NO_CHANGE; +#endif + + /* Initialize the transmit and receive descriptor */ + memset(p_ether_extended_cfg->p_rx_descriptors, + 0x00, + sizeof(ether_instance_descriptor_t) * p_instance_ctrl->p_ether_cfg->num_rx_descriptors); + memset(p_ether_extended_cfg->p_tx_descriptors, + 0x00, + sizeof(ether_instance_descriptor_t) * p_instance_ctrl->p_ether_cfg->num_tx_descriptors); + + /* Initialize the Ethernet buffer */ + ether_init_buffers(p_instance_ctrl); + + p_instance_ctrl->link_establish_status = ETHER_LINK_ESTABLISH_STATUS_UP; + + /* + * ETHERC and EDMAC are set after ETHERC and EDMAC are reset in software + * and sending and receiving is permitted. + */ + ether_configure_mac(p_instance_ctrl, + p_instance_ctrl->p_ether_cfg->p_mac_address, + ETHER_NO_USE_MAGIC_PACKET_DETECT); + err = ether_do_link(p_instance_ctrl, ETHER_NO_USE_MAGIC_PACKET_DETECT); + + if (FSP_SUCCESS == err) + { + /* If a callback is provided, then call it with callback argument. */ + if (NULL != p_instance_ctrl->p_callback) + { + callback_arg.channel = p_instance_ctrl->p_ether_cfg->channel; + callback_arg.event = ETHER_EVENT_LINK_ON; + callback_arg.status_ecsr = 0; + callback_arg.status_eesr = 0; + callback_arg.p_context = p_instance_ctrl->p_ether_cfg->p_context; + ether_call_callback(p_instance_ctrl, &callback_arg); + } + } + else + { + /* When PHY auto-negotiation is not completed */ + p_instance_ctrl->link_establish_status = ETHER_LINK_ESTABLISH_STATUS_DOWN; + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_LINK_UP; + } + +#if (ETHER_CFG_USE_LINKSTA == 1) + } + else + { + /* no process */ + } +#endif + } + /* When the link is down */ + else if (ETHER_LINK_CHANGE_LINK_DOWN == p_instance_ctrl->link_change) + { + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_NO_CHANGE; + +#if (ETHER_CFG_USE_LINKSTA == 1) + + /* + * The Link Up/Down is confirmed by the Link Status bit of PHY register1, + * because the LINK signal of PHY-LSI is used for LED indicator, and + * isn't used for notifying the Link Up/Down to external device. + */ + err = ether_link_status_check(p_instance_ctrl); + if (FSP_ERR_ETHER_ERROR_LINK == err) + { +#endif + + p_reg_etherc = (R_ETHERC0_Type *) p_instance_ctrl->p_reg_etherc; + + /* Disable receive and transmit. */ + p_reg_etherc->ECMR_b.RE = 0; + p_reg_etherc->ECMR_b.TE = 0; + + p_instance_ctrl->link_establish_status = ETHER_LINK_ESTABLISH_STATUS_DOWN; + + /* If a callback is provided, then call it with callback argument. */ + if (NULL != p_instance_ctrl->p_callback) + { + callback_arg.channel = p_instance_ctrl->p_ether_cfg->channel; + callback_arg.event = ETHER_EVENT_LINK_OFF; + callback_arg.status_ecsr = 0; + callback_arg.status_eesr = 0; + callback_arg.p_context = p_instance_ctrl->p_ether_cfg->p_context; + ether_call_callback(p_instance_ctrl, &callback_arg); + } + +#if (ETHER_CFG_USE_LINKSTA == 1) + } + else + { + ; /* no operation */ + } +#endif + } + else + { + ; /* no operation */ + } + + return err; +} /* End of function R_ETHER_LinkProcess() */ + +/********************************************************************************************************************//** + * @brief The setting of ETHERC is changed from normal sending and receiving mode to magic packet detection mode. + * Implements @ref ether_api_t::wakeOnLANEnable. + * + * @retval FSP_SUCCESS Processing completed successfully. + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_ETHER_ERROR_LINK Auto-negotiation is not completed, and reception is not enabled. + * @retval FSP_ERR_ETHER_PHY_ERROR_LINK Initialization of PHY-LSI failed. + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_WakeOnLANEnable (ether_ctrl_t * const p_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) p_ctrl; + +#if (ETHER_CFG_USE_LINKSTA == 1) + R_ETHERC0_Type * p_reg_etherc; +#endif + + /* Check argument */ +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN(ETHER_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* When the Link up processing is not completed, return error */ + ETHER_ERROR_RETURN(ETHER_LINK_ESTABLISH_STATUS_UP == p_instance_ctrl->link_establish_status, + FSP_ERR_ETHER_ERROR_LINK); + + /* When the Link up processing is completed */ + /* Change to the magic packet detection mode. */ + ether_configure_mac(p_instance_ctrl, p_instance_ctrl->p_ether_cfg->p_mac_address, ETHER_USE_MAGIC_PACKET_DETECT); + err = ether_do_link(p_instance_ctrl, ETHER_USE_MAGIC_PACKET_DETECT); + if (FSP_SUCCESS == err) + { +#if (ETHER_CFG_USE_LINKSTA == 1) + p_reg_etherc = (R_ETHERC0_Type *) p_instance_ctrl->p_reg_etherc; + + /* It is confirmed not to become Link down while changing the setting. */ + if (ETHER_CFG_LINK_PRESENT == p_reg_etherc->PSR_b.LMON) + { + err = FSP_SUCCESS; + } + else + { + err = FSP_ERR_ETHER_ERROR_LINK; + } + +#else + + /* It is confirmed not to become Link down while changing the setting. */ + err = ether_link_status_check(p_instance_ctrl); +#endif + } + else + { + err = FSP_ERR_ETHER_ERROR_LINK; + } + + return err; +} /* End of function R_ETHER_WakeOnLANEnable() */ + +/********************************************************************************************************************//** + * @brief Receive Ethernet frame. Receives data to the location specified by the pointer to the receive buffer. + * In zero copy mode, the address of the receive buffer is returned. + * In non zero copy mode, the received data in the internal buffer is copied to the pointer passed by the argument. + * Implements @ref ether_api_t::read. + * + * @retval FSP_SUCCESS Processing completed successfully. + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_ETHER_ERROR_NO_DATA There is no data in receive buffer. + * @retval FSP_ERR_ETHER_ERROR_LINK Auto-negotiation is not completed, and reception is not enabled. + * @retval FSP_ERR_ETHER_ERROR_MAGIC_PACKET_MODE As a Magic Packet is being detected, transmission and reception + * is not enabled. + * @retval FSP_ERR_ETHER_ERROR_FILTERING Multicast Frame filter is enable, and Multicast Address Frame is + * received. + * @retval FSP_ERR_INVALID_POINTER Value of the pointer is NULL. + * + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_Read (ether_ctrl_t * const p_ctrl, void * const p_buffer, uint32_t * const length_bytes) +{ + fsp_err_t err = FSP_SUCCESS; + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) p_ctrl; + uint8_t * p_read_buffer = NULL; /* Buffer location controlled by the Ethernet driver */ + uint32_t received_size = ETHER_NO_DATA; + uint8_t ** pp_read_buffer = (uint8_t **) p_buffer; + + /* Check argument */ +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN(ETHER_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + ETHER_ERROR_RETURN(NULL != p_buffer, FSP_ERR_INVALID_POINTER); + ETHER_ERROR_RETURN(NULL != length_bytes, FSP_ERR_INVALID_POINTER); +#endif + + /* (1) Retrieve the receive buffer location controlled by the descriptor. */ + /* When the Link up processing is not completed, return error */ + ETHER_ERROR_RETURN(ETHER_LINK_ESTABLISH_STATUS_UP == p_instance_ctrl->link_establish_status, + FSP_ERR_ETHER_ERROR_LINK); + + /* In case of detection mode of magic packet, return error. */ + ETHER_ERROR_RETURN(0 == ether_check_magic_packet_detection_bit(p_instance_ctrl), + FSP_ERR_ETHER_ERROR_MAGIC_PACKET_MODE); + + while (FSP_SUCCESS == err) + { + /* When receive data exists. */ + + if (ETHER_RD0_RACT != (p_instance_ctrl->p_rx_descriptor->status & ETHER_RD0_RACT)) + { + /* Check multicast is detected when multicast frame filter is enabled */ + + if (ETHER_MULTICAST_DISABLE == p_instance_ctrl->p_ether_cfg->multicast) + { + if (ETHER_RD0_RFS7_RMAF == (p_instance_ctrl->p_rx_descriptor->status & ETHER_RD0_RFS7_RMAF)) + { + /* The buffer is released at the multicast frame detect. */ + + err = R_ETHER_BufferRelease((ether_ctrl_t *) p_instance_ctrl); + + if (FSP_SUCCESS == err) + { + err = FSP_ERR_ETHER_ERROR_FILTERING; + } + + break; + } + } + + if (ETHER_RD0_RFE == (p_instance_ctrl->p_rx_descriptor->status & ETHER_RD0_RFE)) + { + /* The buffer is released at the error. */ + err = R_ETHER_BufferRelease((ether_ctrl_t *) p_instance_ctrl); + } + else + { + /** + * Pass the pointer to received data to application. This is + * zero-copy operation. + */ + p_read_buffer = p_instance_ctrl->p_rx_descriptor->p_buffer; + + /* Get bytes received */ + received_size = + (uint32_t) (p_instance_ctrl->p_rx_descriptor->size + + (uint16_t) p_instance_ctrl->p_ether_cfg->padding); + break; + } + } + else + { + break; + } + } + + if (FSP_SUCCESS == err) + { + /* When there is data to receive */ + if (received_size > ETHER_NO_DATA) + { + if (ETHER_ZEROCOPY_DISABLE == p_instance_ctrl->p_ether_cfg->zerocopy) + { + /* (2) Copy the data read from the receive buffer which is controlled + * by the descriptor to the buffer which is specified by the user (up to 1024 bytes). */ + memcpy(p_buffer, p_read_buffer, received_size); + + /* (3) Read the receive data from the receive buffer controlled by the descriptor, + * and then release the receive buffer. */ + err = R_ETHER_BufferRelease((ether_ctrl_t *) p_instance_ctrl); + } + else + { + *pp_read_buffer = p_read_buffer; + } + + *length_bytes = received_size; + } + /* When there is no data to receive */ + else + { + err = FSP_ERR_ETHER_ERROR_NO_DATA; + } + } + + return err; +} /* End of function R_ETHER_Read() */ + +/********************************************************************************************************************//** + * @brief Transmit Ethernet frame. Transmits data from the location specified by the pointer to the transmit + * buffer, with the data size equal to the specified frame length. + * In the non zero copy mode, transmits data after being copied to the internal buffer. + * Implements @ref ether_api_t::write. + * + * @retval FSP_SUCCESS Processing completed successfully. + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_ETHER_ERROR_LINK Auto-negotiation is not completed, and reception is not enabled. + * @retval FSP_ERR_ETHER_ERROR_MAGIC_PACKET_MODE As a Magic Packet is being detected, transmission and reception + * is not enabled. + * @retval FSP_ERR_ETHER_ERROR_TRANSMIT_BUFFER_FULL Transmit buffer is not empty. + * @retval FSP_ERR_INVALID_POINTER Value of the pointer is NULL. + * @retval FSP_ERR_INVALID_ARGUMENT Value of the send frame size is out of range. + * + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_Write (ether_ctrl_t * const p_ctrl, void * const p_buffer, uint32_t const frame_length) +{ + fsp_err_t err = FSP_SUCCESS; + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) p_ctrl; + R_ETHERC_EDMAC_Type * p_reg_edmac; + + uint8_t * p_write_buffer; + uint32_t write_buffer_size; + + /* Check argument */ +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN(ETHER_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + ETHER_ERROR_RETURN(NULL != p_buffer, FSP_ERR_INVALID_POINTER); + ETHER_ERROR_RETURN((ETHER_MINIMUM_FRAME_SIZE <= frame_length) && (ETHER_MAXIMUM_FRAME_SIZE >= frame_length), + FSP_ERR_INVALID_ARGUMENT); +#endif + + /* When the Link up processing is not completed, return error */ + ETHER_ERROR_RETURN(ETHER_LINK_ESTABLISH_STATUS_UP == p_instance_ctrl->link_establish_status, + FSP_ERR_ETHER_ERROR_LINK); + + /* In case of detection mode of magic packet, return error. */ + ETHER_ERROR_RETURN(0 == ether_check_magic_packet_detection_bit(p_instance_ctrl), + FSP_ERR_ETHER_ERROR_MAGIC_PACKET_MODE); + + if (ETHER_ZEROCOPY_DISABLE == p_instance_ctrl->p_ether_cfg->zerocopy) + { + /* (1) Retrieve the transmit buffer location controlled by the descriptor. */ + err = ether_buffer_get(p_instance_ctrl, (void **) &p_write_buffer, &write_buffer_size); + + /* Writing to the transmit buffer (buf) is enabled. */ + if (FSP_SUCCESS == err) + { + if (write_buffer_size < frame_length) + { + err = FSP_ERR_ETHER_ERROR_TRANSMIT_BUFFER_FULL; /* Transmit buffer overflow */ + } + else + { + /* Write the transmit data to the transmit buffer. */ + + /* (2) Write the data to the transmit buffer controlled by the descriptor. */ + memcpy(p_write_buffer, p_buffer, frame_length); + } + } + } + + /* Writing to the transmit buffer (buf) is enabled. */ + if (FSP_SUCCESS == err) + { + /* (3) Enable the EDMAC to transmit data in the transmit buffer. */ + /* When the Link up processing is not completed, return error */ + + /* The data of the buffer is made active. */ + if (ETHER_ZEROCOPY_ENABLE == p_instance_ctrl->p_ether_cfg->zerocopy) + { + p_instance_ctrl->p_tx_descriptor->p_buffer = (uint8_t *) p_buffer; + } + + p_instance_ctrl->p_tx_descriptor->buffer_size = (uint16_t) frame_length; + p_instance_ctrl->p_tx_descriptor->status &= (~(ETHER_TD0_TFP1 | ETHER_TD0_TFP0)); + p_instance_ctrl->p_tx_descriptor->status |= ((ETHER_TD0_TFP1 | ETHER_TD0_TFP0) | ETHER_TD0_TACT); + p_instance_ctrl->p_tx_descriptor = p_instance_ctrl->p_tx_descriptor->p_next; + + p_reg_edmac = (R_ETHERC_EDMAC_Type *) p_instance_ctrl->p_reg_edmac; + + if (ETHER_EDMAC_EDTRR_TRANSMIT_REQUEST != p_reg_edmac->EDTRR) + { + /* Restart if stopped */ + p_reg_edmac->EDTRR = ETHER_EDMAC_EDTRR_TRANSMIT_REQUEST; + } + } + + return err; +} /* End of function R_ETHER_Write() */ + +/**********************************************************************************************************************//** + * Provides status of Ethernet driver in the user provided pointer. Implements @ref ether_api_t::txStatusGet. + * + * @retval FSP_SUCCESS Transmit buffer address is stored in provided p_buffer_address. + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_INVALID_POINTER p_status is NULL. + * @retval FSP_ERR_NOT_FOUND Transmit buffer address has been overwritten in transmit descriptor. + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_TxStatusGet (ether_ctrl_t * const p_ctrl, void * const p_buffer_address) +{ + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) p_ctrl; + ether_extended_cfg_t * p_ether_extended_cfg; + R_ETHERC_EDMAC_Type * p_reg_edmac; + ether_instance_descriptor_t * p_descriptor; + uint8_t ** p_sent_buffer_address = (uint8_t **) p_buffer_address; + fsp_err_t err = FSP_ERR_NOT_FOUND; + +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN(ETHER_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + ETHER_ERROR_RETURN(NULL != p_buffer_address, FSP_ERR_INVALID_POINTER); +#endif + p_ether_extended_cfg = (ether_extended_cfg_t *) p_instance_ctrl->p_ether_cfg->p_extend; + + p_reg_edmac = (R_ETHERC_EDMAC_Type *) p_instance_ctrl->p_reg_edmac; + + p_descriptor = (ether_instance_descriptor_t *) p_reg_edmac->TDFAR; + + /* Descriptor is NULL, when no packet transmitted. */ + if (NULL != p_descriptor) + { + uint32_t num_tx_descriptors = p_instance_ctrl->p_ether_cfg->num_tx_descriptors; + ether_instance_descriptor_t * p_tx_descriptors = p_ether_extended_cfg->p_tx_descriptors; + + p_descriptor = (ether_instance_descriptor_t *) ((uint8_t *) p_descriptor - sizeof(ether_instance_descriptor_t)); + + if (p_descriptor < p_tx_descriptors) + { + p_descriptor = &p_tx_descriptors[num_tx_descriptors - 1]; + } + + /* Check that the descriptor is not overridden. */ + if ((NULL != p_descriptor->p_buffer) && (ETHER_TD0_TACT != (p_descriptor->status & ETHER_TD0_TACT))) + { + *p_sent_buffer_address = p_descriptor->p_buffer; + err = FSP_SUCCESS; + } + else + { + ; + } + } + + return err; +} /* End of function R_ETHER_VersionGet() */ + +/*******************************************************************************************************************//** + * Updates the user callback with the option to provide memory for the callback argument structure. + * Implements @ref ether_api_t::callbackSet. + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL. + **********************************************************************************************************************/ +fsp_err_t R_ETHER_CallbackSet (ether_ctrl_t * const p_api_ctrl, + void ( * p_callback)(ether_callback_args_t *), + void const * const p_context, + ether_callback_args_t * const p_callback_memory) +{ + ether_instance_ctrl_t * p_ctrl = (ether_instance_ctrl_t *) p_api_ctrl; + +#if ETHER_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(ETHER_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + +#if BSP_TZ_SECURE_BUILD && BSP_FEATURE_ETHER_SUPPORTS_TZ_SECURE + + /* Get security state of p_callback */ + bool callback_is_secure = + (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE)); + + #if ETHER_CFG_PARAM_CHECKING_ENABLE + + /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */ + ether_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory, + CMSE_AU_NONSECURE); + FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY); + #endif +#endif + + /* Store callback and context */ +#if BSP_TZ_SECURE_BUILD && BSP_FEATURE_ETHER_SUPPORTS_TZ_SECURE + p_ctrl->p_callback = callback_is_secure ? p_callback : + (void (*)(ether_callback_args_t *))cmse_nsfptr_create(p_callback); +#else + p_ctrl->p_callback = p_callback; +#endif + p_ctrl->p_context = p_context; + p_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup ETHER) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + +/*******************************************************************************************************************//** + * @brief Parameter error check function for open. + * + * @param[in] p_instance_ctrl Pointer to the control block for the channel + * @param[in] p_cfg Pointer to the configuration structure specific to UART mode + * + * @retval FSP_SUCCESS No parameter error found + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block or configuration structure is NULL + * @retval FSP_ERR_INVALID_CHANNEL Invalid channel number is given. + * @retval FSP_ERR_INVALID_POINTER Pointer to MAC address is NULL. + * @retval FSP_ERR_INVALID_ARGUMENT Irq number lower then 0. + **********************************************************************************************************************/ +static fsp_err_t ether_open_param_check (ether_instance_ctrl_t const * const p_instance_ctrl, + ether_cfg_t const * const p_cfg) +{ + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN((NULL != p_cfg), FSP_ERR_INVALID_POINTER); + ETHER_ERROR_RETURN((NULL != p_cfg->p_mac_address), FSP_ERR_INVALID_POINTER); + ETHER_ERROR_RETURN((NULL != p_cfg->p_extend), FSP_ERR_INVALID_POINTER); + ETHER_ERROR_RETURN((BSP_FEATURE_ETHER_MAX_CHANNELS > p_cfg->channel), FSP_ERR_INVALID_CHANNEL); + ETHER_ERROR_RETURN((0 <= p_cfg->irq), FSP_ERR_INVALID_ARGUMENT); + ETHER_ERROR_RETURN((p_cfg->padding <= ETHER_PADDING_3BYTE), FSP_ERR_INVALID_ARGUMENT); + + if (p_cfg->padding != ETHER_PADDING_DISABLE) + { + ETHER_ERROR_RETURN((p_cfg->padding_offset <= ETHER_MAXIMUM_PADDING_OFFSET), FSP_ERR_INVALID_ARGUMENT); + } + + if (p_cfg->zerocopy == ETHER_ZEROCOPY_DISABLE) + { + ETHER_ERROR_RETURN((p_cfg->pp_ether_buffers != NULL), FSP_ERR_INVALID_ARGUMENT); + } + + return FSP_SUCCESS; +} + +#endif + +/*********************************************************************************************************************** + * Function Name: ether_reset_mac + * Description : The EDMAC and EtherC are reset through the software reset. + * Arguments : channel - + * ETHERC channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_reset_mac (R_ETHERC_EDMAC_Type * const p_reg) +{ + p_reg->EDMR_b.SWR = 1; + + /* + * Waiting time until the initialization of ETHERC and EDMAC is completed is 64 cycles + * in the clock conversion of an internal bus of EDMAC. + */ + R_BSP_SoftwareDelay(ETHER_ETHERC_INITIALIZATION_WAIT_CYCLE * BSP_DELAY_UNITS_SECONDS / SystemCoreClock + 1, + BSP_DELAY_UNITS_MICROSECONDS); +} /* End of function ether_reset_mac() */ + +/*********************************************************************************************************************** + * Function Name: ether_init_descriptors + * Description : The EDMAC descriptors and the driver buffers are initialized. + * Arguments : channel - + * ETHERC channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_init_descriptors (ether_instance_ctrl_t * const p_instance_ctrl) +{ + ether_instance_descriptor_t * p_descriptor = NULL; + uint32_t i; + ether_extended_cfg_t * p_ether_extended_cfg = (ether_extended_cfg_t *) p_instance_ctrl->p_ether_cfg->p_extend; + + /* Initialize the receive descriptors */ + for (i = 0; i < p_instance_ctrl->p_ether_cfg->num_rx_descriptors; i++) + { + p_descriptor = &p_ether_extended_cfg->p_rx_descriptors[i]; + p_descriptor->buffer_size = (uint16_t) p_instance_ctrl->p_ether_cfg->ether_buffer_size; + p_descriptor->size = 0; + p_descriptor->p_next = &p_ether_extended_cfg->p_rx_descriptors[(i + 1)]; + + if (NULL != p_instance_ctrl->p_ether_cfg->pp_ether_buffers) + { + p_descriptor->p_buffer = p_instance_ctrl->p_ether_cfg->pp_ether_buffers[i]; + p_descriptor->status = ETHER_RD0_RACT; + } + else + { + p_descriptor->p_buffer = NULL; + } + } + + if (NULL != p_descriptor) + { + /* The last descriptor points back to the start */ + p_descriptor->status |= ETHER_RD0_RDLE; + p_descriptor->p_next = &p_ether_extended_cfg->p_rx_descriptors[0]; + + /* Initialize application receive descriptor pointer */ + p_instance_ctrl->p_rx_descriptor = &p_ether_extended_cfg->p_rx_descriptors[0]; + } + + /* Initialize the transmit descriptors */ + for (i = 0; i < p_instance_ctrl->p_ether_cfg->num_tx_descriptors; i++) + { + p_descriptor = &p_ether_extended_cfg->p_tx_descriptors[i]; + p_descriptor->buffer_size = 1; /* Set a value equal to or greater than 1. (reference to UMH) + * When transmitting data, the value of size is set to the function argument + * R_ETHER_Write. */ + p_descriptor->size = 0; /* Reserved : The write value should be 0. (reference to UMH) */ + p_descriptor->status = 0; + p_descriptor->p_next = &p_ether_extended_cfg->p_tx_descriptors[(i + 1)]; + + if ((ETHER_ZEROCOPY_DISABLE == p_instance_ctrl->p_ether_cfg->zerocopy) && + (NULL != p_instance_ctrl->p_ether_cfg->pp_ether_buffers)) + { + p_descriptor->p_buffer = + p_instance_ctrl->p_ether_cfg->pp_ether_buffers[(p_instance_ctrl->p_ether_cfg->num_rx_descriptors + i)]; + } + else + { + p_descriptor->p_buffer = NULL; + } + } + + if (NULL != p_descriptor) + { + /* The last descriptor points back to the start */ + p_descriptor->status |= ETHER_TD0_TDLE; + p_descriptor->p_next = &p_ether_extended_cfg->p_tx_descriptors[0]; + + /* Initialize application transmit descriptor pointer */ + p_instance_ctrl->p_tx_descriptor = &p_ether_extended_cfg->p_tx_descriptors[0]; + } +} /* End of function ether_init_descriptors() */ + +/*********************************************************************************************************************** + * Function Name: ether_init_buffers + * Description : The driver buffers are initialized. + * Arguments : p_instance_ctrl - + * ETHERC control block. + * Return Value : none + ***********************************************************************************************************************/ +static void ether_init_buffers (ether_instance_ctrl_t * const p_instance_ctrl) +{ + uint32_t i; + uint32_t buffer_num; + + if (NULL != p_instance_ctrl->p_ether_cfg->pp_ether_buffers) + { + if (ETHER_ZEROCOPY_DISABLE == p_instance_ctrl->p_ether_cfg->zerocopy) + { + buffer_num = + (uint32_t) (p_instance_ctrl->p_ether_cfg->num_tx_descriptors + + p_instance_ctrl->p_ether_cfg->num_rx_descriptors); + } + else + { + buffer_num = (uint32_t) p_instance_ctrl->p_ether_cfg->num_rx_descriptors; + } + + for (i = 0; i < buffer_num; i++) + { + memset(p_instance_ctrl->p_ether_cfg->pp_ether_buffers[i], + 0x00, + p_instance_ctrl->p_ether_cfg->ether_buffer_size); + } + } +} /* End of function ether_init_buffers() */ + +/********************************************************************************************************************//** + * @brief Get Points to the buffer pointer used by the stack. + * @param[in] p_instance_ctrl Ethernet driver control block. + * @param[out] p_buffer Pointer to location to store the buffer pointer + * @param[out] p_buffer_size Pointer to location to store the buffer size + * @retval FSP_SUCCESS Processing completed successfully. + * @retval FSP_ERR_ETHER_ERROR_TRANSMIT_BUFFER_FULL Transmit buffer is not empty. + * + ***********************************************************************************************************************/ +static fsp_err_t ether_buffer_get (ether_instance_ctrl_t * const p_instance_ctrl, + void ** const p_buffer, + uint32_t * p_buffer_size) +{ + fsp_err_t err = FSP_SUCCESS; + + /* When the Link up processing is completed */ + /* All transmit buffers are full */ + if (ETHER_TD0_TACT == (p_instance_ctrl->p_tx_descriptor->status & ETHER_TD0_TACT)) + { + err = FSP_ERR_ETHER_ERROR_TRANSMIT_BUFFER_FULL; + } + else + { + /* Give application another buffer to work with */ + (*p_buffer) = p_instance_ctrl->p_tx_descriptor->p_buffer; + (*p_buffer_size) = p_instance_ctrl->p_ether_cfg->ether_buffer_size; + err = FSP_SUCCESS; + } + + return err; +} /* End of function ether_buffer_get() */ + +/*********************************************************************************************************************** + * Function Name: ether_config_ethernet + * Description : Configure the Ethernet Controller (EtherC) and the Ethernet + * Direct Memory Access controller (EDMAC). + * Arguments : channel - + * ETHERC channel number + * mode - + * The operational mode is specified. + * NO_USE_MAGIC_PACKET_DETECT (0) - Communicate mode usually + * USE_MAGIC_PACKET_DETECT (1) - Magic packet detection mode + * Return Value : none + ***********************************************************************************************************************/ +static void ether_config_ethernet (ether_instance_ctrl_t const * const p_instance_ctrl, const uint8_t mode) +{ + R_ETHERC0_Type * p_reg_etherc; + R_ETHERC_EDMAC_Type * p_reg_edmac; + +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + + /* Check argument */ + if ((NULL == p_instance_ctrl) || (ETHER_OPEN != p_instance_ctrl->open)) + { + return; + } +#endif + + p_reg_etherc = (R_ETHERC0_Type *) p_instance_ctrl->p_reg_etherc; + p_reg_edmac = (R_ETHERC_EDMAC_Type *) p_instance_ctrl->p_reg_edmac; + + /* Magic packet detection mode */ + if (ETHER_USE_MAGIC_PACKET_DETECT == mode) + { +#if (ETHER_CFG_USE_LINKSTA == 1) + p_reg_etherc->ECSIPR = (ETHER_ETHERC_INTERRUPT_ENABLE_LCHNG | ETHER_ETHERC_INTERRUPT_ENABLE_MPD); +#elif (ETHER_CFG_USE_LINKSTA == 0) + p_reg_etherc->ECSIPR_b.MPDIP = 1; +#endif + p_reg_edmac->EESIPR_b.ECIIP = 1; + } + /* Normal mode */ + else + { +#if (ETHER_CFG_USE_LINKSTA == 1) + + /* LINK Signal Change Interrupt Enable */ + p_reg_etherc->ECSR_b.LCHNG = 1; + p_reg_etherc->ECSIPR_b.LCHNGIP = 1; +#endif + p_reg_edmac->EESIPR_b.ECIIP = 1; + + /* Frame receive interrupt and frame transmit end interrupt */ + p_reg_edmac->EESIPR_b.FRIP = 1; /* Enable the frame receive interrupt. */ + p_reg_edmac->EESIPR_b.TCIP = 1; /* Enable the frame transmit end interrupt. */ + } + + /* Ethernet length 1514bytes + CRC and intergap is 96-bit time */ + p_reg_etherc->RFLR = ETHER_ETHERC_RFLR_DEFAULT_VALUE; /* Ethernet length (1514bytes) + CRC(4byte) */ + p_reg_etherc->IPGR = ETHER_ETHERC_IPGR_DEFAULT_VALUE; /* Interpacket Gap is 96-bit time */ + + /* Continuous reception number of Broadcast frame */ + p_reg_etherc->BCFRR = p_instance_ctrl->p_ether_cfg->broadcast_filter; + +#if ((defined(__GNUC__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || (defined(__ARMCC_VERSION) && \ + !defined(__ARM_BIG_ENDIAN)) || (defined(__ICCARM__) && (__LITTLE_ENDIAN__))) + + /* Set little endian mode */ + p_reg_edmac->EDMR_b.DE = 1; +#endif + + /* Initialize Rx descriptor list address */ + /* Casting the pointer to a uint32_t type is valid because the Renesas Compiler uses 4 bytes per pointer. */ + p_reg_edmac->RDLAR = (uint32_t) p_instance_ctrl->p_rx_descriptor; + + /* Initialize Tx descriptor list address */ + /* Casting the pointer to a uint32_t type is valid because the Renesas Compiler uses 4 bytes per pointer. */ + p_reg_edmac->TDLAR = (uint32_t) p_instance_ctrl->p_tx_descriptor; + + if (ETHER_MULTICAST_DISABLE == p_instance_ctrl->p_ether_cfg->multicast) + { + /* Reflect the EESR.RMAF bit status in the RD0.RFS bit in the receive descriptor */ + p_reg_edmac->TRSCER = ETHER_EDMAC_TRSCER_MULTICAST_DISABLE; + } + else + { + /* Don't reflect the EESR.RMAF bit status in the RD0.RFS bit in the receive descriptor */ + p_reg_edmac->TRSCER = ETHER_EDMAC_TRSCER_MULTICAST_ENABLE; + } + + /* Threshold of Tx_FIFO */ + /* To prevent a transmit underflow, setting the initial value (store and forward modes) is recommended. */ + p_reg_edmac->TFTR = ETHER_EDMAC_TFTR_STORE_AND_FORWARD_MODE; + + p_reg_edmac->FDR = BSP_FEATURE_ETHER_FIFO_DEPTH; + + /* Configure receiving method + * b0 RNR - Receive Request Bit Reset - Continuous reception of multiple frames is possible. + * b31:b1 Reserved set to 0 + */ + p_reg_edmac->RMCR = ETHER_EDMAC_RMCR_MULTIPLE_FRAMES_ENABLE; +} /* End of function ether_config_ethernet() */ + +/*********************************************************************************************************************** + * Function Name: ether_pause_resolution + * Description : Determines PAUSE frame generation and handling. Uses + * the resolution Table 28B-3 of IEEE 802.3-2008. + * Arguments : local_ability - + * local PAUSE capability (2 least significant bits) + * partner_ability - + * link partner PAUSE capability (2 least significant bits) + * *ptx_pause - + * pointer to location to store the result of the table lookup for transmit + * PAUSE. 1 is enable, 0 is disable. + * *prx_pause - + * pointer to location to store the result of the table lookup for receive + * PAUSE. 1 is enable, 0 is disable. + * Return Value : none + ***********************************************************************************************************************/ +static void ether_pause_resolution (uint32_t const local_ability, + uint32_t const partner_ability, + uint32_t * ptx_pause, + uint32_t * prx_pause) +{ + uint32_t i; + uint32_t ability_compare; + + /* + * Arrange the bits so that they correspond to the Table 28B-3 + * of the IEEE 802.3 values. + */ + ability_compare = + (uint32_t) (((local_ability & ETHER_LINK_RESOLUTION_ABILITY_MASK) << + ETHER_LINK_RESOLUTION_LOCAL_ABILITY_BITSHIFT) | + (partner_ability & ETHER_LINK_RESOLUTION_ABILITY_MASK)); + + /* Walk through the look up table */ + for (i = 0; i < ETHER_PAUSE_TABLE_ENTRIES; i++) + { + if ((ability_compare & pause_resolution[i].mask) == pause_resolution[i].value) + { + (*ptx_pause) = pause_resolution[i].transmit; + (*prx_pause) = pause_resolution[i].receive; + + return; + } + } +} /* End of function ether_pause_resolution() */ + +/*********************************************************************************************************************** + * Function Name: ether_configure_mac + * Description : Software reset is executed, and ETHERC and EDMAC are configured. + * Arguments : channel - + * ETHERC channel number + * mac_addr - + * The MAC address of ETHERC + * mode - + * The operational mode is specified. + * NO_USE_MAGIC_PACKET_DETECT (0) - Communicate mode usually + * USE_MAGIC_PACKET_DETECT (1) - Magic packet detection mode + * Return Value : none + ***********************************************************************************************************************/ +static void ether_configure_mac (ether_instance_ctrl_t * const p_instance_ctrl, + const uint8_t mac_addr[], + const uint8_t mode) +{ + R_ETHERC0_Type * p_reg_etherc; + uint32_t mac_h; + uint32_t mac_l; + +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + + /* Check argument */ + if ((NULL == p_instance_ctrl) || (ETHER_OPEN != p_instance_ctrl->open)) + { + return; + } +#endif + + p_reg_etherc = (R_ETHERC0_Type *) p_instance_ctrl->p_reg_etherc; + + /* Software reset */ + ether_reset_mac(p_instance_ctrl->p_reg_edmac); + + /* Setting the padding function */ + ether_configure_padding(p_instance_ctrl); + + /* Set MAC address */ + mac_h = (((((uint32_t) mac_addr[0] << 24) | ((uint32_t) mac_addr[1] << 16)) | ((uint32_t) mac_addr[2] << 8)) | + (uint32_t) mac_addr[3]); + + mac_l = (((uint32_t) mac_addr[4] << 8) | (uint32_t) mac_addr[5]); + + p_reg_etherc->MAHR = mac_h; + p_reg_etherc->MALR = mac_l; + + /* Initialize receive and transmit descriptors */ + ether_init_descriptors(p_instance_ctrl); + + /* Perform reset of hardware interface configuration */ + ether_config_ethernet(p_instance_ctrl, mode); +} /* End of function ether_configure_mac() */ + +/********************************************************************************************************************//** + * @brief Determines the partner PHY capability through auto-negotiation process. The link abilities + * are handled to determine duplex, speed and flow control (PAUSE frames). + * + * @param[in] p_instance_ctrl Pointer to the control block for the channel + * @param[in] mode The operational mode is specified. + * NO_USE_MAGIC_PACKET_DETECT (0) - Communicate mode usually + * USE_MAGIC_PACKET_DETECT (1) - Magic packet detection mode + * @retval FSP_SUCCESS Processing completed successfully. + * @retval FSP_ERR_ASSERTION Pointer to ETHER control block or configuration structure is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_ETHER_ERROR_LINK Auto-negotiation of PHY-LSI is not completed + * or result of Auto-negotiation is abnormal. + * + ***********************************************************************************************************************/ +static fsp_err_t ether_do_link (ether_instance_ctrl_t * const p_instance_ctrl, const uint8_t mode) +{ + fsp_err_t err; + R_ETHERC0_Type * p_reg_etherc; + R_ETHERC_EDMAC_Type * p_reg_edmac; + + uint32_t link_speed_duplex = 0; + uint32_t local_pause_bits = 0; + uint32_t partner_pause_bits = 0; + uint32_t transmit_pause_set = 0; + uint32_t receive_pause_set = 0; + uint32_t full_duplex = 0; + fsp_err_t link_result; + +#if (ETHER_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_ERROR_RETURN(ETHER_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + p_reg_etherc = (R_ETHERC0_Type *) p_instance_ctrl->p_reg_etherc; + p_reg_edmac = (R_ETHERC_EDMAC_Type *) p_instance_ctrl->p_reg_edmac; + + /* Set the link status */ + link_result = p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_api->linkPartnerAbilityGet( + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_ctrl, + &link_speed_duplex, + &local_pause_bits, + &partner_pause_bits); + + if (FSP_SUCCESS == link_result) + { + switch (link_speed_duplex) + { + /* Half duplex link */ + case ETHER_PHY_LINK_SPEED_100H: + { + p_reg_etherc->ECMR_b.DM = 0; + p_reg_etherc->ECMR_b.RTM = 1; + err = FSP_SUCCESS; + break; + } + + case ETHER_PHY_LINK_SPEED_10H: + { + p_reg_etherc->ECMR_b.DM = 0; + p_reg_etherc->ECMR_b.RTM = 0; + err = FSP_SUCCESS; + break; + } + + /* Full duplex link */ + case ETHER_PHY_LINK_SPEED_100F: + { + p_reg_etherc->ECMR_b.DM = 1; + p_reg_etherc->ECMR_b.RTM = 1; + full_duplex = 1; + err = FSP_SUCCESS; + break; + } + + case ETHER_PHY_LINK_SPEED_10F: + { + p_reg_etherc->ECMR_b.DM = 1; + p_reg_etherc->ECMR_b.RTM = 0; + full_duplex = 1; + err = FSP_SUCCESS; + break; + } + + default: + { + err = FSP_ERR_ETHER_ERROR_LINK; + break; + } + } + + /* At the communicate mode usually */ + if (FSP_SUCCESS == err) + { + if (ETHER_NO_USE_MAGIC_PACKET_DETECT == mode) + { + /* When pause frame is used */ + if ((full_duplex) && (ETHER_FLOW_CONTROL_ENABLE == p_instance_ctrl->p_ether_cfg->flow_control)) + { + /* Set automatic PAUSE for 512 bit-time */ + p_reg_etherc->APR = ETHER_ETHERC_APR_MAXIMUM_VALUE; + + /* Set unlimited retransmit of PAUSE frames */ + p_reg_etherc->TPAUSER = 0; + + /* PAUSE flow control FIFO settings. */ + p_reg_edmac->FCFTR = ETHER_ETHERC_FCFTR_MINIMUM_VALUE; + + /* Control of a PAUSE frame whose TIME parameter value is 0 is enabled. */ + p_reg_etherc->ECMR_b.ZPF = 1; + + /** + * Enable PAUSE for full duplex link depending on + * the pause resolution results + */ + ether_pause_resolution(local_pause_bits, partner_pause_bits, &transmit_pause_set, + &receive_pause_set); + + if (ETHER_PAUSE_XMIT_ON == transmit_pause_set) + { + /* Enable automatic PAUSE frame transmission */ + p_reg_etherc->ECMR_b.TXF = 1; + } + else + { + /* Disable automatic PAUSE frame transmission */ + p_reg_etherc->ECMR_b.TXF = 0; + } + + if (ETHER_PAUSE_RECV_ON == receive_pause_set) + { + /* Enable reception of PAUSE frames */ + p_reg_etherc->ECMR_b.RXF = 1; + } + else + { + /* Disable reception of PAUSE frames */ + p_reg_etherc->ECMR_b.RXF = 0; + } + } + /* When pause frame is not used */ + else + { + /* Disable PAUSE for half duplex link */ + p_reg_etherc->ECMR_b.TXF = 0; + p_reg_etherc->ECMR_b.RXF = 0; + } + + /* Set the promiscuous mode bit */ + p_reg_etherc->ECMR_b.PRM = p_instance_ctrl->p_ether_cfg->promiscuous; + + /* Enable receive and transmit. */ + p_reg_etherc->ECMR_b.RE = 1; + p_reg_etherc->ECMR_b.TE = 1; + + /* Enable EDMAC receive */ + p_reg_edmac->EDRRR = 0x1; + } + /* At the magic packet detection mode */ + else + { + /* The magic packet detection is permitted. */ + p_reg_etherc->ECMR_b.MPDE = 1; + + /* Because data is not transmitted for the magic packet detection waiting, + * only the reception is permitted. */ + p_reg_etherc->ECMR_b.RE = 1; + + /* + * The reception function of EDMAC keep invalidity + * because the receive data don't need to be read when the magic packet detection mode. + */ + } + } + } + else + { + err = FSP_ERR_ETHER_ERROR_LINK; + } + + return err; +} /* End of function ether_do_link() */ + +/*********************************************************************************************************************** + * Function Name: ether_check_magic_packet_detection_bit + * Description : + * Arguments : ether_instance_ctrl_t const * const p_instance_ctrl + * Return Value : 1: Magic Packet detection is enabled. + * 0: Magic Packet detection is disabled. + ***********************************************************************************************************************/ +static uint8_t ether_check_magic_packet_detection_bit (ether_instance_ctrl_t const * const p_instance_ctrl) +{ + R_ETHERC0_Type * p_reg_etherc = (R_ETHERC0_Type *) p_instance_ctrl->p_reg_etherc; + uint8_t ret = 0; + + /* The MPDE bit can be referred to only when ETHERC operates. */ + if ((1 == p_reg_etherc->ECMR_b.MPDE)) + { + ret = 1; + } + else + { + ret = 0; + } + + return ret; +} /* End of function ether_check_magic_packet_detection_bit() */ + +/*******************************************************************************************************************//** + * @brief Verifies the Etherent link is up or not. + * + * @param[in] p_instance_ctrl Pointer to the control block for the channel + * + * @retval FSP_SUCCESS: Link is up + * @retval FSP_ERR_ETHER_ERROR_LINK: Link is down + * @retval FSP_ERR_ETHER_PHY_ERROR_LINK Initialization of PHY-LSI failed. + **********************************************************************************************************************/ +static fsp_err_t ether_link_status_check (ether_instance_ctrl_t const * const p_instance_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + fsp_err_t link_status; + + link_status = p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_api->linkStatusGet( + p_instance_ctrl->p_ether_cfg->p_ether_phy_instance->p_ctrl); + + if (FSP_ERR_ETHER_PHY_ERROR_LINK == link_status) + { + /* Link is down */ + err = FSP_ERR_ETHER_ERROR_LINK; + } + else + { + /* Link is up */ + err = FSP_SUCCESS; + } + + return err; +} /* End of function ether_link_status_check() */ + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_instance_ctrl Pointer to ether instance control block + * @param[in] p_callback_args Pointer to callback args + **********************************************************************************************************************/ +static void ether_call_callback (ether_instance_ctrl_t * p_instance_ctrl, ether_callback_args_t * p_callback_args) +{ + ether_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. This allows callback arguments to be + * stored in non-secure memory so they can be accessed by a non-secure callback function. */ + ether_callback_args_t * p_args = p_instance_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->event = p_callback_args->event; + p_args->status_ecsr = p_callback_args->status_ecsr; + p_args->status_eesr = p_callback_args->status_eesr; + p_args->channel = p_instance_ctrl->p_ether_cfg->channel; + p_args->p_context = p_instance_ctrl->p_context; + +#if BSP_TZ_SECURE_BUILD && BSP_FEATURE_ETHER_SUPPORTS_TZ_SECURE + + /* p_callback can point to a secure function or a non-secure function. */ + if (!cmse_is_nsfptr(p_instance_ctrl->p_callback)) + { + /* If p_callback is secure, then the project does not need to change security state. */ + p_instance_ctrl->p_callback(p_args); + } + else + { + /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */ + ether_prv_ns_callback p_callback = (ether_prv_ns_callback) (p_instance_ctrl->p_callback); + p_callback(p_args); + } + +#else + + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */ + p_instance_ctrl->p_callback(p_args); +#endif + + if (NULL != p_instance_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_instance_ctrl->p_callback_memory = args; + } +} + +/*********************************************************************************************************************** + * Function Name: ether_eint_isr + * Description : Interrupt handler for Ethernet receive and transmit interrupts. + * Arguments : none + * Return Value : none + ***********************************************************************************************************************/ +void ether_eint_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + uint32_t status_ecsr; + uint32_t status_eesr; + + ether_callback_args_t callback_arg; + R_ETHERC0_Type * p_reg_etherc; + R_ETHERC_EDMAC_Type * p_reg_edmac; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + ether_instance_ctrl_t * p_instance_ctrl = (ether_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + p_reg_etherc = (R_ETHERC0_Type *) p_instance_ctrl->p_reg_etherc; + p_reg_edmac = (R_ETHERC_EDMAC_Type *) p_instance_ctrl->p_reg_edmac; + + status_ecsr = p_reg_etherc->ECSR; + status_eesr = p_reg_edmac->EESR; + + /* When the ETHERC status interrupt is generated */ + if (status_eesr & ETHER_EDMAC_INTERRUPT_FACTOR_ECI) + { +#if (ETHER_CFG_USE_LINKSTA == 1) + + /* When the link signal change interrupt is generated */ + if (ETHER_ETHERC_INTERRUPT_FACTOR_LCHNG == (status_ecsr & ETHER_ETHERC_INTERRUPT_FACTOR_LCHNG)) + { + /* The state of the link signal is confirmed and Link Up/Down is judged. */ + /* When becoming Link up */ + if (ETHER_CFG_LINK_PRESENT == p_reg_etherc->PSR_b.LMON) + { + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_LINK_UP; + } + /* When Link becomes down */ + else + { + p_instance_ctrl->link_change = ETHER_LINK_CHANGE_LINK_DOWN; + } + } +#endif + + /* When the Magic Packet detection interrupt is generated */ + if (ETHER_ETHERC_INTERRUPT_FACTOR_MPD == (status_ecsr & ETHER_ETHERC_INTERRUPT_FACTOR_MPD)) + { + p_instance_ctrl->magic_packet = ETHER_MAGIC_PACKET_DETECTED; + } + + /* + * Because each bit of the ECSR register is cleared when one is written, + * the value read from the register is written and the bit is cleared. + */ + p_reg_etherc->ECSR = status_ecsr; /* Clear all ETHERC status BFR, PSRTO, LCHNG, MPD, ICD */ + } + + /* + * Because each bit of the EESR register is cleared when one is written, + * the value read from the register is written and the bit is cleared. + */ + p_reg_edmac->EESR = status_eesr; /* Clear EDMAC status bits */ + + /* If a callback is provided, then call it with callback argument. */ + if (NULL != p_instance_ctrl->p_callback) + { + callback_arg.channel = p_instance_ctrl->p_ether_cfg->channel; + callback_arg.event = ETHER_EVENT_INTERRUPT; + callback_arg.status_ecsr = status_ecsr; + callback_arg.status_eesr = status_eesr; + callback_arg.p_context = p_instance_ctrl->p_ether_cfg->p_context; + ether_call_callback(p_instance_ctrl, &callback_arg); + } + + /* Clear pending interrupt flag to make sure it doesn't fire again + * after exiting. */ + R_BSP_IrqStatusClear(R_FSP_CurrentIrqGet()); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} /* End of function ether_eint_isr() */ + +/*********************************************************************************************************************** + * Function Name: ether_enable_icu + * Description : + * Arguments : channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_enable_icu (ether_instance_ctrl_t * const p_instance_ctrl) +{ + /** Configure the Ethernet interrupt. */ + R_BSP_IrqCfgEnable(p_instance_ctrl->p_ether_cfg->irq, + p_instance_ctrl->p_ether_cfg->interrupt_priority, + p_instance_ctrl); +} /* End of function ether_enable_icu() */ + +/*********************************************************************************************************************** + * Function Name: ether_disable_icu + * Description : + * Arguments : channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_disable_icu (ether_instance_ctrl_t * const p_instance_ctrl) +{ + /* Get IRQ number for EDMAC_EINT interrupt. */ + NVIC_DisableIRQ(p_instance_ctrl->p_ether_cfg->irq); + R_FSP_IsrContextSet(p_instance_ctrl->p_ether_cfg->irq, NULL); +} /* End of function ether_disable_icu() */ + +/*********************************************************************************************************************** + * Function Name: ether_configure_padding + * Description : + * Arguments : channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_configure_padding (ether_instance_ctrl_t * const p_instance_ctrl) +{ + R_ETHERC_EDMAC_Type * p_reg_edmac; + p_reg_edmac = (R_ETHERC_EDMAC_Type *) p_instance_ctrl->p_reg_edmac; + p_reg_edmac->RPADIR_b.PADR = (unsigned) p_instance_ctrl->p_ether_cfg->padding_offset & ETHER_MAXIMUM_PADDING_OFFSET; + p_reg_edmac->RPADIR_b.PADS = p_instance_ctrl->p_ether_cfg->padding; +} diff --git a/drivers/ra/fsp/src/r_ether_phy/r_ether_phy.c b/drivers/ra/fsp/src/r_ether_phy/r_ether_phy.c new file mode 100644 index 00000000..368e655b --- /dev/null +++ b/drivers/ra/fsp/src/r_ether_phy/r_ether_phy.c @@ -0,0 +1,1112 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + ***********************************************************************************************************************/ + +/* Access to peripherals and board defines. */ +#include "bsp_api.h" +#include "r_ether_phy.h" + +/*********************************************************************************************************************** + * Macro definitions + ***********************************************************************************************************************/ + +#ifndef ETHER_PHY_ERROR_RETURN + + #define ETHER_PHY_ERROR_RETURN(a, err) FSP_ERROR_RETURN((a), (err)) +#endif + +#define ETHERC_REG_SIZE (0x400UL) + +/** "RPHY" in ASCII. Used to determine if the control block is open. */ +#define ETHER_PHY_OPEN (0x52504859U) + +/* Media Independent Interface */ +#define ETHER_PHY_MII_ST (1) +#define ETHER_PHY_MII_READ (2) +#define ETHER_PHY_MII_WRITE (1) + +/* Standard PHY Registers */ +#define ETHER_PHY_REG_CONTROL (0) +#define ETHER_PHY_REG_STATUS (1) +#define ETHER_PHY_REG_IDENTIFIER1 (2) +#define ETHER_PHY_REG_IDENTIFIER2 (3) +#define ETHER_PHY_REG_AN_ADVERTISEMENT (4) +#define ETHER_PHY_REG_AN_LINK_PARTNER (5) +#define ETHER_PHY_REG_AN_EXPANSION (6) + +/* Basic Mode Control Register Bit Definitions */ +#define ETHER_PHY_CONTROL_RESET (1 << 15) +#define ETHER_PHY_CONTROL_LOOPBACK (1 << 14) +#define ETHER_PHY_CONTROL_100_MBPS (1 << 13) +#define ETHER_PHY_CONTROL_AN_ENABLE (1 << 12) +#define ETHER_PHY_CONTROL_POWER_DOWN (1 << 11) +#define ETHER_PHY_CONTROL_ISOLATE (1 << 10) +#define ETHER_PHY_CONTROL_AN_RESTART (1 << 9) +#define ETHER_PHY_CONTROL_FULL_DUPLEX (1 << 8) +#define ETHER_PHY_CONTROL_COLLISION (1 << 7) + +/* Basic Mode Status Register Bit Definitions */ +#define ETHER_PHY_STATUS_100_T4 (1 << 15) +#define ETHER_PHY_STATUS_100F (1 << 14) +#define ETHER_PHY_STATUS_100H (1 << 13) +#define ETHER_PHY_STATUS_10F (1 << 12) +#define ETHER_PHY_STATUS_10H (1 << 11) +#define ETHER_PHY_STATUS_AN_COMPLETE (1 << 5) +#define ETHER_PHY_STATUS_RM_FAULT (1 << 4) +#define ETHER_PHY_STATUS_AN_ABILITY (1 << 3) +#define ETHER_PHY_STATUS_LINK_UP (1 << 2) +#define ETHER_PHY_STATUS_JABBER (1 << 1) +#define ETHER_PHY_STATUS_EX_CAPABILITY (1 << 0) + +/* Auto Negotiation Advertisement Bit Definitions */ +#define ETHER_PHY_AN_ADVERTISEMENT_NEXT_PAGE (1 << 15) +#define ETHER_PHY_AN_ADVERTISEMENT_RM_FAULT (1 << 13) +#define ETHER_PHY_AN_ADVERTISEMENT_ASM_DIR (1 << 11) +#define ETHER_PHY_AN_ADVERTISEMENT_PAUSE (1 << 10) +#define ETHER_PHY_AN_ADVERTISEMENT_100_T4 (1 << 9) +#define ETHER_PHY_AN_ADVERTISEMENT_100F (1 << 8) +#define ETHER_PHY_AN_ADVERTISEMENT_100H (1 << 7) +#define ETHER_PHY_AN_ADVERTISEMENT_10F (1 << 6) +#define ETHER_PHY_AN_ADVERTISEMENT_10H (1 << 5) +#define ETHER_PHY_AN_ADVERTISEMENT_SELECTOR (1 << 0) + +/* Auto Negotiate Link Partner Ability Bit Definitions */ +#define ETHER_PHY_AN_LINK_PARTNER_NEXT_PAGE (1 << 15) +#define ETHER_PHY_AN_LINK_PARTNER_ACK (1 << 14) +#define ETHER_PHY_AN_LINK_PARTNER_RM_FAULT (1 << 13) +#define ETHER_PHY_AN_LINK_PARTNER_ASM_DIR (1 << 11) +#define ETHER_PHY_AN_LINK_PARTNER_PAUSE (1 << 10) +#define ETHER_PHY_AN_LINK_PARTNER_100_T4 (1 << 9) +#define ETHER_PHY_AN_LINK_PARTNER_100F (1 << 8) +#define ETHER_PHY_AN_LINK_PARTNER_100H (1 << 7) +#define ETHER_PHY_AN_LINK_PARTNER_10F (1 << 6) +#define ETHER_PHY_AN_LINK_PARTNER_10H (1 << 5) +#define ETHER_PHY_AN_LINK_PARTNER_SELECTOR (1 << 0) + +#define ETHER_PHY_PIR_MDI_MASK (1 << 3) +#define ETHER_PHY_PIR_MDO_HIGH (0x04) +#define ETHER_PHY_PIR_MDO_LOW (0x00) +#define ETHER_PHY_PIR_MMD_WRITE (0x02) +#define ETHER_PHY_PIR_MMD_READ (0x00) +#define ETHER_PHY_PIR_MDC_HIGH (0x01) +#define ETHER_PHY_PIR_MDC_LOW (0x00) + +#define ETHER_PHY_ADDRESS_SIZE (0x1fU) +#define ETHER_PHY_REGISTER_DATA_SIZE (0xffffU) + +#define ETHER_PHY_PREAMBLE_LENGTH (32U) +#define ETHER_PHY_WRITE_DATA_BIT_MASK (0x8000) + +/*********************************************************************************************************************** + * Typedef definitions + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Exported global variables (to be accessed by other files) + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Exported global function + ***********************************************************************************************************************/ +#if (ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE) +extern void ether_phy_target_ksz8091rnb_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl); +extern bool ether_phy_target_ksz8091rnb_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex); + +#endif +#if (ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE) +extern void ether_phy_target_ksz8041_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl); +extern bool ether_phy_target_ksz8041_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex); + +#endif +#if (ETHER_PHY_CFG_TARGET_DP83620_ENABLE) +extern void ether_phy_target_dp83620_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl); +extern bool ether_phy_target_dp83620_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex); + +#endif +#if (ETHER_PHY_CFG_TARGET_ICS1894_ENABLE) +extern void ether_phy_target_ics1894_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl); +extern bool ether_phy_target_ics1894_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex); + +#endif + +/*********************************************************************************************************************** + * Private global variables and functions + ***********************************************************************************************************************/ +static void ether_phy_preamble(ether_phy_instance_ctrl_t * p_instance_ctrl); +static void ether_phy_reg_set(ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t reg_addr, int32_t option); +static void ether_phy_reg_read(ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t * pdata); +static void ether_phy_reg_write(ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t data); +static void ether_phy_trans_zto0(ether_phy_instance_ctrl_t * p_instance_ctrl); +static void ether_phy_trans_1to0(ether_phy_instance_ctrl_t * p_instance_ctrl); +static void ether_phy_trans_idle(ether_phy_instance_ctrl_t * p_instance_ctrl); +static void ether_phy_mii_write1(ether_phy_instance_ctrl_t * p_instance_ctrl); +static void ether_phy_mii_write0(ether_phy_instance_ctrl_t * p_instance_ctrl); +static void ether_phy_mii_writez(ether_phy_instance_ctrl_t * p_instance_ctrl); +static void ether_phy_targets_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl); +static bool ether_phy_targets_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex); + +/** ETHER_PHY HAL API mapping for Ethernet PHY Controller interface */ +/*LDRA_INSPECTED 27 D This structure must be accessible in user code. It cannot be static. */ +const ether_phy_api_t g_ether_phy_on_ether_phy = +{ + .open = R_ETHER_PHY_Open, + .close = R_ETHER_PHY_Close, + .startAutoNegotiate = R_ETHER_PHY_StartAutoNegotiate, + .linkPartnerAbilityGet = R_ETHER_PHY_LinkPartnerAbilityGet, + .linkStatusGet = R_ETHER_PHY_LinkStatusGet, + .chipInit = R_ETHER_PHY_ChipInit, + .read = R_ETHER_PHY_Read, + .write = R_ETHER_PHY_Write +}; + +/*******************************************************************************************************************//** + * @addtogroup ETHER_PHY + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/********************************************************************************************************************//** + * @brief Resets Ethernet PHY device. Implements @ref ether_phy_api_t::open. + * + * @retval FSP_SUCCESS Channel opened successfully. + * @retval FSP_ERR_ASSERTION Pointer to ETHER_PHY control block or configuration structure is NULL. + * @retval FSP_ERR_ALREADY_OPEN Control block has already been opened or channel is being used by another + * instance. Call close() then open() to reconfigure. + * @retval FSP_ERR_INVALID_CHANNEL Invalid channel number is given. + * @retval FSP_ERR_INVALID_POINTER Pointer to p_cfg is NULL. + * @retval FSP_ERR_TIMEOUT PHY-LSI Reset wait timeout. + * @retval FSP_ERR_INVALID_ARGUMENT Register address is incorrect + * @retval FSP_ERR_NOT_INITIALIZED The control block has not been initialized. + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_PHY_Open (ether_phy_ctrl_t * const p_ctrl, ether_phy_cfg_t const * const p_cfg) +{ + fsp_err_t err = FSP_SUCCESS; + ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl; + R_ETHERC0_Type * p_reg_etherc; + +#if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_PHY_ERROR_RETURN(NULL != p_cfg, FSP_ERR_INVALID_POINTER); + ETHER_PHY_ERROR_RETURN((ETHER_PHY_OPEN != p_instance_ctrl->open), FSP_ERR_ALREADY_OPEN); + ETHER_PHY_ERROR_RETURN((BSP_FEATURE_ETHER_MAX_CHANNELS > p_cfg->channel), FSP_ERR_INVALID_CHANNEL); +#endif + + /** Make sure this channel exists. */ + p_reg_etherc = ((R_ETHERC0_Type *) (R_ETHERC0_BASE + (ETHERC_REG_SIZE * p_cfg->channel))); + p_instance_ctrl->p_reg_pir = (uint32_t *) &p_reg_etherc->PIR; + p_instance_ctrl->local_advertise = 0; + + /* Initialize configuration of ethernet phy module. */ + p_instance_ctrl->p_ether_phy_cfg = p_cfg; + + /* Configure pins for MII or RMII. Set PHYMODE0 if MII is selected. */ + R_PMISC->PFENET = (uint8_t) ((ETHER_PHY_MII_TYPE_MII == p_cfg->mii_type) << R_PMISC_PFENET_PHYMODE0_Pos); + +#if ETHER_PHY_CFG_INIT_PHY_LSI_AUTOMATIC + uint32_t reg = 0; + uint32_t count = 0; + + p_instance_ctrl->interface_status = ETHER_PHY_INTERFACE_STATUS_INITIALIZED; + + /* Reset PHY */ + R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_CONTROL, ETHER_PHY_CONTROL_RESET); + + /* Reset completion waiting */ + do + { + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_CONTROL, ®); + count++; + } while ((reg & ETHER_PHY_CONTROL_RESET) && (count < p_cfg->phy_reset_wait_time)); + + if (count < p_cfg->phy_reset_wait_time) + { + ether_phy_targets_initialize(p_instance_ctrl); + + p_instance_ctrl->open = ETHER_PHY_OPEN; + + err = FSP_SUCCESS; + } + else + { + err = FSP_ERR_TIMEOUT; + } + +#else + p_instance_ctrl->open = ETHER_PHY_OPEN; + + err = FSP_SUCCESS; +#endif + + return err; +} /* End of function R_ETHER_PHY_Open() */ + +/********************************************************************************************************************//** + * @brief Close Ethernet PHY device. Implements @ref ether_phy_api_t::close. + * + * @retval FSP_SUCCESS Channel successfully closed. + * @retval FSP_ERR_ASSERTION Pointer to ETHER_PHY control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened + * + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_PHY_Close (ether_phy_ctrl_t * const p_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl; + +#if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /** Clear configure block parameters. */ + p_instance_ctrl->p_ether_phy_cfg = NULL; + p_instance_ctrl->local_advertise = 0; + p_instance_ctrl->p_reg_pir = NULL; + + p_instance_ctrl->interface_status = ETHER_PHY_INTERFACE_STATUS_UNINITIALIZED; + p_instance_ctrl->open = 0; + + return err; +} /* End of function R_ETHER_PHY_Close() */ + +/********************************************************************************************************************//** + * @brief Starts auto-negotiate. Implements @ref ether_phy_api_t::startAutoNegotiate. + * + * @retval FSP_SUCCESS ETHER_PHY successfully starts auto-negotiate. + * @retval FSP_ERR_ASSERTION Pointer to ETHER_PHY control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened + * @retval FSP_ERR_INVALID_ARGUMENT Register address is incorrect + * @retval FSP_ERR_INVALID_POINTER Pointer to read buffer is NULL. + * @retval FSP_ERR_NOT_INITIALIZED The control block has not been initialized + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_PHY_StartAutoNegotiate (ether_phy_ctrl_t * const p_ctrl) +{ + ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl; + uint32_t reg = 0; + +#if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status, + FSP_ERR_NOT_INITIALIZED); +#endif + + /* Set local ability */ + /* When pause frame is not used */ + if (ETHER_PHY_FLOW_CONTROL_DISABLE == p_instance_ctrl->p_ether_phy_cfg->flow_control) + { + p_instance_ctrl->local_advertise = ((((ETHER_PHY_AN_ADVERTISEMENT_100F | + ETHER_PHY_AN_ADVERTISEMENT_100H) | + ETHER_PHY_AN_ADVERTISEMENT_10F) | + ETHER_PHY_AN_ADVERTISEMENT_10H) | + ETHER_PHY_AN_ADVERTISEMENT_SELECTOR); + } + /* When pause frame is used */ + else + { + p_instance_ctrl->local_advertise = ((((((ETHER_PHY_AN_ADVERTISEMENT_ASM_DIR | + ETHER_PHY_AN_ADVERTISEMENT_PAUSE) | + ETHER_PHY_AN_ADVERTISEMENT_100F) | + ETHER_PHY_AN_ADVERTISEMENT_100H) | + ETHER_PHY_AN_ADVERTISEMENT_10F) | + ETHER_PHY_AN_ADVERTISEMENT_10H) | + ETHER_PHY_AN_ADVERTISEMENT_SELECTOR); + } + + /* Configure what the PHY and the Ethernet controller on this board supports */ + R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_AN_ADVERTISEMENT, p_instance_ctrl->local_advertise); + R_ETHER_PHY_Write(p_instance_ctrl, + ETHER_PHY_REG_CONTROL, + (ETHER_PHY_CONTROL_AN_ENABLE | + ETHER_PHY_CONTROL_AN_RESTART)); + + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_AN_ADVERTISEMENT, ®); + + return FSP_SUCCESS; +} /* End of function R_ETHER_PHY_StartAutoNegotiate() */ + +/********************************************************************************************************************//** + * @brief Reports the other side's physical capability. Implements @ref ether_phy_api_t::linkPartnerAbilityGet. + * + * @retval FSP_SUCCESS ETHER_PHY successfully get link partner ability. + * @retval FSP_ERR_ASSERTION Pointer to ETHER_PHY control block is NULL. + * @retval FSP_ERR_INVALID_POINTER Pointer to arguments are NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened + * @retval FSP_ERR_ETHER_PHY_ERROR_LINK PHY-LSI is not link up. + * @retval FSP_ERR_ETHER_PHY_NOT_READY The auto-negotiation isn't completed + * @retval FSP_ERR_INVALID_ARGUMENT Status register address is incorrect + * @retval FSP_ERR_NOT_INITIALIZED The control block has not been initialized + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_PHY_LinkPartnerAbilityGet (ether_phy_ctrl_t * const p_ctrl, + uint32_t * const p_line_speed_duplex, + uint32_t * const p_local_pause, + uint32_t * const p_partner_pause) +{ + fsp_err_t err = FSP_SUCCESS; + ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl; + uint32_t reg = 0; + uint32_t line_speed_duplex = ETHER_PHY_LINK_SPEED_NO_LINK; + +#if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + ETHER_PHY_ERROR_RETURN(NULL != p_line_speed_duplex, FSP_ERR_INVALID_POINTER); + ETHER_PHY_ERROR_RETURN(NULL != p_local_pause, FSP_ERR_INVALID_POINTER); + ETHER_PHY_ERROR_RETURN(NULL != p_partner_pause, FSP_ERR_INVALID_POINTER); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status, + FSP_ERR_NOT_INITIALIZED); +#endif + + /* Because reading the first time shows the previous state, the Link status bit is read twice. */ + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_STATUS, ®); + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_STATUS, ®); + + /* When the link isn't up, return error */ + ETHER_PHY_ERROR_RETURN(ETHER_PHY_STATUS_LINK_UP == (reg & ETHER_PHY_STATUS_LINK_UP), FSP_ERR_ETHER_PHY_ERROR_LINK); + + /* Establish local pause capability */ + if (ETHER_PHY_AN_ADVERTISEMENT_PAUSE == (p_instance_ctrl->local_advertise & ETHER_PHY_AN_ADVERTISEMENT_PAUSE)) + { + (*p_local_pause) |= (1 << 1); + } + + if (ETHER_PHY_AN_ADVERTISEMENT_ASM_DIR == (p_instance_ctrl->local_advertise & ETHER_PHY_AN_ADVERTISEMENT_ASM_DIR)) + { + (*p_local_pause) |= 1; + } + + /* When the auto-negotiation isn't completed, return error */ + ETHER_PHY_ERROR_RETURN(ETHER_PHY_STATUS_AN_COMPLETE == (reg & ETHER_PHY_STATUS_AN_COMPLETE), + FSP_ERR_ETHER_PHY_NOT_READY); + + /* Get the link partner response */ + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_AN_LINK_PARTNER, ®); + + /* Establish partner pause capability */ + if (ETHER_PHY_AN_LINK_PARTNER_PAUSE == (reg & ETHER_PHY_AN_LINK_PARTNER_PAUSE)) + { + (*p_partner_pause) = (1 << 1); + } + + if (ETHER_PHY_AN_LINK_PARTNER_ASM_DIR == (reg & ETHER_PHY_AN_LINK_PARTNER_ASM_DIR)) + { + (*p_partner_pause) |= 1; + } + + /* Establish the line speed and the duplex */ + if ((ETHER_PHY_AN_LINK_PARTNER_10H == (reg & ETHER_PHY_AN_LINK_PARTNER_10H)) && + ether_phy_targets_is_support_link_partner_ability(p_instance_ctrl, ETHER_PHY_LINK_SPEED_10H)) + { + line_speed_duplex = ETHER_PHY_LINK_SPEED_10H; + } + + if ((ETHER_PHY_AN_LINK_PARTNER_10F == (reg & ETHER_PHY_AN_LINK_PARTNER_10F)) && + ether_phy_targets_is_support_link_partner_ability(p_instance_ctrl, ETHER_PHY_LINK_SPEED_10F)) + { + line_speed_duplex = ETHER_PHY_LINK_SPEED_10F; + } + + if ((ETHER_PHY_AN_LINK_PARTNER_100H == (reg & ETHER_PHY_AN_LINK_PARTNER_100H)) && + ether_phy_targets_is_support_link_partner_ability(p_instance_ctrl, ETHER_PHY_LINK_SPEED_100H)) + { + line_speed_duplex = ETHER_PHY_LINK_SPEED_100H; + } + + if ((ETHER_PHY_AN_LINK_PARTNER_100F == (reg & ETHER_PHY_AN_LINK_PARTNER_100F)) && + ether_phy_targets_is_support_link_partner_ability(p_instance_ctrl, ETHER_PHY_LINK_SPEED_100F)) + { + line_speed_duplex = ETHER_PHY_LINK_SPEED_100F; + } + + if (ETHER_PHY_LINK_SPEED_NO_LINK == line_speed_duplex) + { + err = FSP_ERR_ETHER_PHY_ERROR_LINK; + } + else + { + (*p_line_speed_duplex) = line_speed_duplex; + } + + return err; +} /* End of function R_ETHER_PHY_LinkPartnerAbilityGet() */ + +/********************************************************************************************************************//** + * @brief Returns the status of the physical link. Implements @ref ether_phy_api_t::linkStatusGet. + * + * @retval FSP_SUCCESS ETHER_PHY successfully get link partner ability. + * @retval FSP_ERR_ASSERTION Pointer to ETHER_PHY control block is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened + * @retval FSP_ERR_ETHER_PHY_ERROR_LINK PHY-LSI is not link up. + * @retval FSP_ERR_INVALID_ARGUMENT Status register address is incorrect + * @retval FSP_ERR_INVALID_POINTER Pointer to read buffer is NULL. + * @retval FSP_ERR_NOT_INITIALIZED The control block has not been initialized + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_PHY_LinkStatusGet (ether_phy_ctrl_t * const p_ctrl) +{ + ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl; + uint32_t reg; + fsp_err_t err = FSP_SUCCESS; + +#if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status, + FSP_ERR_NOT_INITIALIZED); +#endif + + /* Because reading the first time shows the previous state, the Link status bit is read twice. */ + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_STATUS, ®); + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_STATUS, ®); + + /* When the link isn't up, return error */ + if (ETHER_PHY_STATUS_LINK_UP != (reg & ETHER_PHY_STATUS_LINK_UP)) + { + /* Link is down */ + err = FSP_ERR_ETHER_PHY_ERROR_LINK; + } + else + { + /* Link is up */ + err = FSP_SUCCESS; + } + + return err; +} /* End of function R_ETHER_PHY_LinkStatusGet() */ + +/********************************************************************************************************************//** + * @brief Initialize Ethernet PHY device. Implements @ref ether_phy_api_t::chipInit. + * + * @retval FSP_SUCCESS PHY device initialized successfully. + * @retval FSP_ERR_ASSERTION Pointer to ETHER_PHY control block or configuration structure is NULL. + * @retval FSP_ERR_INVALID_ARGUMENT Address or data is not a valid size. + * @retval FSP_ERR_INVALID_POINTER Pointer to p_cfg is NULL. + * @retval FSP_ERR_NOT_INITIALIZED The control block has not been initialized. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_TIMEOUT PHY-LSI Reset wait timeout. + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_PHY_ChipInit (ether_phy_ctrl_t * const p_ctrl, ether_phy_cfg_t const * const p_cfg) +{ + fsp_err_t err = FSP_SUCCESS; + ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl; + uint32_t reg = 0; + uint32_t count = 0; + +#if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_PHY_ERROR_RETURN(NULL != p_cfg, FSP_ERR_INVALID_POINTER); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + p_instance_ctrl->interface_status = ETHER_PHY_INTERFACE_STATUS_INITIALIZED; + + /* Reset PHY */ + R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_CONTROL, ETHER_PHY_CONTROL_RESET); + + /* Reset completion waiting */ + do + { + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_CONTROL, ®); + count++; + } while ((reg & ETHER_PHY_CONTROL_RESET) && (count < p_cfg->phy_reset_wait_time)); + + if (count < p_cfg->phy_reset_wait_time) + { + ether_phy_targets_initialize(p_instance_ctrl); + + err = FSP_SUCCESS; + } + else + { + err = FSP_ERR_TIMEOUT; + } + + return err; +} /* End of function R_ETHER_PHY_ChipInit() */ + +/********************************************************************************************************************//** + * @brief Read data from register of PHY-LSI . Implements @ref ether_phy_api_t::read. + * + * @retval FSP_SUCCESS ETHER_PHY successfully read data. + * @retval FSP_ERR_ASSERTION Pointer to ETHER_PHY control block is NULL. + * @retval FSP_ERR_INVALID_POINTER Pointer to read buffer is NULL. + * @retval FSP_ERR_INVALID_ARGUMENT Address is not a valid size + * @retval FSP_ERR_NOT_INITIALIZED The control block has not been initialized + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_PHY_Read (ether_phy_ctrl_t * const p_ctrl, uint32_t reg_addr, uint32_t * const p_data) +{ + ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl; + uint32_t data; +#if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_PHY_ERROR_RETURN(NULL != p_data, FSP_ERR_INVALID_POINTER); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_ADDRESS_SIZE >= reg_addr, FSP_ERR_INVALID_ARGUMENT); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status, + FSP_ERR_NOT_INITIALIZED); +#endif + + /* + * The value is read from the PHY register by the frame format of MII Management Interface provided + * for by Table 22-12 of 22.2.4.5 of IEEE 802.3-2008_section2. + */ + ether_phy_preamble(p_instance_ctrl); + ether_phy_reg_set(p_instance_ctrl, reg_addr, ETHER_PHY_MII_READ); + ether_phy_trans_zto0(p_instance_ctrl); + ether_phy_reg_read(p_instance_ctrl, &data); + ether_phy_trans_idle(p_instance_ctrl); + + (*p_data) = data; + + return FSP_SUCCESS; +} /* End of function R_ETHER_PHY_Read() */ + +/********************************************************************************************************************//** + * @brief Write data to register of PHY-LSI . Implements @ref ether_phy_api_t::write. + * + * @retval FSP_SUCCESS ETHER_PHY successfully write data. + * @retval FSP_ERR_ASSERTION Pointer to ETHER_PHY control block is NULL. + * @retval FSP_ERR_INVALID_ARGUMENT Address or data is not a valid size + * @retval FSP_ERR_NOT_INITIALIZED The control block has not been initialized + ***********************************************************************************************************************/ +fsp_err_t R_ETHER_PHY_Write (ether_phy_ctrl_t * const p_ctrl, uint32_t reg_addr, uint32_t data) +{ + ether_phy_instance_ctrl_t * p_instance_ctrl = (ether_phy_instance_ctrl_t *) p_ctrl; + +#if (ETHER_PHY_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_ADDRESS_SIZE >= reg_addr, FSP_ERR_INVALID_ARGUMENT); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_REGISTER_DATA_SIZE >= data, FSP_ERR_INVALID_ARGUMENT); + ETHER_PHY_ERROR_RETURN(ETHER_PHY_INTERFACE_STATUS_INITIALIZED == p_instance_ctrl->interface_status, + FSP_ERR_NOT_INITIALIZED); +#endif + + /* + * The value is read from the PHY register by the frame format of MII Management Interface provided + * for by Table 22-12 of 22.2.4.5 of IEEE 802.3-2008_section2. + */ + ether_phy_preamble(p_instance_ctrl); + ether_phy_reg_set(p_instance_ctrl, reg_addr, ETHER_PHY_MII_WRITE); + ether_phy_trans_1to0(p_instance_ctrl); + ether_phy_reg_write(p_instance_ctrl, data); + ether_phy_trans_idle(p_instance_ctrl); + + return FSP_SUCCESS; +} /* End of function R_ETHER_PHY_Write() */ + +/*******************************************************************************************************************//** + * @} (end addtogroup ETHER_PHY) + **********************************************************************************************************************/ + +/** + * Private functions + */ + +/*********************************************************************************************************************** + * Function Name: phy_preamble + * Description : As preliminary preparation for access to the PHY module register, + * "1" is output via the MII management interface. + * Arguments : ether_channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_preamble (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + int16_t i; + + /* + * The processing of PRE (preamble) about the frame format of MII Management Interface which is + * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2". + */ + i = ETHER_PHY_PREAMBLE_LENGTH; + while (i > 0) + { + ether_phy_mii_write1(p_instance_ctrl); + i--; + } +} /* End of function ether_phy_preamble() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_reg_set + * Description : Sets a PHY device to read or write mode + * Arguments : ether_channel - + * Ethernet channel number + * reg_addr - + * address of the PHY register + * option - + * mode + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_reg_set (ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t reg_addr, int32_t option) +{ + int32_t i; + uint32_t data = 0; + + /* + * The processing of ST (start of frame),OP (operation code), PHYAD (PHY Address), and + * REGAD (Register Address) about the frame format of MII Management Interface which is + * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2". + */ + data = (ETHER_PHY_MII_ST << 14); /* ST code */ + + if (ETHER_PHY_MII_READ == option) + { + data |= (ETHER_PHY_MII_READ << 12); /* OP code(RD) */ + } + else + { + data |= (ETHER_PHY_MII_WRITE << 12); /* OP code(WT) */ + } + + data |= (uint32_t) (p_instance_ctrl->p_ether_phy_cfg->phy_lsi_address << 7); /* PHY Address */ + + data |= (reg_addr << 2); /* Reg Address */ + + i = 14; + while (i > 0) + { + if (0 == (data & ETHER_PHY_WRITE_DATA_BIT_MASK)) + { + ether_phy_mii_write0(p_instance_ctrl); + } + else + { + ether_phy_mii_write1(p_instance_ctrl); + } + + data = (data << 1); + i--; + } +} /* End of function ether_phy_reg_set() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_reg_read + * Description : Reads PHY register through MII interface + * Arguments : p_instance_ctrl - + * Ethernet channel number + * pdata - + * pointer to store the data read + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_reg_read (ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t * pdata) +{ + int32_t i; + int32_t j; + uint32_t reg_data; + + volatile uint32_t * petherc_pir; + + petherc_pir = p_instance_ctrl->p_reg_pir; + + /* + * The processing of DATA (data) about reading of the frame format of MII Management Interface which is + * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2". + */ + reg_data = 0; + i = 16; + while (i > 0) + { + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW); + } + + reg_data = (reg_data << 1); + reg_data |= (uint32_t) (((*petherc_pir) & ETHER_PHY_PIR_MDI_MASK) >> 3); /* MDI read */ + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_HIGH); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_HIGH); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW); + } + + i--; + } + + (*pdata) = reg_data; +} /* End of function ether_phy_reg_read() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_reg_write + * Description : Writes to PHY register through MII interface + * Arguments : ether_channel - + * Ethernet channel number + * data - + * value to write + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_reg_write (ether_phy_instance_ctrl_t * p_instance_ctrl, uint32_t data) +{ + int32_t i; + + /* + * The processing of DATA (data) about writing of the frame format of MII Management Interface which is + * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2". + */ + i = 16; + while (i > 0) + { + if (0 == (data & ETHER_PHY_WRITE_DATA_BIT_MASK)) + { + ether_phy_mii_write0(p_instance_ctrl); + } + else + { + ether_phy_mii_write1(p_instance_ctrl); + } + + i--; + data = (data << 1); + } +} /* End of function ether_phy_reg_write() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_trans_zto0 + * Description : Performs bus release so that PHY can drive data + * : for read operation + * Arguments : ether_channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_trans_zto0 (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + /* Release the bus by writing z. */ + ether_phy_mii_writez(p_instance_ctrl); + + /* The PHY will drive the bus to 0. */ + ether_phy_mii_writez(p_instance_ctrl); +} /* End of function ether_phy_trans_zto0() */ + +/*********************************************************************************************************************** + * Function Name: phy_trans_1to0 + * Description : Switches data bus so MII interface can drive data + * : for write operation + * Arguments : ether_channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_trans_1to0 (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + /* + * The processing of TA (turnaround) about writing of the frame format of MII Management Interface which is + * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2". + */ + ether_phy_mii_write1(p_instance_ctrl); + ether_phy_mii_write0(p_instance_ctrl); +} /* End of function ether_phy_trans_1to0() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_trans_idle + * Description : Switches data bus to IDLE state to prepare for the next transfer. + * Arguments : ether_channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_trans_idle (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + volatile uint32_t * petherc_pir; + + petherc_pir = p_instance_ctrl->p_reg_pir; + + int64_t count = (int64_t) p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time * 4; + + /* Release the bus for one MDC period. */ + for (int64_t j = count; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW); + } +} + +/*********************************************************************************************************************** + * Function Name: ether_phy_mii_write1 + * Description : Outputs 1 to the MII interface + * Arguments : ether_channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_mii_write1 (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + int32_t j; + volatile uint32_t * petherc_pir; + + petherc_pir = p_instance_ctrl->p_reg_pir; + + /* + * The processing of one bit about frame format of MII Management Interface which is + * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2". + * The data that 1 is output. + */ + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_HIGH | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_LOW); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_HIGH | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_HIGH); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_HIGH | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_HIGH); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_HIGH | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_LOW); + } +} /* End of function ether_phy_mii_write1() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_mii_write0 + * Description : Outputs 0 to the MII interface + * Arguments : ether_channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_mii_write0 (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + int32_t j; + volatile uint32_t * petherc_pir; + + petherc_pir = p_instance_ctrl->p_reg_pir; + + /* + * The processing of one bit about frame format of MII Management Interface which is + * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2". + * The data that 0 is output. + */ + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_LOW); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_HIGH); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_HIGH); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_WRITE | ETHER_PHY_PIR_MDC_LOW); + } +} /* End of function ether_phy_mii_write0() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_mii_writez + * Description : Outputs z to the MII interface + * Arguments : ether_channel - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_mii_writez (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + int32_t j; + + volatile uint32_t * petherc_pir; + + petherc_pir = p_instance_ctrl->p_reg_pir; + + /* + * The processing of one bit about frame format of MII Management Interface which is + * provided by "Table 22-12" of "22.2.4.5" of "IEEE 802.3-2008_section2". + * The data that z is output. + */ + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_HIGH); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_HIGH); + } + + for (j = p_instance_ctrl->p_ether_phy_cfg->mii_bit_access_wait_time; j > 0; j--) + { + (*petherc_pir) = (ETHER_PHY_PIR_MDO_LOW | ETHER_PHY_PIR_MMD_READ | ETHER_PHY_PIR_MDC_LOW); + } +} + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_initialize + * Description : PHY-LSI specific initialization processing + * Arguments : p_instance_ctrl - + * Ethernet control block + * Return Value : none + ***********************************************************************************************************************/ +static void ether_phy_targets_initialize (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + switch (p_instance_ctrl->p_ether_phy_cfg->phy_lsi_type) + { + /* Use KSZ8091RNB */ +#if (ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE) + case ETHER_PHY_LSI_TYPE_KSZ8091RNB: + { + ether_phy_target_ksz8091rnb_initialize(p_instance_ctrl); + break; + } +#endif + + /* Use KSZ8041 */ +#if (ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE) + case ETHER_PHY_LSI_TYPE_KSZ8041: + { + ether_phy_target_ksz8041_initialize(p_instance_ctrl); + break; + } +#endif + + /* Use DP83620 */ +#if (ETHER_PHY_CFG_TARGET_DP83620_ENABLE) + case ETHER_PHY_LSI_TYPE_DP83620: + { + ether_phy_target_dp83620_initialize(p_instance_ctrl); + break; + } +#endif + + /* Use ICS1894 */ +#if (ETHER_PHY_CFG_TARGET_ICS1894_ENABLE) + case ETHER_PHY_LSI_TYPE_ICS1894: + { + ether_phy_target_ics1894_initialize(p_instance_ctrl); + break; + } +#endif + + /* User custom */ +#if (ETHER_PHY_CFG_USE_CUSTOM_PHY_LSI_ENABLE) + case ETHER_PHY_LSI_TYPE_CUSTOM: + { + if (NULL != p_instance_ctrl->p_ether_phy_cfg->p_extend) + { + ether_phy_extended_cfg_t const * p_callback = p_instance_ctrl->p_ether_phy_cfg->p_extend; + if (NULL != p_callback->p_target_init) + { + p_callback->p_target_init(p_instance_ctrl); + } + } + + break; + } +#endif + + /* If module is configured for default LSI */ + default: + { + break; + } + } +} /* End of function ether_phy_targets_initialize() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_is_support_link_partner_ability + * Description : Check if the PHY-LSI connected Ethernet controller supports link ability + * Arguments : p_instance_ctrl - + * Ethernet control block + * line_speed_duplex - + * Line speed duplex of link partner PHY-LSI + * Return Value : bool + ***********************************************************************************************************************/ +static bool ether_phy_targets_is_support_link_partner_ability (ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex) +{ + bool result = false; + FSP_PARAMETER_NOT_USED(line_speed_duplex); + switch (p_instance_ctrl->p_ether_phy_cfg->phy_lsi_type) + { + /* Use KSZ8091RNB */ +#if (ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE) + case ETHER_PHY_LSI_TYPE_KSZ8091RNB: + { + result = ether_phy_target_ksz8091rnb_is_support_link_partner_ability(p_instance_ctrl, line_speed_duplex); + break; + } +#endif + + /* Use KSZ8041 */ +#if (ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE) + case ETHER_PHY_LSI_TYPE_KSZ8041: + { + result = ether_phy_target_ksz8041_is_support_link_partner_ability(p_instance_ctrl, line_speed_duplex); + break; + } +#endif + + /* Use DP83620 */ +#if (ETHER_PHY_CFG_TARGET_DP83620_ENABLE) + case ETHER_PHY_LSI_TYPE_DP83620: + { + result = ether_phy_target_dp83620_is_support_link_partner_ability(p_instance_ctrl, line_speed_duplex); + break; + } +#endif + + /* Use ICS1894 */ +#if (ETHER_PHY_CFG_TARGET_ICS1894_ENABLE) + case ETHER_PHY_LSI_TYPE_ICS1894: + { + result = ether_phy_target_ics1894_is_support_link_partner_ability(p_instance_ctrl, line_speed_duplex); + break; + } +#endif + + /* User custom */ +#if (ETHER_PHY_CFG_USE_CUSTOM_PHY_LSI_ENABLE) + case ETHER_PHY_LSI_TYPE_CUSTOM: + { + if (NULL != p_instance_ctrl->p_ether_phy_cfg->p_extend) + { + ether_phy_extended_cfg_t const * p_callback = p_instance_ctrl->p_ether_phy_cfg->p_extend; + if (NULL != p_callback->p_target_link_partner_ability_get) + { + result = p_callback->p_target_link_partner_ability_get(p_instance_ctrl, line_speed_duplex); + } + } + + break; + } +#endif + + /* If module is configured for default LSI, always return true */ + default: + { + result = true; + break; + } + } + + return result; +} /* End of function ether_phy_targets_is_support_link_partner_ability() */ diff --git a/drivers/ra/fsp/src/r_ether_phy/targets/DP83620/r_ether_phy_target_dp83620.c b/drivers/ra/fsp/src/r_ether_phy/targets/DP83620/r_ether_phy_target_dp83620.c new file mode 100644 index 00000000..f8628c22 --- /dev/null +++ b/drivers/ra/fsp/src/r_ether_phy/targets/DP83620/r_ether_phy_target_dp83620.c @@ -0,0 +1,94 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + ***********************************************************************************************************************/ + +/* Access to peripherals and board defines. */ +#include "bsp_api.h" +#include "r_ether_phy.h" + +#if (ETHER_PHY_CFG_TARGET_DP83620_ENABLE) + +/*********************************************************************************************************************** + * Macro definitions + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + ***********************************************************************************************************************/ + +/* Vendor Specific PHY Registers */ + #define ETHER_PHY_REG_PAGE_SELECT (0x13) + #define ETHER_PHY_REG_14H (0x14) + +/*********************************************************************************************************************** + * Exported global variables (to be accessed by other files) + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Exported global function + ***********************************************************************************************************************/ +void ether_phy_target_dp83620_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl); +bool ether_phy_target_dp83620_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex); + +/*********************************************************************************************************************** + * Private global variables and functions + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_initialize + * Description : PHY-LSI specific initialization processing + * Arguments : p_api_ctrl - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +void ether_phy_target_dp83620_initialize (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + uint32_t reg; + + if (ETHER_PHY_MII_TYPE_RMII == p_instance_ctrl->p_ether_phy_cfg->mii_type) + { + /* + * The following is the recommended settings for TI to output 50 MHz from CLK_OUT when using Texas Instruments DP83620 + * in RMII master mode. + */ + R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_PAGE_SELECT, 0x0006); + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_14H, ®); + if (0x800A == reg) + { + R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_14H, 0x000A); + R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_PAGE_SELECT, 0x0000); + } + } +} /* End of function ether_phy_targets_initialize() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_is_support_link_partner_ability + * Description : Check if the PHY-LSI connected Ethernet controller supports link ability + * Arguments : p_instance_ctrl - + * Ethernet control block + * line_speed_duplex - + * Line speed duplex of link partner PHY-LSI + * Return Value : bool + ***********************************************************************************************************************/ +bool ether_phy_target_dp83620_is_support_link_partner_ability (ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex) +{ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + FSP_PARAMETER_NOT_USED(line_speed_duplex); + + /* This PHY-LSI supports half and full duplex mode. */ + return true; +} /* End of function ether_phy_targets_is_support_link_partner_ability() */ + +#endif /* ETHER_PHY_CFG_TARGET_DP83620_ENABLE */ diff --git a/drivers/ra/fsp/src/r_ether_phy/targets/ICS1894/r_ether_phy_target_ics1894.c b/drivers/ra/fsp/src/r_ether_phy/targets/ICS1894/r_ether_phy_target_ics1894.c new file mode 100644 index 00000000..2b31ae5d --- /dev/null +++ b/drivers/ra/fsp/src/r_ether_phy/targets/ICS1894/r_ether_phy_target_ics1894.c @@ -0,0 +1,110 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + ***********************************************************************************************************************/ + +/* Access to peripherals and board defines. */ +#include "bsp_api.h" +#include "r_ether_phy.h" + +#if (ETHER_PHY_CFG_TARGET_ICS1894_ENABLE) + +/*********************************************************************************************************************** + * Macro definitions + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + ***********************************************************************************************************************/ + +/* Vendor Specific PHY Registers */ + #define ETHER_PHY_REG_PHY_CONTROL_20 (0x14) + +/*********************************************************************************************************************** + * Exported global variables (to be accessed by other files) + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Exported global function + ***********************************************************************************************************************/ +void ether_phy_target_ics1894_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl); +bool ether_phy_target_ics1894_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex); + +/*********************************************************************************************************************** + * Private global variables and functions + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_initialize + * Description : PHY-LSI specific initialization processing + * Arguments : p_instance_ctrl - + * Ethernet control block + * Return Value : none + ***********************************************************************************************************************/ +void ether_phy_target_ics1894_initialize (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + uint32_t reg; + + /* + * When ICS1894NL of the the Renesas Electronics Corporation. is used, + * the pin that outputs the state of LINK is used combinedly with ACTIVITY in default. + * The setting of the pin is changed so that only the state of LINK is output. + */ + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_PHY_CONTROL_20, ®); + reg |= 0x0007U; + R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_PHY_CONTROL_20, reg); +} /* End of function ether_phy_targets_initialize() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_is_support_link_partner_ability + * Description : Check if the PHY-LSI connected Ethernet controller supports link ability + * Arguments : p_instance_ctrl - + * Ethernet control block + * line_speed_duplex - + * Line speed duplex of link partner PHY-LSI + * Return Value : bool + ***********************************************************************************************************************/ +bool ether_phy_target_ics1894_is_support_link_partner_ability (ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex) +{ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + bool ret = false; + + /* This PHY-LSI only supports full duplex mode. */ + switch (line_speed_duplex) + { + /* 10Mbps full duplex */ + case ETHER_PHY_LINK_SPEED_10F: + { + ret = true; + break; + } + + /* 100Mbps full duplex */ + case ETHER_PHY_LINK_SPEED_100F: + { + ret = true; + break; + } + + /* Half duplex is not supported */ + default: + { + break; + } + } + + return ret; +} /* End of function ether_phy_targets_is_support_link_partner_ability() */ + +#endif /* ETHER_PHY_CFG_TARGET_ICS1894_ENABLE */ diff --git a/drivers/ra/fsp/src/r_ether_phy/targets/KSZ8041/r_ether_phy_target_ksz8041.c b/drivers/ra/fsp/src/r_ether_phy/targets/KSZ8041/r_ether_phy_target_ksz8041.c new file mode 100644 index 00000000..966bf442 --- /dev/null +++ b/drivers/ra/fsp/src/r_ether_phy/targets/KSZ8041/r_ether_phy_target_ksz8041.c @@ -0,0 +1,91 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + ***********************************************************************************************************************/ + +/* Access to peripherals and board defines. */ +#include "bsp_api.h" +#include "r_ether_phy.h" + +#if (ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE) + +/*********************************************************************************************************************** + * Macro definitions + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + ***********************************************************************************************************************/ + +/* Vendor Specific PHY Registers */ + #define ETHER_PHY_REG_PHY_CONTROL_1 (0x1E) + + #define ETHER_PHY_LED_MODE_LED0_LINK_LED1_ACTIVITY (0x4000U) + #define ETHER_PHY_LED_MODE_MASK (0xC000U) + +/*********************************************************************************************************************** + * Exported global variables (to be accessed by other files) + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Exported global function + ***********************************************************************************************************************/ +void ether_phy_target_ksz8041_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl); +bool ether_phy_target_ksz8041_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex); + +/*********************************************************************************************************************** + * Private global variables and functions + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_initialize + * Description : PHY-LSI specific initialization processing + * Arguments : p_api_ctrl - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +void ether_phy_target_ksz8041_initialize (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + uint32_t reg; + + /* + * When KSZ8041NL of the Micrel, Inc. is used, + * the pin that outputs the state of LINK is used combinedly with ACTIVITY in default. + * The setting of the pin is changed so that only the state of LINK is output. + */ + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_PHY_CONTROL_1, ®); + reg &= ~ETHER_PHY_LED_MODE_MASK; + reg |= ETHER_PHY_LED_MODE_LED0_LINK_LED1_ACTIVITY; + R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_PHY_CONTROL_1, reg); +} /* End of function ether_phy_targets_initialize() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_is_support_link_partner_ability + * Description : Check if the PHY-LSI connected Ethernet controller supports link ability + * Arguments : p_instance_ctrl - + * Ethernet control block + * line_speed_duplex - + * Line speed duplex of link partner PHY-LSI + * Return Value : bool + ***********************************************************************************************************************/ +bool ether_phy_target_ksz8041_is_support_link_partner_ability (ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex) +{ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + FSP_PARAMETER_NOT_USED(line_speed_duplex); + + /* This PHY-LSI supports half and full duplex mode. */ + return true; +} /* End of function ether_phy_targets_is_support_link_partner_ability() */ + +#endif /* ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE */ diff --git a/drivers/ra/fsp/src/r_ether_phy/targets/KSZ8091RNB/r_ether_phy_target_ksz8091rnb.c b/drivers/ra/fsp/src/r_ether_phy/targets/KSZ8091RNB/r_ether_phy_target_ksz8091rnb.c new file mode 100644 index 00000000..6af6aba7 --- /dev/null +++ b/drivers/ra/fsp/src/r_ether_phy/targets/KSZ8091RNB/r_ether_phy_target_ksz8091rnb.c @@ -0,0 +1,105 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + ***********************************************************************************************************************/ + +/* Access to peripherals and board defines. */ +#include "bsp_api.h" +#include "r_ether_phy.h" + +#if (ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE) + +/*********************************************************************************************************************** + * Macro definitions + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + ***********************************************************************************************************************/ + +/* Vendor Specific PHY Registers */ + #define ETHER_PHY_REG_INTERRUPT_CONTROL (0x1B) + #define ETHER_PHY_REG_PHY_CONTROL2 (0x1F) + + #define ETHER_PHY_REG_INTERRUPT_CONTROL_LUIE_OFFSET (0x8) + #define ETHER_PHY_REG_INTERRUPT_CONTROL_LDIE_OFFSET (0xA) + #define ETHER_PHY_REG_PHY_CONTROL2_RMII_RCS_OFFSET (0x7) + #define ETHER_PHY_REG_PHY_CONTROL2_RMII_IL_OFFSET (0x9) + +/*********************************************************************************************************************** + * Exported global variables (to be accessed by other files) + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Exported global function + ***********************************************************************************************************************/ +void ether_phy_target_ksz8091rnb_initialize(ether_phy_instance_ctrl_t * p_instance_ctrl); +bool ether_phy_target_ksz8091rnb_is_support_link_partner_ability(ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex); + +/*********************************************************************************************************************** + * Private global variables and functions + ***********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_initialize + * Description : PHY-LSI specific initialization processing + * Arguments : p_api_ctrl - + * Ethernet channel number + * Return Value : none + ***********************************************************************************************************************/ +void ether_phy_target_ksz8091rnb_initialize (ether_phy_instance_ctrl_t * p_instance_ctrl) +{ + uint32_t reg; + + /* When KSZ8091RNB of the Micrel, Inc. is used. + * This processing is a setting to use Link -up and Link-down as a factor of INTPR. + * b10=1:Enable link-down interrupt + * b8=1 :Enable link-up interrupt + */ + R_ETHER_PHY_Write(p_instance_ctrl, + ETHER_PHY_REG_INTERRUPT_CONTROL, + (0x1 << ETHER_PHY_REG_INTERRUPT_CONTROL_LUIE_OFFSET | 0x1 << + ETHER_PHY_REG_INTERRUPT_CONTROL_LDIE_OFFSET)); + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_INTERRUPT_CONTROL, ®); + R_ETHER_PHY_Read(p_instance_ctrl, ETHER_PHY_REG_PHY_CONTROL2, ®); + + /* b7=1:RMII 50MHz clock mode; clock input to XI(pin 9) is 50MHz */ + #if (ETHER_PHY_CFG_USE_REF_CLK == 0) + reg |= (0x1 << ETHER_PHY_REG_PHY_CONTROL2_RMII_RCS_OFFSET); + #endif + + /* b9=0:Interrupt pin active low */ + reg &= (uint16_t) ~(0x1 << ETHER_PHY_REG_PHY_CONTROL2_RMII_IL_OFFSET); + R_ETHER_PHY_Write(p_instance_ctrl, ETHER_PHY_REG_PHY_CONTROL2, reg); +} /* End of function ether_phy_targets_initialize() */ + +/*********************************************************************************************************************** + * Function Name: ether_phy_targets_is_support_link_partner_ability + * Description : Check if the PHY-LSI connected Ethernet controller supports link ability + * Arguments : p_instance_ctrl - + * Ethernet control block + * line_speed_duplex - + * Line speed duplex of link partner PHY-LSI + * Return Value : bool + ***********************************************************************************************************************/ +bool ether_phy_target_ksz8091rnb_is_support_link_partner_ability (ether_phy_instance_ctrl_t * p_instance_ctrl, + uint32_t line_speed_duplex) +{ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + FSP_PARAMETER_NOT_USED(line_speed_duplex); + + /* This PHY-LSI supports half and full duplex mode. */ + return true; +} /* End of function ether_phy_targets_is_support_link_partner_ability() */ + +#endif /* ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE */ diff --git a/zephyr/ra/ra_cfg/fsp_cfg/r_ether_cfg.h b/zephyr/ra/ra_cfg/fsp_cfg/r_ether_cfg.h new file mode 100644 index 00000000..42726bd7 --- /dev/null +++ b/zephyr/ra/ra_cfg/fsp_cfg/r_ether_cfg.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its + * affiliates + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef R_ETHER_CFG_H_ +#define R_ETHER_CFG_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define ETHER_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#define ETHER_CFG_LINK_PRESENT (0) +#define ETHER_CFG_USE_LINKSTA (0) + +#ifdef __cplusplus +} +#endif +#endif /* R_ETHER_CFG_H_ */ diff --git a/zephyr/ra/ra_cfg/fsp_cfg/r_ether_phy_cfg.h b/zephyr/ra/ra_cfg/fsp_cfg/r_ether_phy_cfg.h new file mode 100644 index 00000000..1df55acd --- /dev/null +++ b/zephyr/ra/ra_cfg/fsp_cfg/r_ether_phy_cfg.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its + * affiliates + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef R_ETHER_PHY_CFG_H_ +#define R_ETHER_PHY_CFG_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#if DT_PROP(DT_NODELABEL(eth), phy_type) == 4 +#define ETHER_PHY_CFG_TARGET_ICS1894_ENABLE 1 +#elif DT_PROP(DT_NODELABEL(eth), phy_type) == 3 +#define ETHER_PHY_CFG_TARGET_DP83620_ENABLE 1 +#elif DT_PROP(DT_NODELABEL(eth), phy_type) == 2 +#define ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE 1 +#elif DT_PROP(DT_NODELABEL(eth), phy_type) == 1 +#define ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE 1 +#else +#error "Invalid LSI type" +#endif + +#define ETHER_PHY_LSI_TYPE_KIT_COMPONENT DT_PROP(DT_NODELABEL(eth), phy_type) +#define BOARD_PHY_REF_CLK (1) + +#define ETHER_PHY_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#ifndef ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE +#define ETHER_PHY_CFG_TARGET_KSZ8091RNB_ENABLE (0) +#endif +#ifndef ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE +#define ETHER_PHY_CFG_TARGET_KSZ8041_ENABLE (1) +#endif +#ifndef ETHER_PHY_CFG_TARGET_DP83620_ENABLE +#define ETHER_PHY_CFG_TARGET_DP83620_ENABLE (0) +#endif +#ifndef ETHER_PHY_CFG_TARGET_ICS1894_ENABLE +#define ETHER_PHY_CFG_TARGET_ICS1894_ENABLE (0) +#endif +#ifndef ETHER_PHY_CFG_USE_CUSTOM_PHY_LSI_ENABLE +#define ETHER_PHY_CFG_USE_CUSTOM_PHY_LSI_ENABLE (0) +#endif +#define ETHER_PHY_CFG_USE_REF_CLK (BOARD_PHY_REF_CLK) +#define ETHER_PHY_CFG_INIT_PHY_LSI_AUTOMATIC (1) + +#ifdef __cplusplus +} +#endif +#endif /* R_ETHER_PHY_CFG_H_ */