- /**\r
- * \file\r
- *\r
- * \brief GMAC (Ethernet MAC) driver for SAM.\r
- *\r
- * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
- *\r
- * \asf_license_start\r
- *\r
- * \page License\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- *\r
- * 1. Redistributions of source code must retain the above copyright notice,\r
- * this list of conditions and the following disclaimer.\r
- *\r
- * 2. Redistributions in binary form must reproduce the above copyright notice,\r
- * this list of conditions and the following disclaimer in the documentation\r
- * and/or other materials provided with the distribution.\r
- *\r
- * 3. The name of Atmel may not be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * 4. This software may only be redistributed and used in connection with an\r
- * Atmel microcontroller product.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
- * POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- * \asf_license_stop\r
- *\r
- */\r
-\r
-#ifndef GMAC_H_INCLUDED\r
-#define GMAC_H_INCLUDED\r
-\r
-#include "compiler.h"\r
-\r
-/// @cond 0\r
-/**INDENT-OFF**/\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-/**INDENT-ON**/\r
-/// @endcond\r
-\r
-/** The buffer addresses written into the descriptors must be aligned, so the\r
- last few bits are zero. These bits have special meaning for the GMAC\r
- peripheral and cannot be used as part of the address. */\r
-#define GMAC_RXD_ADDR_MASK 0xFFFFFFFC\r
-#define GMAC_RXD_WRAP (1ul << 1) /**< Wrap bit */\r
-#define GMAC_RXD_OWNERSHIP (1ul << 0) /**< Ownership bit */\r
-\r
-#define GMAC_RXD_BROADCAST (1ul << 31) /**< Broadcast detected */\r
-#define GMAC_RXD_MULTIHASH (1ul << 30) /**< Multicast hash match */\r
-#define GMAC_RXD_UNIHASH (1ul << 29) /**< Unicast hash match */\r
-#define GMAC_RXD_ADDR_FOUND (1ul << 27) /**< Specific address match found */\r
-#define GMAC_RXD_ADDR (3ul << 25) /**< Address match */\r
-#define GMAC_RXD_RXCOEN (1ul << 24) /**< RXCOEN related function */\r
-#define GMAC_RXD_TYPE (3ul << 22) /**< Type ID match */\r
-#define GMAC_RXD_VLAN (1ul << 21) /**< VLAN tag detected */\r
-#define GMAC_RXD_PRIORITY (1ul << 20) /**< Priority tag detected */\r
-#define GMAC_RXD_PRIORITY_MASK (3ul << 17) /**< VLAN priority */\r
-#define GMAC_RXD_CFI (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */\r
-#define GMAC_RXD_EOF (1ul << 15) /**< End of frame */\r
-#define GMAC_RXD_SOF (1ul << 14) /**< Start of frame */\r
-#define GMAC_RXD_FCS (1ul << 13) /**< Frame check sequence */\r
-#define GMAC_RXD_OFFSET_MASK /**< Receive buffer offset */\r
-#define GMAC_RXD_LEN_MASK (0xFFF) /**< Length of frame including FCS (if selected) */\r
-#define GMAC_RXD_LENJUMBO_MASK (0x3FFF) /**< Jumbo frame length */\r
-\r
-#define GMAC_TXD_USED (1ul << 31) /**< Frame is transmitted */\r
-#define GMAC_TXD_WRAP (1ul << 30) /**< Last descriptor */\r
-#define GMAC_TXD_ERROR (1ul << 29) /**< Retry limit exceeded, error */\r
-#define GMAC_TXD_UNDERRUN (1ul << 28) /**< Transmit underrun */\r
-#define GMAC_TXD_EXHAUSTED (1ul << 27) /**< Buffer exhausted */\r
-#define GMAC_TXD_LATE (1ul << 26) /**< Late collision,transmit error */\r
-#define GMAC_TXD_CHECKSUM_ERROR (7ul << 20) /**< Checksum error */\r
-#define GMAC_TXD_NOCRC (1ul << 16) /**< No CRC */\r
-#define GMAC_TXD_LAST (1ul << 15) /**< Last buffer in frame */\r
-#define GMAC_TXD_LEN_MASK (0x1FFF) /**< Length of buffer */\r
-\r
-/** The MAC can support frame lengths up to 1536 bytes */\r
-#define GMAC_FRAME_LENTGH_MAX 1536\r
-\r
-#define GMAC_RX_UNITSIZE 128 /**< Fixed size for RX buffer */\r
-#define GMAC_TX_UNITSIZE 1518 /**< Size for ETH frame length */\r
-\r
-/** GMAC clock speed */\r
-#define GMAC_MCK_SPEED_240MHZ (240*1000*1000)\r
-#define GMAC_MCK_SPEED_160MHZ (160*1000*1000)\r
-#define GMAC_MCK_SPEED_120MHZ (120*1000*1000)\r
-#define GMAC_MCK_SPEED_80MHZ (80*1000*1000)\r
-#define GMAC_MCK_SPEED_40MHZ (40*1000*1000)\r
-#define GMAC_MCK_SPEED_20MHZ (20*1000*1000)\r
-\r
-/** GMAC maintain code default value*/\r
-#define GMAC_MAN_CODE_VALUE (10)\r
-\r
-/** GMAC maintain start of frame default value*/\r
-#define GMAC_MAN_SOF_VALUE (1)\r
-\r
-/** GMAC maintain read/write*/\r
-#define GMAC_MAN_RW_TYPE (2)\r
-\r
-/** GMAC maintain read only*/\r
-#define GMAC_MAN_READ_ONLY (1)\r
-\r
-/** GMAC address length */\r
-#define GMAC_ADDR_LENGTH (6)\r
-\r
-\r
-#define GMAC_DUPLEX_HALF 0\r
-#define GMAC_DUPLEX_FULL 1\r
-\r
-#define GMAC_SPEED_10M 0\r
-#define GMAC_SPEED_100M 1\r
-\r
-/**\r
- * \brief Return codes for GMAC APIs.\r
- */\r
-typedef enum {\r
- GMAC_OK = 0, /** 0 Operation OK */\r
- GMAC_TIMEOUT = 1, /** 1 GMAC operation timeout */\r
- GMAC_TX_BUSY, /** 2 TX in progress */\r
- GMAC_RX_NULL, /** 3 No data received */\r
- GMAC_SIZE_TOO_SMALL, /** 4 Buffer size not enough */\r
- GMAC_PARAM, /** 5 Parameter error, TX packet invalid or RX size too small */\r
- GMAC_INVALID = 0xFF, /* Invalid */\r
-} gmac_status_t;\r
-\r
-/**\r
- * \brief Media Independent Interface (MII) type.\r
- */\r
-typedef enum {\r
- GMAC_PHY_MII = 0, /** MII mode */\r
- GMAC_PHY_RMII = 1, /** Reduced MII mode */\r
- GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/\r
-} gmac_mii_mode_t;\r
-\r
-/** Receive buffer descriptor struct */\r
-COMPILER_PACK_SET(8)\r
-typedef struct gmac_rx_descriptor {\r
- union gmac_rx_addr {\r
- uint32_t val;\r
- struct gmac_rx_addr_bm {\r
- uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */\r
- b_wrap:1, /**< Marks last descriptor in receive buffer */\r
- addr_dw:30; /**< Address in number of DW */\r
- } bm;\r
- } addr; /**< Address, Wrap & Ownership */\r
- union gmac_rx_status {\r
- uint32_t val;\r
- struct gmac_rx_status_bm {\r
- uint32_t len:13, /** 0..12 Length of frame including FCS */\r
- b_fcs:1, /** 13 Receive buffer offset, bits 13:12 of frame length for jumbo frame */\r
- b_sof:1, /** 14 Start of frame */\r
- b_eof:1, /** 15 End of frame */\r
- b_cfi:1, /** 16 Concatenation Format Indicator */\r
- vlan_priority:3, /** 17..19 VLAN priority (if VLAN detected) */\r
- b_priority_detected:1, /** 20 Priority tag detected */\r
- b_vlan_detected:1, /** 21 VLAN tag detected */\r
- b_type_id_match:2, /** 22..23 Type ID match */\r
- b_checksumoffload:1, /** 24 Checksum offload specific function */\r
- b_addrmatch:2, /** 25..26 Address register match */\r
- b_ext_addr_match:1, /** 27 External address match found */\r
- reserved:1, /** 28 */\r
- b_uni_hash_match:1, /** 29 Unicast hash match */\r
- b_multi_hash_match:1, /** 30 Multicast hash match */\r
- b_boardcast_detect:1; /** 31 Global broadcast address detected */\r
- } bm;\r
- } status;\r
-} gmac_rx_descriptor_t;\r
-\r
-/** Transmit buffer descriptor struct */\r
-COMPILER_PACK_SET(8)\r
-typedef struct gmac_tx_descriptor {\r
- uint32_t addr;\r
- union gmac_tx_status {\r
- uint32_t val;\r
- struct gmac_tx_status_bm {\r
- uint32_t len:14, /** 0..13 Length of buffer */\r
- reserved:1, /** 14 */\r
- b_last_buffer:1, /** 15 Last buffer (in the current frame) */\r
- b_no_crc:1, /** 16 No CRC */\r
- reserved1:3, /** 17..19 */\r
- b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */\r
- reserved2:3, /** 23..25 */\r
- b_lco:1, /** 26 Late collision, transmit error detected */\r
- b_exhausted:1, /** 27 Buffer exhausted in mid frame */\r
- b_underrun:1, /** 28 Transmit underrun */\r
- b_error:1, /** 29 Retry limit exceeded, error detected */\r
- b_wrap:1, /** 30 Marks last descriptor in TD list */\r
- b_used:1; /** 31 User clear, GMAC sets this to 1 once a frame has been successfully transmitted */\r
- } bm;\r
- } status;\r
-} gmac_tx_descriptor_t;\r
-\r
-COMPILER_PACK_RESET()\r
-\r
-/**\r
- * \brief Input parameters when initializing the gmac module mode.\r
- */\r
-typedef struct gmac_options {\r
- /* Enable/Disable CopyAllFrame */\r
- uint8_t uc_copy_all_frame;\r
- /* Enable/Disable NoBroadCast */\r
- uint8_t uc_no_boardcast;\r
- /* MAC address */\r
- uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];\r
-} gmac_options_t;\r
-\r
-/** RX callback */\r
-typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status);\r
-/** Wakeup callback */\r
-typedef void (*gmac_dev_wakeup_cb_t) (void);\r
-\r
-/**\r
- * GMAC driver structure.\r
- */\r
-typedef struct gmac_device {\r
-\r
- /** Pointer to HW register base */\r
- Gmac *p_hw;\r
- /**\r
- * Pointer to allocated TX buffer.\r
- * Section 3.6 of AMBA 2.0 spec states that burst should not cross\r
- * 1K Boundaries.\r
- * Receive buffer manager writes are burst of 2 words => 3 lsb bits\r
- * of the address shall be set to 0.\r
- */\r
- uint8_t *p_tx_buffer;\r
- /** Pointer to allocated RX buffer */\r
- uint8_t *p_rx_buffer;\r
- /** Pointer to Rx TDs (must be 8-byte aligned) */\r
- gmac_rx_descriptor_t *p_rx_dscr;\r
- /** Pointer to Tx TDs (must be 8-byte aligned) */\r
- gmac_tx_descriptor_t *p_tx_dscr;\r
- /** Optional callback to be invoked once a frame has been received */\r
- gmac_dev_tx_cb_t func_rx_cb;\r
-#if( GMAC_USES_WAKEUP_CALLBACK )\r
- /** Optional callback to be invoked once several TDs have been released */\r
- gmac_dev_wakeup_cb_t func_wakeup_cb;\r
-#endif\r
-#if( GMAC_USES_TX_CALLBACK != 0 )\r
- /** Optional callback list to be invoked once TD has been processed */\r
- gmac_dev_tx_cb_t *func_tx_cb_list;\r
-#endif\r
- /** RX TD list size */\r
- uint32_t ul_rx_list_size;\r
- /** RX index for current processing TD */\r
- uint32_t ul_rx_idx;\r
- /** TX TD list size */\r
- uint32_t ul_tx_list_size;\r
- /** Circular buffer head pointer by upper layer (buffer to be sent) */\r
- int32_t l_tx_head;\r
- /** Circular buffer tail pointer incremented by handlers (buffer sent) */\r
- int32_t l_tx_tail;\r
-\r
- /** Number of free TD before wakeup callback is invoked */\r
- uint32_t uc_wakeup_threshold;\r
-} gmac_device_t;\r
-\r
-/**\r
- * \brief Write network control value.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_ncr Network control value.\r
- */\r
-static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)\r
-{\r
- p_gmac->GMAC_NCR = ul_ncr;\r
-}\r
-\r
-/**\r
- * \brief Get network control value.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-\r
-static inline uint32_t gmac_get_network_control(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_NCR;\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable GMAC receive.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable GMAC receiver, else to enable it.\r
- */\r
-static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;\r
- } else {\r
- p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable GMAC transmit.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable GMAC transmit, else to enable it.\r
- */\r
-static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;\r
- } else {\r
- p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable GMAC management.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable GMAC management, else to enable it.\r
- */\r
-static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCR |= GMAC_NCR_MPE;\r
- } else {\r
- p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Clear all statistics registers.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_clear_statistics(Gmac* p_gmac)\r
-{\r
- p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;\r
-}\r
-\r
-/**\r
- * \brief Increase all statistics registers.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_increase_statistics(Gmac* p_gmac)\r
-{\r
- p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable statistics registers writing.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable the statistics registers writing, else to enable it.\r
- */\r
-static inline void gmac_enable_statistics_write(Gmac* p_gmac,\r
- uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;\r
- } else {\r
- p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;\r
- }\r
-}\r
-\r
-/**\r
- * \brief In half-duplex mode, forces collisions on all received frames.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable the back pressure, else to enable it.\r
- */\r
-static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCR |= GMAC_NCR_BP;\r
- } else {\r
- p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Start transmission.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_start_transmission(Gmac* p_gmac)\r
-{\r
- p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;\r
-}\r
-\r
-/**\r
- * \brief Halt transmission.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_halt_transmission(Gmac* p_gmac)\r
-{\r
- p_gmac->GMAC_NCR |= GMAC_NCR_THALT;\r
-}\r
-\r
-/**\r
- * \brief Transmit pause frame.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_tx_pause_frame(Gmac* p_gmac)\r
-{\r
- p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;\r
-}\r
-\r
-/**\r
- * \brief Transmit zero quantum pause frame.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)\r
-{\r
- p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;\r
-}\r
-\r
-/**\r
- * \brief Read snapshot.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_read_snapshot(Gmac* p_gmac)\r
-{\r
- p_gmac->GMAC_NCR |= GMAC_NCR_RDS;\r
-}\r
-\r
-/**\r
- * \brief Store receivetime stamp to memory.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to normal operation, else to enable the store.\r
- */\r
-static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;\r
- } else {\r
- p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable PFC priority-based pause reception.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 1 to set the reception, 0 to disable.\r
- */\r
-static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;\r
- } else {\r
- p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Transmit PFC priority-based pause reception.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)\r
-{\r
- p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;\r
-}\r
-\r
-/**\r
- * \brief Flush next packet.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_flush_next_packet(Gmac* p_gmac)\r
-{\r
- p_gmac->GMAC_NCR |= GMAC_NCR_FNP;\r
-}\r
-\r
-/**\r
- * \brief Set up network configuration register.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_cfg Network configuration value.\r
- */\r
-static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)\r
-{\r
- p_gmac->GMAC_NCFGR = ul_cfg;\r
-}\r
-\r
-/**\r
- * \brief Get network configuration.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return Network configuration.\r
- */\r
-static inline uint32_t gmac_get_configure(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_NCFGR;\r
-}\r
-\r
-\r
-/* Get and set DMA Configuration Register */\r
-static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)\r
-{\r
- p_gmac->GMAC_DCFGR = ul_cfg;\r
-}\r
-\r
-static inline uint32_t gmac_get_dma(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_DCFGR;\r
-}\r
-\r
-/**\r
- * \brief Set speed.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.\r
- */\r
-static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)\r
-{\r
- if (uc_speed) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable Full-Duplex mode.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable the Full-Duplex mode, else to enable it.\r
- */\r
-static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable Copy(Receive) All Valid Frames.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable copying all valid frames, else to enable it.\r
- */\r
-static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable jumbo frames (up to 10240 bytes).\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable the jumbo frames, else to enable it.\r
- */\r
-static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Disable/Enable broadcast receiving.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 1 to disable the broadcast, else to enable it.\r
- */\r
-static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable multicast hash.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable the multicast hash, else to enable it.\r
- */\r
-static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable big frames (over 1518, up to 1536).\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable big frames else to enable it.\r
- */\r
-static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Set MDC clock divider.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_mck GMAC MCK.\r
- *\r
- * \return GMAC_OK if successfully.\r
- */\r
-static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)\r
-{\r
- uint32_t ul_clk;\r
- \r
- if (ul_mck > GMAC_MCK_SPEED_240MHZ) {\r
- return GMAC_INVALID;\r
- } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {\r
- ul_clk = GMAC_NCFGR_CLK_MCK_96;\r
- } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {\r
- ul_clk = GMAC_NCFGR_CLK_MCK_64;\r
- } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {\r
- ul_clk = GMAC_NCFGR_CLK_MCK_48;\r
- } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {\r
- ul_clk = GMAC_NCFGR_CLK_MCK_32;\r
- } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {\r
- ul_clk = GMAC_NCFGR_CLK_MCK_16;\r
- } else {\r
- ul_clk = GMAC_NCFGR_CLK_MCK_8;\r
- }\r
- ;\r
- p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;\r
- return GMAC_OK;\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable retry test.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable the GMAC receiver, else to enable it.\r
- */\r
-static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable pause (when a valid pause frame is received).\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable pause frame, else to enable it.\r
- */\r
-static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Set receive buffer offset to 0 ~ 3.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)\r
-{\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable receive length field checking.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable receive length field checking, else to enable it.\r
- */\r
-static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable discarding FCS field of received frames.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable discarding FCS field of received frames, else to enable it.\r
- */\r
-static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;\r
- }\r
-}\r
-\r
-\r
-/**\r
- * \brief Enable/Disable frames to be received in half-duplex mode\r
- * while transmitting.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable the received in half-duplex mode, else to enable it.\r
- */\r
-static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Enable/Disable ignore RX FCS.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_enable 0 to disable ignore RX FCS, else to enable it.\r
- */\r
-static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
-{\r
- if (uc_enable) {\r
- p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;\r
- } else {\r
- p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;\r
- }\r
-}\r
-\r
-/**\r
- * \brief Get Network Status.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return Network status.\r
- */\r
-static inline uint32_t gmac_get_status(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_NSR;\r
-}\r
-\r
-/**\r
- * \brief Get MDIO IN pin status.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return MDIO IN pin status.\r
- */\r
-static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)\r
-{\r
- return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);\r
-}\r
-\r
-/**\r
- * \brief Check if PHY is idle.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return 1 if PHY is idle.\r
- */\r
-static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)\r
-{\r
- return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);\r
-}\r
-\r
-/**\r
- * \brief Return transmit status.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return Transmit status.\r
- */\r
-static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_TSR;\r
-}\r
-\r
-/**\r
- * \brief Clear transmit status.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_status Transmit status.\r
- */\r
-static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)\r
-{\r
- p_gmac->GMAC_TSR = ul_status;\r
-}\r
-\r
-/**\r
- * \brief Return receive status.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- */\r
-static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_RSR;\r
-}\r
-\r
-/**\r
- * \brief Clear receive status.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_status Receive status.\r
- */\r
-static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)\r
-{\r
- p_gmac->GMAC_RSR = ul_status;\r
-}\r
-\r
-/**\r
- * \brief Set Rx Queue.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_addr Rx queue address.\r
- */\r
-static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
-{\r
- p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;\r
-}\r
-\r
-/**\r
- * \brief Get Rx Queue Address.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return Rx queue address.\r
- */\r
-static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_RBQB;\r
-}\r
-\r
-/**\r
- * \brief Set Tx Queue.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_addr Tx queue address.\r
- */\r
-static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
-{\r
- p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;\r
-}\r
-\r
-/**\r
- * \brief Get Tx Queue.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return Rx queue address.\r
- */\r
-static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_TBQB;\r
-}\r
-\r
-/**\r
- * \brief Enable interrupt(s).\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_source Interrupt source(s) to be enabled.\r
- */\r
-static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
-{\r
- p_gmac->GMAC_IER = ul_source;\r
-}\r
-\r
-/**\r
- * \brief Disable interrupt(s).\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_source Interrupt source(s) to be disabled.\r
- */\r
-static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
-{\r
- p_gmac->GMAC_IDR = ul_source;\r
-}\r
-\r
-/**\r
- * \brief Return interrupt status.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return Interrupt status.\r
- */\r
-static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_ISR;\r
-}\r
-\r
-/**\r
- * \brief Return interrupt mask.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return Interrupt mask.\r
- */\r
-static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)\r
-{\r
- return p_gmac->GMAC_IMR;\r
-}\r
-\r
-/**\r
- * \brief Execute PHY maintenance command.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_phy_addr PHY address.\r
- * \param uc_reg_addr Register address.\r
- * \param uc_rw 1 to Read, 0 to write.\r
- * \param us_data Data to be performed, write only.\r
- */\r
-static inline void gmac_maintain_phy(Gmac* p_gmac,\r
- uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,\r
- uint16_t us_data)\r
-{\r
- /* Wait until bus idle */\r
- while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
- /* Write maintain register */\r
- p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)\r
- | GMAC_MAN_CLTTO \r
- | GMAC_MAN_PHYA(uc_phy_addr)\r
- | GMAC_MAN_REGA(uc_reg_addr)\r
- | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))\r
- | GMAC_MAN_DATA(us_data);\r
-}\r
-\r
-/**\r
- * \brief Get PHY maintenance data returned.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- *\r
- * \return Get PHY data.\r
- */\r
-static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)\r
-{\r
- /* Wait until bus idle */\r
- while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
- /* Return data */\r
- return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);\r
-}\r
-\r
-/**\r
- * \brief Set Hash.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ul_hash_top Hash top.\r
- * \param ul_hash_bottom Hash bottom.\r
- */\r
-static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,\r
- uint32_t ul_hash_bottom)\r
-{\r
- p_gmac->GMAC_HRB = ul_hash_bottom;\r
- p_gmac->GMAC_HRT = ul_hash_top;\r
-}\r
-\r
-/**\r
- * \brief Set 64 bits Hash.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param ull_hash 64 bits hash value.\r
- */\r
-static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)\r
-{\r
- p_gmac->GMAC_HRB = (uint32_t) ull_hash;\r
- p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);\r
-}\r
-\r
-/**\r
- * \brief Set MAC Address.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_index GMAC specific address register index.\r
- * \param p_mac_addr GMAC address.\r
- */\r
-static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,\r
- uint8_t* p_mac_addr)\r
-{\r
- p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)\r
- | (p_mac_addr[2] << 16)\r
- | (p_mac_addr[1] << 8)\r
- | (p_mac_addr[0]);\r
- p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)\r
- | (p_mac_addr[4]);\r
-}\r
-\r
-/**\r
- * \brief Set MAC Address via 2 dword.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_index GMAC specific address register index.\r
- * \param ul_mac_top GMAC top address.\r
- * \param ul_mac_bottom GMAC bottom address.\r
- */\r
-static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,\r
- uint32_t ul_mac_top, uint32_t ul_mac_bottom)\r
-{\r
- p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;\r
- p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;\r
-}\r
-\r
-/**\r
- * \brief Set MAC Address via int64.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param uc_index GMAC specific address register index.\r
- * \param ull_mac 64-bit GMAC address.\r
- */\r
-static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,\r
- uint64_t ull_mac)\r
-{\r
- p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;\r
- p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);\r
-}\r
-\r
-/**\r
- * \brief Select media independent interface mode.\r
- *\r
- * \param p_gmac Pointer to the GMAC instance.\r
- * \param mode Media independent interface mode.\r
- */\r
-static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)\r
-{\r
- switch (mode) {\r
- case GMAC_PHY_MII:\r
- case GMAC_PHY_RMII:\r
- p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;\r
- break;\r
-\r
- default:\r
- p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;\r
- break;\r
- }\r
-}\r
-\r
-uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
- uint32_t* p_value);\r
-uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
- uint8_t uc_address, uint32_t ul_value);\r
-void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
- gmac_options_t* p_opt);\r
-uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
- uint32_t ul_frame_size, uint32_t* p_rcv_size);\r
-uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
- uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);\r
-uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);\r
-void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
- gmac_dev_tx_cb_t func_rx_cb);\r
-uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
- gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);\r
-void gmac_dev_reset(gmac_device_t* p_gmac_dev);\r
-void gmac_handler(gmac_device_t* p_gmac_dev);\r
-\r
-/// @cond 0\r
-/**INDENT-OFF**/\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-/**INDENT-ON**/\r
-/// @endcond\r
-\r
-/**\r
- * \page gmac_quickstart Quickstart guide for GMAC driver.\r
- *\r
- * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",\r
- * with step-by-step instructions on how to configure and use the driver in a\r
- * selection of use cases.\r
- *\r
- * The use cases contain several code fragments. The code fragments in the\r
- * steps for setup can be copied into a custom initialization function, while\r
- * the steps for usage can be copied into, e.g., the main application function.\r
- *\r
- * \section gmac_basic_use_case Basic use case\r
- * In the basic use case, the GMAC driver are configured for:\r
- * - PHY component KSZ8051MNL is used\r
- * - GMAC uses MII mode\r
- * - The number of receive buffer is 16\r
- * - The number of transfer buffer is 8\r
- * - MAC address is set to 00-04-25-1c-a0-02\r
- * - IP address is set to 192.168.0.2\r
- * - IP address is set to 192.168.0.2\r
- * - Gateway is set to 192.168.0.1\r
- * - Network mask is 255.255.255.0\r
- * - PHY operation max retry count is 1000000\r
- * - GMAC is configured to not support copy all frame and support broadcast\r
- * - The data will be read from the ethernet\r
- *\r
- * \section gmac_basic_use_case_setup Setup steps\r
- *\r
- * \subsection gmac_basic_use_case_setup_prereq Prerequisites\r
- * -# \ref sysclk_group "System Clock Management (sysclock)"\r
- * -# \ref pmc_group "Power Management Controller (pmc)"\r
- * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"\r
- *\r
- * \subsection gmac_basic_use_case_setup_code Example code\r
- * Content of conf_eth.h\r
- * \code\r
- * #define GMAC_RX_BUFFERS 16\r
- * #define GMAC_TX_BUFFERS 8\r
- * #define MAC_PHY_RETRY_MAX 1000000\r
- * #define ETHERNET_CONF_ETHADDR0 0x00\r
- * #define ETHERNET_CONF_ETHADDR0 0x00\r
- * #define ETHERNET_CONF_ETHADDR1 0x04\r
- * #define ETHERNET_CONF_ETHADDR2 0x25\r
- * #define ETHERNET_CONF_ETHADDR3 0x1C\r
- * #define ETHERNET_CONF_ETHADDR4 0xA0\r
- * #define ETHERNET_CONF_ETHADDR5 0x02\r
- * #define ETHERNET_CONF_IPADDR0 192\r
- * #define ETHERNET_CONF_IPADDR1 168\r
- * #define ETHERNET_CONF_IPADDR2 0\r
- * #define ETHERNET_CONF_IPADDR3 2\r
- * #define ETHERNET_CONF_GATEWAY_ADDR0 192\r
- * #define ETHERNET_CONF_GATEWAY_ADDR1 168\r
- * #define ETHERNET_CONF_GATEWAY_ADDR2 0\r
- * #define ETHERNET_CONF_GATEWAY_ADDR3 1\r
- * #define ETHERNET_CONF_NET_MASK0 255\r
- * #define ETHERNET_CONF_NET_MASK1 255\r
- * #define ETHERNET_CONF_NET_MASK2 255\r
- * #define ETHERNET_CONF_NET_MASK3 0\r
- * #define ETH_PHY_MODE ETH_PHY_MODE\r
- * \endcode\r
- *\r
- * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined\r
- * to trace the actual size of the data received.\r
- * \code\r
- * static gmac_device_t gs_gmac_dev;\r
- * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];\r
- *\r
- * uint32_t ul_frm_size;\r
- * \endcode\r
- *\r
- * Add to application C-file:\r
- * \code\r
- * void gmac_init(void)\r
- * {\r
- * sysclk_init();\r
- *\r
- * board_init();\r
- *\r
- * pmc_enable_periph_clk(ID_GMAC);\r
- *\r
- * gmac_option.uc_copy_all_frame = 0;\r
- * gmac_option.uc_no_boardcast = 0;\r
- * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
- * gs_gmac_dev.p_hw = GMAC;\r
- *\r
- * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
- *\r
- * NVIC_EnableIRQ(GMAC_IRQn);\r
- *\r
- * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
- * \r
- * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
- *\r
- * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
- * \endcode\r
- *\r
- * \subsection gmac_basic_use_case_setup_flow Workflow\r
- * - Ensure that conf_eth.h is present and contains the\r
- * following configuration symbol. This configuration file is used\r
- * by the driver and should not be included by the application.\r
- * -# Define the receiving buffer size used in the internal GMAC driver.\r
- * The buffer size used for RX is GMAC_RX_BUFFERS * 128.\r
- * If it was supposed receiving a large number of frame, the\r
- * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept\r
- * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least \r
- * (2048/128)=16, and as there are additional frames coming, a preferred\r
- * number is 24 depending on a normal Ethernet throughput.\r
- * - \code\r
- * #define GMAC_RX_BUFFERS 16\r
- * \endcode\r
- * -# Define the transmitting buffer size used in the internal GMAC driver.\r
- * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.\r
- * - \code\r
- * #define GMAC_TX_BUFFERS 8\r
- * \endcode\r
- * -# Define maximum retry time for a PHY read/write operation.\r
- * - \code\r
- * #define MAC_PHY_RETRY_MAX 1000000\r
- * \endcode\r
- * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved\r
- * for ATMEL, application should always change this address to its' own.\r
- * - \code\r
- * #define ETHERNET_CONF_ETHADDR0 0x00\r
- * #define ETHERNET_CONF_ETHADDR1 0x04\r
- * #define ETHERNET_CONF_ETHADDR2 0x25\r
- * #define ETHERNET_CONF_ETHADDR3 0x1C\r
- * #define ETHERNET_CONF_ETHADDR4 0xA0\r
- * #define ETHERNET_CONF_ETHADDR5 0x02\r
- * \endcode\r
- * -# Define the IP address configration used in the application. When DHCP\r
- * is enabled, this configuration is not effected.\r
- * - \code\r
- * #define ETHERNET_CONF_IPADDR0 192\r
- * #define ETHERNET_CONF_IPADDR1 168\r
- * #define ETHERNET_CONF_IPADDR2 0\r
- * #define ETHERNET_CONF_IPADDR3 2\r
- * #define ETHERNET_CONF_GATEWAY_ADDR0 192\r
- * #define ETHERNET_CONF_GATEWAY_ADDR1 168\r
- * #define ETHERNET_CONF_GATEWAY_ADDR2 0\r
- * #define ETHERNET_CONF_GATEWAY_ADDR3 1\r
- * #define ETHERNET_CONF_NET_MASK0 255\r
- * #define ETHERNET_CONF_NET_MASK1 255\r
- * #define ETHERNET_CONF_NET_MASK2 255\r
- * #define ETHERNET_CONF_NET_MASK3 0\r
- * \endcode\r
- * -# Configure the PHY maintainance interface.\r
- * - \code\r
- * #define ETH_PHY_MODE GMAC_PHY_MII\r
- * \endcode\r
- * -# Enable the system clock:\r
- * - \code sysclk_init(); \endcode\r
- * -# Enable PIO configurations for GMAC:\r
- * - \code board_init(); \endcode\r
- * -# Enable PMC clock for GMAC:\r
- * - \code pmc_enable_periph_clk(ID_GMAC); \endcode\r
- * -# Set the GMAC options; it's set to copy all frame and support broadcast:\r
- * - \code\r
- * gmac_option.uc_copy_all_frame = 0;\r
- * gmac_option.uc_no_boardcast = 0;\r
- * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
- * gs_gmac_dev.p_hw = GMAC;\r
- * \endcode\r
- * -# Initialize GMAC device with the filled option:\r
- * - \code\r
- * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
- * \endcode\r
- * -# Enable the interrupt service for GMAC:\r
- * - \code\r
- * NVIC_EnableIRQ(GMAC_IRQn);\r
- * \endcode\r
- * -# Initialize the PHY component:\r
- * - \code\r
- * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
- * \endcode\r
- * -# The link will be established based on auto negotiation.\r
- * - \code\r
- * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
- * \endcode\r
- * -# Establish the ethernet link; the network can be worked from now on:\r
- * - \code\r
- * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
- * \endcode\r
- *\r
- * \section gmac_basic_use_case_usage Usage steps\r
- * \subsection gmac_basic_use_case_usage_code Example code\r
- * Add to, e.g., main loop in application C-file:\r
- * \code\r
- * gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));\r
- * \endcode\r
- *\r
- * \subsection gmac_basic_use_case_usage_flow Workflow\r
- * -# Start reading the data from the ethernet:\r
- * - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode\r
- */\r
-\r
-# define GMAC_STATS 0\r
-\r
-#if( GMAC_STATS != 0 )\r
-\r
- /* Here below some code to study the types and\r
- frequencies of GMAC interrupts. */\r
- #define GMAC_IDX_RXUBR 0\r
- #define GMAC_IDX_TUR 1\r
- #define GMAC_IDX_RLEX 2\r
- #define GMAC_IDX_TFC 3\r
- #define GMAC_IDX_RCOMP 4\r
- #define GMAC_IDX_TCOMP 5\r
- #define GMAC_IDX_ROVR 6\r
- #define GMAC_IDX_HRESP 7\r
- #define GMAC_IDX_PFNZ 8\r
- #define GMAC_IDX_PTZ 9\r
-\r
- struct SGmacStats {\r
- unsigned recvCount;\r
- unsigned rovrCount;\r
- unsigned bnaCount;\r
- unsigned sendCount;\r
- unsigned sovrCount;\r
- unsigned incompCount;\r
- unsigned truncCount;\r
-\r
- unsigned intStatus[10];\r
- };\r
- extern struct SGmacStats gmacStats;\r
-\r
- struct SIntPair {\r
- const char *name;\r
- unsigned mask;\r
- int index;\r
- };\r
-\r
- #define MK_PAIR( NAME ) #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME\r
- static const struct SIntPair intPairs[] = {\r
- { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */\r
- { MK_PAIR( TUR ) }, /* Enable transmit underrun interrupt. */\r
- { MK_PAIR( RLEX ) }, /* Enable retry limit exceeded interrupt. */\r
- { MK_PAIR( TFC ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
- { MK_PAIR( RCOMP ) }, /* Receive complete */\r
- { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */\r
- { MK_PAIR( ROVR ) }, /* Enable receive overrun interrupt. */\r
- { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */\r
- { MK_PAIR( PFNZ ) }, /* Enable pause frame received interrupt. */\r
- { MK_PAIR( PTZ ) } /* Enable pause time zero interrupt. */\r
- };\r
-\r
- void gmac_show_irq_counts ();\r
-\r
-#endif\r
-\r
-#endif /* GMAC_H_INCLUDED */\r
+ /**
+ * \file
+ *
+ * \brief GMAC (Ethernet MAC) driver for SAM.
+ *
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef GMAC_H_INCLUDED
+#define GMAC_H_INCLUDED
+
+#include "compiler.h"
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/** The buffer addresses written into the descriptors must be aligned, so the
+ last few bits are zero. These bits have special meaning for the GMAC
+ peripheral and cannot be used as part of the address. */
+#define GMAC_RXD_ADDR_MASK 0xFFFFFFFC
+#define GMAC_RXD_WRAP (1ul << 1) /**< Wrap bit */
+#define GMAC_RXD_OWNERSHIP (1ul << 0) /**< Ownership bit */
+
+#define GMAC_RXD_BROADCAST (1ul << 31) /**< Broadcast detected */
+#define GMAC_RXD_MULTIHASH (1ul << 30) /**< Multicast hash match */
+#define GMAC_RXD_UNIHASH (1ul << 29) /**< Unicast hash match */
+#define GMAC_RXD_ADDR_FOUND (1ul << 27) /**< Specific address match found */
+#define GMAC_RXD_ADDR (3ul << 25) /**< Address match */
+#define GMAC_RXD_RXCOEN (1ul << 24) /**< RXCOEN related function */
+#define GMAC_RXD_TYPE (3ul << 22) /**< Type ID match */
+#define GMAC_RXD_VLAN (1ul << 21) /**< VLAN tag detected */
+#define GMAC_RXD_PRIORITY (1ul << 20) /**< Priority tag detected */
+#define GMAC_RXD_PRIORITY_MASK (3ul << 17) /**< VLAN priority */
+#define GMAC_RXD_CFI (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */
+#define GMAC_RXD_EOF (1ul << 15) /**< End of frame */
+#define GMAC_RXD_SOF (1ul << 14) /**< Start of frame */
+#define GMAC_RXD_FCS (1ul << 13) /**< Frame check sequence */
+#define GMAC_RXD_OFFSET_MASK /**< Receive buffer offset */
+#define GMAC_RXD_LEN_MASK (0xFFF) /**< Length of frame including FCS (if selected) */
+#define GMAC_RXD_LENJUMBO_MASK (0x3FFF) /**< Jumbo frame length */
+
+#define GMAC_TXD_USED (1ul << 31) /**< Frame is transmitted */
+#define GMAC_TXD_WRAP (1ul << 30) /**< Last descriptor */
+#define GMAC_TXD_ERROR (1ul << 29) /**< Retry limit exceeded, error */
+#define GMAC_TXD_UNDERRUN (1ul << 28) /**< Transmit underrun */
+#define GMAC_TXD_EXHAUSTED (1ul << 27) /**< Buffer exhausted */
+#define GMAC_TXD_LATE (1ul << 26) /**< Late collision,transmit error */
+#define GMAC_TXD_CHECKSUM_ERROR (7ul << 20) /**< Checksum error */
+#define GMAC_TXD_NOCRC (1ul << 16) /**< No CRC */
+#define GMAC_TXD_LAST (1ul << 15) /**< Last buffer in frame */
+#define GMAC_TXD_LEN_MASK (0x1FFF) /**< Length of buffer */
+
+/** The MAC can support frame lengths up to 1536 bytes */
+#define GMAC_FRAME_LENTGH_MAX 1536
+
+#define GMAC_RX_UNITSIZE 128 /**< Fixed size for RX buffer */
+#define GMAC_TX_UNITSIZE 1518 /**< Size for ETH frame length */
+
+/** GMAC clock speed */
+#define GMAC_MCK_SPEED_240MHZ (240*1000*1000)
+#define GMAC_MCK_SPEED_160MHZ (160*1000*1000)
+#define GMAC_MCK_SPEED_120MHZ (120*1000*1000)
+#define GMAC_MCK_SPEED_80MHZ (80*1000*1000)
+#define GMAC_MCK_SPEED_40MHZ (40*1000*1000)
+#define GMAC_MCK_SPEED_20MHZ (20*1000*1000)
+
+/** GMAC maintain code default value*/
+#define GMAC_MAN_CODE_VALUE (10)
+
+/** GMAC maintain start of frame default value*/
+#define GMAC_MAN_SOF_VALUE (1)
+
+/** GMAC maintain read/write*/
+#define GMAC_MAN_RW_TYPE (2)
+
+/** GMAC maintain read only*/
+#define GMAC_MAN_READ_ONLY (1)
+
+/** GMAC address length */
+#define GMAC_ADDR_LENGTH (6)
+
+
+#define GMAC_DUPLEX_HALF 0
+#define GMAC_DUPLEX_FULL 1
+
+#define GMAC_SPEED_10M 0
+#define GMAC_SPEED_100M 1
+
+/**
+ * \brief Return codes for GMAC APIs.
+ */
+typedef enum {
+ GMAC_OK = 0, /** 0 Operation OK */
+ GMAC_TIMEOUT = 1, /** 1 GMAC operation timeout */
+ GMAC_TX_BUSY, /** 2 TX in progress */
+ GMAC_RX_NULL, /** 3 No data received */
+ GMAC_SIZE_TOO_SMALL, /** 4 Buffer size not enough */
+ GMAC_PARAM, /** 5 Parameter error, TX packet invalid or RX size too small */
+ GMAC_INVALID = 0xFF, /* Invalid */
+} gmac_status_t;
+
+/**
+ * \brief Media Independent Interface (MII) type.
+ */
+typedef enum {
+ GMAC_PHY_MII = 0, /** MII mode */
+ GMAC_PHY_RMII = 1, /** Reduced MII mode */
+ GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/
+} gmac_mii_mode_t;
+
+/** Receive buffer descriptor struct */
+COMPILER_PACK_SET(8)
+typedef struct gmac_rx_descriptor {
+ union gmac_rx_addr {
+ uint32_t val;
+ struct gmac_rx_addr_bm {
+ uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */
+ b_wrap:1, /**< Marks last descriptor in receive buffer */
+ addr_dw:30; /**< Address in number of DW */
+ } bm;
+ } addr; /**< Address, Wrap & Ownership */
+ union gmac_rx_status {
+ uint32_t val;
+ struct gmac_rx_status_bm {
+ uint32_t len:13, /** 0..12 Length of frame including FCS */
+ b_fcs:1, /** 13 Receive buffer offset, bits 13:12 of frame length for jumbo frame */
+ b_sof:1, /** 14 Start of frame */
+ b_eof:1, /** 15 End of frame */
+ b_cfi:1, /** 16 Concatenation Format Indicator */
+ vlan_priority:3, /** 17..19 VLAN priority (if VLAN detected) */
+ b_priority_detected:1, /** 20 Priority tag detected */
+ b_vlan_detected:1, /** 21 VLAN tag detected */
+ b_type_id_match:2, /** 22..23 Type ID match */
+ b_checksumoffload:1, /** 24 Checksum offload specific function */
+ b_addrmatch:2, /** 25..26 Address register match */
+ b_ext_addr_match:1, /** 27 External address match found */
+ reserved:1, /** 28 */
+ b_uni_hash_match:1, /** 29 Unicast hash match */
+ b_multi_hash_match:1, /** 30 Multicast hash match */
+ b_boardcast_detect:1; /** 31 Global broadcast address detected */
+ } bm;
+ } status;
+} gmac_rx_descriptor_t;
+
+/** Transmit buffer descriptor struct */
+COMPILER_PACK_SET(8)
+typedef struct gmac_tx_descriptor {
+ uint32_t addr;
+ union gmac_tx_status {
+ uint32_t val;
+ struct gmac_tx_status_bm {
+ uint32_t len:14, /** 0..13 Length of buffer */
+ reserved:1, /** 14 */
+ b_last_buffer:1, /** 15 Last buffer (in the current frame) */
+ b_no_crc:1, /** 16 No CRC */
+ reserved1:3, /** 17..19 */
+ b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */
+ reserved2:3, /** 23..25 */
+ b_lco:1, /** 26 Late collision, transmit error detected */
+ b_exhausted:1, /** 27 Buffer exhausted in mid frame */
+ b_underrun:1, /** 28 Transmit underrun */
+ b_error:1, /** 29 Retry limit exceeded, error detected */
+ b_wrap:1, /** 30 Marks last descriptor in TD list */
+ b_used:1; /** 31 User clear, GMAC sets this to 1 once a frame has been successfully transmitted */
+ } bm;
+ } status;
+} gmac_tx_descriptor_t;
+
+COMPILER_PACK_RESET()
+
+/**
+ * \brief Input parameters when initializing the gmac module mode.
+ */
+typedef struct gmac_options {
+ /* Enable/Disable CopyAllFrame */
+ uint8_t uc_copy_all_frame;
+ /* Enable/Disable NoBroadCast */
+ uint8_t uc_no_boardcast;
+ /* MAC address */
+ uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];
+} gmac_options_t;
+
+/** RX callback */
+typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status);
+/** Wakeup callback */
+typedef void (*gmac_dev_wakeup_cb_t) (void);
+
+/**
+ * GMAC driver structure.
+ */
+typedef struct gmac_device {
+
+ /** Pointer to HW register base */
+ Gmac *p_hw;
+ /**
+ * Pointer to allocated TX buffer.
+ * Section 3.6 of AMBA 2.0 spec states that burst should not cross
+ * 1K Boundaries.
+ * Receive buffer manager writes are burst of 2 words => 3 lsb bits
+ * of the address shall be set to 0.
+ */
+ uint8_t *p_tx_buffer;
+ /** Pointer to allocated RX buffer */
+ uint8_t *p_rx_buffer;
+ /** Pointer to Rx TDs (must be 8-byte aligned) */
+ gmac_rx_descriptor_t *p_rx_dscr;
+ /** Pointer to Tx TDs (must be 8-byte aligned) */
+ gmac_tx_descriptor_t *p_tx_dscr;
+ /** Optional callback to be invoked once a frame has been received */
+ gmac_dev_tx_cb_t func_rx_cb;
+#if( GMAC_USES_WAKEUP_CALLBACK )
+ /** Optional callback to be invoked once several TDs have been released */
+ gmac_dev_wakeup_cb_t func_wakeup_cb;
+#endif
+#if( GMAC_USES_TX_CALLBACK != 0 )
+ /** Optional callback list to be invoked once TD has been processed */
+ gmac_dev_tx_cb_t *func_tx_cb_list;
+#endif
+ /** RX TD list size */
+ uint32_t ul_rx_list_size;
+ /** RX index for current processing TD */
+ uint32_t ul_rx_idx;
+ /** TX TD list size */
+ uint32_t ul_tx_list_size;
+ /** Circular buffer head pointer by upper layer (buffer to be sent) */
+ int32_t l_tx_head;
+ /** Circular buffer tail pointer incremented by handlers (buffer sent) */
+ int32_t l_tx_tail;
+
+ /** Number of free TD before wakeup callback is invoked */
+ uint32_t uc_wakeup_threshold;
+} gmac_device_t;
+
+/**
+ * \brief Write network control value.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_ncr Network control value.
+ */
+static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)
+{
+ p_gmac->GMAC_NCR = ul_ncr;
+}
+
+/**
+ * \brief Get network control value.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+
+static inline uint32_t gmac_get_network_control(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_NCR;
+}
+
+/**
+ * \brief Enable/Disable GMAC receive.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable GMAC receiver, else to enable it.
+ */
+static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;
+ }
+}
+
+/**
+ * \brief Enable/Disable GMAC transmit.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable GMAC transmit, else to enable it.
+ */
+static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;
+ }
+}
+
+/**
+ * \brief Enable/Disable GMAC management.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable GMAC management, else to enable it.
+ */
+static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_MPE;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;
+ }
+}
+
+/**
+ * \brief Clear all statistics registers.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_clear_statistics(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;
+}
+
+/**
+ * \brief Increase all statistics registers.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_increase_statistics(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;
+}
+
+/**
+ * \brief Enable/Disable statistics registers writing.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the statistics registers writing, else to enable it.
+ */
+static inline void gmac_enable_statistics_write(Gmac* p_gmac,
+ uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;
+ }
+}
+
+/**
+ * \brief In half-duplex mode, forces collisions on all received frames.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the back pressure, else to enable it.
+ */
+static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_BP;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;
+ }
+}
+
+/**
+ * \brief Start transmission.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_start_transmission(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;
+}
+
+/**
+ * \brief Halt transmission.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_halt_transmission(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_THALT;
+}
+
+/**
+ * \brief Transmit pause frame.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_tx_pause_frame(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;
+}
+
+/**
+ * \brief Transmit zero quantum pause frame.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;
+}
+
+/**
+ * \brief Read snapshot.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_read_snapshot(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_RDS;
+}
+
+/**
+ * \brief Store receivetime stamp to memory.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to normal operation, else to enable the store.
+ */
+static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;
+ }
+}
+
+/**
+ * \brief Enable PFC priority-based pause reception.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 1 to set the reception, 0 to disable.
+ */
+static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;
+ }
+}
+
+/**
+ * \brief Transmit PFC priority-based pause reception.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;
+}
+
+/**
+ * \brief Flush next packet.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_flush_next_packet(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_FNP;
+}
+
+/**
+ * \brief Set up network configuration register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_cfg Network configuration value.
+ */
+static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)
+{
+ p_gmac->GMAC_NCFGR = ul_cfg;
+}
+
+/**
+ * \brief Get network configuration.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Network configuration.
+ */
+static inline uint32_t gmac_get_configure(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_NCFGR;
+}
+
+
+/* Get and set DMA Configuration Register */
+static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)
+{
+ p_gmac->GMAC_DCFGR = ul_cfg;
+}
+
+static inline uint32_t gmac_get_dma(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_DCFGR;
+}
+
+/**
+ * \brief Set speed.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.
+ */
+static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)
+{
+ if (uc_speed) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;
+ }
+}
+
+/**
+ * \brief Enable/Disable Full-Duplex mode.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the Full-Duplex mode, else to enable it.
+ */
+static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;
+ }
+}
+
+/**
+ * \brief Enable/Disable Copy(Receive) All Valid Frames.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable copying all valid frames, else to enable it.
+ */
+static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;
+ }
+}
+
+/**
+ * \brief Enable/Disable jumbo frames (up to 10240 bytes).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the jumbo frames, else to enable it.
+ */
+static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;
+ }
+}
+
+/**
+ * \brief Disable/Enable broadcast receiving.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 1 to disable the broadcast, else to enable it.
+ */
+static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;
+ }
+}
+
+/**
+ * \brief Enable/Disable multicast hash.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the multicast hash, else to enable it.
+ */
+static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;
+ }
+}
+
+/**
+ * \brief Enable/Disable big frames (over 1518, up to 1536).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable big frames else to enable it.
+ */
+static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;
+ }
+}
+
+/**
+ * \brief Set MDC clock divider.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_mck GMAC MCK.
+ *
+ * \return GMAC_OK if successfully.
+ */
+static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)
+{
+ uint32_t ul_clk;
+
+ if (ul_mck > GMAC_MCK_SPEED_240MHZ) {
+ return GMAC_INVALID;
+ } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_96;
+ } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_64;
+ } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_48;
+ } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_32;
+ } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_16;
+ } else {
+ ul_clk = GMAC_NCFGR_CLK_MCK_8;
+ }
+ ;
+ p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;
+ return GMAC_OK;
+}
+
+/**
+ * \brief Enable/Disable retry test.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the GMAC receiver, else to enable it.
+ */
+static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;
+ }
+}
+
+/**
+ * \brief Enable/Disable pause (when a valid pause frame is received).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable pause frame, else to enable it.
+ */
+static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;
+ }
+}
+
+/**
+ * \brief Set receive buffer offset to 0 ~ 3.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)
+{
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);
+}
+
+/**
+ * \brief Enable/Disable receive length field checking.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable receive length field checking, else to enable it.
+ */
+static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;
+ }
+}
+
+/**
+ * \brief Enable/Disable discarding FCS field of received frames.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable discarding FCS field of received frames, else to enable it.
+ */
+static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;
+ }
+}
+
+
+/**
+ * \brief Enable/Disable frames to be received in half-duplex mode
+ * while transmitting.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the received in half-duplex mode, else to enable it.
+ */
+static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;
+ }
+}
+
+/**
+ * \brief Enable/Disable ignore RX FCS.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable ignore RX FCS, else to enable it.
+ */
+static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;
+ }
+}
+
+/**
+ * \brief Get Network Status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Network status.
+ */
+static inline uint32_t gmac_get_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_NSR;
+}
+
+/**
+ * \brief Get MDIO IN pin status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return MDIO IN pin status.
+ */
+static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)
+{
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);
+}
+
+/**
+ * \brief Check if PHY is idle.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return 1 if PHY is idle.
+ */
+static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)
+{
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);
+}
+
+/**
+ * \brief Return transmit status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Transmit status.
+ */
+static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_TSR;
+}
+
+/**
+ * \brief Clear transmit status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_status Transmit status.
+ */
+static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)
+{
+ p_gmac->GMAC_TSR = ul_status;
+}
+
+/**
+ * \brief Return receive status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_RSR;
+}
+
+/**
+ * \brief Clear receive status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_status Receive status.
+ */
+static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)
+{
+ p_gmac->GMAC_RSR = ul_status;
+}
+
+/**
+ * \brief Set Rx Queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_addr Rx queue address.
+ */
+static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)
+{
+ p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Get Rx Queue Address.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Rx queue address.
+ */
+static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_RBQB;
+}
+
+/**
+ * \brief Set Tx Queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_addr Tx queue address.
+ */
+static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)
+{
+ p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Get Tx Queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Rx queue address.
+ */
+static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_TBQB;
+}
+
+/**
+ * \brief Enable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be enabled.
+ */
+static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)
+{
+ p_gmac->GMAC_IER = ul_source;
+}
+
+/**
+ * \brief Disable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be disabled.
+ */
+static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)
+{
+ p_gmac->GMAC_IDR = ul_source;
+}
+
+/**
+ * \brief Return interrupt status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Interrupt status.
+ */
+static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_ISR;
+}
+
+/**
+ * \brief Return interrupt mask.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Interrupt mask.
+ */
+static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_IMR;
+}
+
+/**
+ * \brief Execute PHY maintenance command.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_phy_addr PHY address.
+ * \param uc_reg_addr Register address.
+ * \param uc_rw 1 to Read, 0 to write.
+ * \param us_data Data to be performed, write only.
+ */
+static inline void gmac_maintain_phy(Gmac* p_gmac,
+ uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,
+ uint16_t us_data)
+{
+ /* Wait until bus idle */
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Write maintain register */
+ p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)
+ | GMAC_MAN_CLTTO
+ | GMAC_MAN_PHYA(uc_phy_addr)
+ | GMAC_MAN_REGA(uc_reg_addr)
+ | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))
+ | GMAC_MAN_DATA(us_data);
+}
+
+/**
+ * \brief Get PHY maintenance data returned.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Get PHY data.
+ */
+static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)
+{
+ /* Wait until bus idle */
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Return data */
+ return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);
+}
+
+/**
+ * \brief Set Hash.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_hash_top Hash top.
+ * \param ul_hash_bottom Hash bottom.
+ */
+static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,
+ uint32_t ul_hash_bottom)
+{
+ p_gmac->GMAC_HRB = ul_hash_bottom;
+ p_gmac->GMAC_HRT = ul_hash_top;
+}
+
+/**
+ * \brief Set 64 bits Hash.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ull_hash 64 bits hash value.
+ */
+static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)
+{
+ p_gmac->GMAC_HRB = (uint32_t) ull_hash;
+ p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);
+}
+
+/**
+ * \brief Set MAC Address.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_index GMAC specific address register index.
+ * \param p_mac_addr GMAC address.
+ */
+static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,
+ uint8_t* p_mac_addr)
+{
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)
+ | (p_mac_addr[2] << 16)
+ | (p_mac_addr[1] << 8)
+ | (p_mac_addr[0]);
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)
+ | (p_mac_addr[4]);
+}
+
+/**
+ * \brief Set MAC Address via 2 dword.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_index GMAC specific address register index.
+ * \param ul_mac_top GMAC top address.
+ * \param ul_mac_bottom GMAC bottom address.
+ */
+static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,
+ uint32_t ul_mac_top, uint32_t ul_mac_bottom)
+{
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;
+}
+
+/**
+ * \brief Set MAC Address via int64.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_index GMAC specific address register index.
+ * \param ull_mac 64-bit GMAC address.
+ */
+static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,
+ uint64_t ull_mac)
+{
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);
+}
+
+/**
+ * \brief Select media independent interface mode.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param mode Media independent interface mode.
+ */
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)
+{
+ switch (mode) {
+ case GMAC_PHY_MII:
+ case GMAC_PHY_RMII:
+ p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;
+ break;
+
+ default:
+ p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;
+ break;
+ }
+}
+
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,
+ uint32_t* p_value);
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,
+ uint8_t uc_address, uint32_t ul_value);
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
+ gmac_options_t* p_opt);
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,
+ uint32_t ul_frame_size, uint32_t* p_rcv_size);
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
+ uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,
+ gmac_dev_tx_cb_t func_rx_cb);
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,
+ gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);
+void gmac_dev_reset(gmac_device_t* p_gmac_dev);
+void gmac_handler(gmac_device_t* p_gmac_dev);
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \page gmac_quickstart Quickstart guide for GMAC driver.
+ *
+ * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",
+ * with step-by-step instructions on how to configure and use the driver in a
+ * selection of use cases.
+ *
+ * The use cases contain several code fragments. The code fragments in the
+ * steps for setup can be copied into a custom initialization function, while
+ * the steps for usage can be copied into, e.g., the main application function.
+ *
+ * \section gmac_basic_use_case Basic use case
+ * In the basic use case, the GMAC driver are configured for:
+ * - PHY component KSZ8051MNL is used
+ * - GMAC uses MII mode
+ * - The number of receive buffer is 16
+ * - The number of transfer buffer is 8
+ * - MAC address is set to 00-04-25-1c-a0-02
+ * - IP address is set to 192.168.0.2
+ * - IP address is set to 192.168.0.2
+ * - Gateway is set to 192.168.0.1
+ * - Network mask is 255.255.255.0
+ * - PHY operation max retry count is 1000000
+ * - GMAC is configured to not support copy all frame and support broadcast
+ * - The data will be read from the ethernet
+ *
+ * \section gmac_basic_use_case_setup Setup steps
+ *
+ * \subsection gmac_basic_use_case_setup_prereq Prerequisites
+ * -# \ref sysclk_group "System Clock Management (sysclock)"
+ * -# \ref pmc_group "Power Management Controller (pmc)"
+ * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"
+ *
+ * \subsection gmac_basic_use_case_setup_code Example code
+ * Content of conf_eth.h
+ * \code
+ * #define GMAC_RX_BUFFERS 16
+ * #define GMAC_TX_BUFFERS 8
+ * #define MAC_PHY_RETRY_MAX 1000000
+ * #define ETHERNET_CONF_ETHADDR0 0x00
+ * #define ETHERNET_CONF_ETHADDR0 0x00
+ * #define ETHERNET_CONF_ETHADDR1 0x04
+ * #define ETHERNET_CONF_ETHADDR2 0x25
+ * #define ETHERNET_CONF_ETHADDR3 0x1C
+ * #define ETHERNET_CONF_ETHADDR4 0xA0
+ * #define ETHERNET_CONF_ETHADDR5 0x02
+ * #define ETHERNET_CONF_IPADDR0 192
+ * #define ETHERNET_CONF_IPADDR1 168
+ * #define ETHERNET_CONF_IPADDR2 0
+ * #define ETHERNET_CONF_IPADDR3 2
+ * #define ETHERNET_CONF_GATEWAY_ADDR0 192
+ * #define ETHERNET_CONF_GATEWAY_ADDR1 168
+ * #define ETHERNET_CONF_GATEWAY_ADDR2 0
+ * #define ETHERNET_CONF_GATEWAY_ADDR3 1
+ * #define ETHERNET_CONF_NET_MASK0 255
+ * #define ETHERNET_CONF_NET_MASK1 255
+ * #define ETHERNET_CONF_NET_MASK2 255
+ * #define ETHERNET_CONF_NET_MASK3 0
+ * #define ETH_PHY_MODE ETH_PHY_MODE
+ * \endcode
+ *
+ * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined
+ * to trace the actual size of the data received.
+ * \code
+ * static gmac_device_t gs_gmac_dev;
+ * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];
+ *
+ * uint32_t ul_frm_size;
+ * \endcode
+ *
+ * Add to application C-file:
+ * \code
+ * void gmac_init(void)
+ * {
+ * sysclk_init();
+ *
+ * board_init();
+ *
+ * pmc_enable_periph_clk(ID_GMAC);
+ *
+ * gmac_option.uc_copy_all_frame = 0;
+ * gmac_option.uc_no_boardcast = 0;
+ * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
+ * gs_gmac_dev.p_hw = GMAC;
+ *
+ * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
+ *
+ * NVIC_EnableIRQ(GMAC_IRQn);
+ *
+ * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
+ *
+ * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
+ *
+ * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
+ * \endcode
+ *
+ * \subsection gmac_basic_use_case_setup_flow Workflow
+ * - Ensure that conf_eth.h is present and contains the
+ * following configuration symbol. This configuration file is used
+ * by the driver and should not be included by the application.
+ * -# Define the receiving buffer size used in the internal GMAC driver.
+ * The buffer size used for RX is GMAC_RX_BUFFERS * 128.
+ * If it was supposed receiving a large number of frame, the
+ * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept
+ * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least
+ * (2048/128)=16, and as there are additional frames coming, a preferred
+ * number is 24 depending on a normal Ethernet throughput.
+ * - \code
+ * #define GMAC_RX_BUFFERS 16
+ * \endcode
+ * -# Define the transmitting buffer size used in the internal GMAC driver.
+ * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.
+ * - \code
+ * #define GMAC_TX_BUFFERS 8
+ * \endcode
+ * -# Define maximum retry time for a PHY read/write operation.
+ * - \code
+ * #define MAC_PHY_RETRY_MAX 1000000
+ * \endcode
+ * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved
+ * for ATMEL, application should always change this address to its' own.
+ * - \code
+ * #define ETHERNET_CONF_ETHADDR0 0x00
+ * #define ETHERNET_CONF_ETHADDR1 0x04
+ * #define ETHERNET_CONF_ETHADDR2 0x25
+ * #define ETHERNET_CONF_ETHADDR3 0x1C
+ * #define ETHERNET_CONF_ETHADDR4 0xA0
+ * #define ETHERNET_CONF_ETHADDR5 0x02
+ * \endcode
+ * -# Define the IP address configration used in the application. When DHCP
+ * is enabled, this configuration is not effected.
+ * - \code
+ * #define ETHERNET_CONF_IPADDR0 192
+ * #define ETHERNET_CONF_IPADDR1 168
+ * #define ETHERNET_CONF_IPADDR2 0
+ * #define ETHERNET_CONF_IPADDR3 2
+ * #define ETHERNET_CONF_GATEWAY_ADDR0 192
+ * #define ETHERNET_CONF_GATEWAY_ADDR1 168
+ * #define ETHERNET_CONF_GATEWAY_ADDR2 0
+ * #define ETHERNET_CONF_GATEWAY_ADDR3 1
+ * #define ETHERNET_CONF_NET_MASK0 255
+ * #define ETHERNET_CONF_NET_MASK1 255
+ * #define ETHERNET_CONF_NET_MASK2 255
+ * #define ETHERNET_CONF_NET_MASK3 0
+ * \endcode
+ * -# Configure the PHY maintainance interface.
+ * - \code
+ * #define ETH_PHY_MODE GMAC_PHY_MII
+ * \endcode
+ * -# Enable the system clock:
+ * - \code sysclk_init(); \endcode
+ * -# Enable PIO configurations for GMAC:
+ * - \code board_init(); \endcode
+ * -# Enable PMC clock for GMAC:
+ * - \code pmc_enable_periph_clk(ID_GMAC); \endcode
+ * -# Set the GMAC options; it's set to copy all frame and support broadcast:
+ * - \code
+ * gmac_option.uc_copy_all_frame = 0;
+ * gmac_option.uc_no_boardcast = 0;
+ * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
+ * gs_gmac_dev.p_hw = GMAC;
+ * \endcode
+ * -# Initialize GMAC device with the filled option:
+ * - \code
+ * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
+ * \endcode
+ * -# Enable the interrupt service for GMAC:
+ * - \code
+ * NVIC_EnableIRQ(GMAC_IRQn);
+ * \endcode
+ * -# Initialize the PHY component:
+ * - \code
+ * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
+ * \endcode
+ * -# The link will be established based on auto negotiation.
+ * - \code
+ * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
+ * \endcode
+ * -# Establish the ethernet link; the network can be worked from now on:
+ * - \code
+ * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
+ * \endcode
+ *
+ * \section gmac_basic_use_case_usage Usage steps
+ * \subsection gmac_basic_use_case_usage_code Example code
+ * Add to, e.g., main loop in application C-file:
+ * \code
+ * gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));
+ * \endcode
+ *
+ * \subsection gmac_basic_use_case_usage_flow Workflow
+ * -# Start reading the data from the ethernet:
+ * - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode
+ */
+
+# define GMAC_STATS 0
+
+#if( GMAC_STATS != 0 )
+
+ /* Here below some code to study the types and
+ frequencies of GMAC interrupts. */
+ #define GMAC_IDX_RXUBR 0
+ #define GMAC_IDX_TUR 1
+ #define GMAC_IDX_RLEX 2
+ #define GMAC_IDX_TFC 3
+ #define GMAC_IDX_RCOMP 4
+ #define GMAC_IDX_TCOMP 5
+ #define GMAC_IDX_ROVR 6
+ #define GMAC_IDX_HRESP 7
+ #define GMAC_IDX_PFNZ 8
+ #define GMAC_IDX_PTZ 9
+
+ struct SGmacStats {
+ unsigned recvCount;
+ unsigned rovrCount;
+ unsigned bnaCount;
+ unsigned sendCount;
+ unsigned sovrCount;
+ unsigned incompCount;
+ unsigned truncCount;
+
+ unsigned intStatus[10];
+ };
+ extern struct SGmacStats gmacStats;
+
+ struct SIntPair {
+ const char *name;
+ unsigned mask;
+ int index;
+ };
+
+ #define MK_PAIR( NAME ) #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME
+ static const struct SIntPair intPairs[] = {
+ { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */
+ { MK_PAIR( TUR ) }, /* Enable transmit underrun interrupt. */
+ { MK_PAIR( RLEX ) }, /* Enable retry limit exceeded interrupt. */
+ { MK_PAIR( TFC ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */
+ { MK_PAIR( RCOMP ) }, /* Receive complete */
+ { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */
+ { MK_PAIR( ROVR ) }, /* Enable receive overrun interrupt. */
+ { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */
+ { MK_PAIR( PFNZ ) }, /* Enable pause frame received interrupt. */
+ { MK_PAIR( PTZ ) } /* Enable pause time zero interrupt. */
+ };
+
+ void gmac_show_irq_counts ();
+
+#endif
+
+#endif /* GMAC_H_INCLUDED */