diff --git a/arch/arm/include/samd5e5/irq.h b/arch/arm/include/samd5e5/irq.h index 7807757dbd..bd0b5aca97 100644 --- a/arch/arm/include/samd5e5/irq.h +++ b/arch/arm/include/samd5e5/irq.h @@ -76,7 +76,7 @@ #define SAM_IRQ_EXTINT (16) /* Vector number of the first external interrupt */ -#if defined(CONFIG_ARCH_CHIP_SAMD5X) || defined(ARCH_CHIP_SAME5X) +#if defined(CONFIG_ARCH_CHIP_SAMD5X) || defined(CONFIG_ARCH_CHIP_SAME5X) # include #else # error "Unsupported SAMD5/E5 family" diff --git a/arch/arm/src/samd5e5/Kconfig b/arch/arm/src/samd5e5/Kconfig index 146208373c..a0dba2123a 100644 --- a/arch/arm/src/samd5e5/Kconfig +++ b/arch/arm/src/samd5e5/Kconfig @@ -361,6 +361,13 @@ config SAMD5E5_DMAC default n select ARCH_DMA +config SAMD5E5_GMAC + bool "Ethernet" + default n + depends on SAMD5E5_HAVE_ETHERNET + select NETDEVICES + select ARCH_HAVE_PHY + config SAMD5E5_EVSYS bool "Event System" default n @@ -710,3 +717,111 @@ config SAMD5E5_USB_REGDEBUG CONFIG_DEBUG_USB_INFO. endmenu # USB options + + +if SAMD5E5_GMAC + +menu "GMAC device driver options" + +config SAMD5E5_GMAC_NRXBUFFERS + int "Number of RX buffers" + default 16 + ---help--- + GMAC buffer memory is segmented into 128 byte units (not + configurable). This setting provides the number of such 128 byte + units used for reception. This is also equal to the number of RX + descriptors that will be allocated The selected value must be an + even power of 2. + +config SAMD5E5_GMAC_NTXBUFFERS + int "Number of TX buffers" + default 8 + ---help--- + GMAC buffer memory is segmented into full Ethernet packets (size + NET_BUFSIZE bytes). This setting provides the number of such packets + that can be in flight. This is also equal to the number of TX + descriptors that will be allocated. + +config SAMD5E5_GMAC_PREALLOCATE + bool "Preallocate buffers" + default n + ---help--- + Buffer an descriptor many may either be allocated from the memory + pool or pre-allocated to lie in .bss. This options selected pre- + allocated buffer memory. + +config SAMD5E5_GMAC_NBC + bool "Disable Broadcast" + default n + ---help--- + Select to disable receipt of broadcast packets. + +config SAMD5E5_GMAC_PHYADDR + int "PHY address" + default 1 + ---help--- + The 5-bit address of the PHY on the board. Default: 1 + +config SAMD5E5_GMAC_PHYINIT + bool "Board-specific PHY Initialization" + default n + ---help--- + Some boards require specialized initialization of the PHY before it can be used. + This may include such things as configuring GPIOs, resetting the PHY, etc. If + SAMD5E5_GMAC_PHYINIT is defined in the configuration then the board specific logic must + provide sam_phyinitialize(); The SAMD5E5 GMAC driver will call this function + one time before it first uses the PHY. + +config SAMD5E5_GMAC_AUTONEG + bool "Use autonegotiation" + default y + ---help--- + Use PHY autonegotiation to determine speed and mode + +if !SAMD5E5_GMAC_AUTONEG + +config SAMD5E5_GMAC_ETHFD + bool "Full duplex" + default n + ---help--- + If SAMD5E5_GMAC_AUTONEG is not defined, then this may be defined to + select full duplex mode. Default: half-duplex + +choice + prompt "GMAC Speed" + default SAMD5E5_GMAC_ETH100MBPS + ---help--- + If autonegotiation is not used, then you must select the fixed speed + of the PHY + +config SAMD5E5_GMAC_ETH10MBPS + bool "10 Mbps" + ---help--- + If SAMD5E5_GMAC_AUTONEG is not defined, then this may be defined to select 10 MBps + speed. Default: 100 Mbps + +config SAMD5E5_GMAC_ETH100MBPS + bool "100 Mbps" + ---help--- + If SAMD5E5_GMAC_AUTONEG is not defined, then this may be defined to select 100 MBps + speed. Default: 100 Mbps + +endchoice # GMAC speed +endif # !SAMD5E5_GMAC_AUTONEG + +config SAMD5E5_GMAC_REGDEBUG + bool "Register-Level Debug" + default n + depends on DEBUG_NET_INFO + ---help--- + Enable very low-level register access debug. Depends on CONFIG_DEBUG_NET_INFO. + +config SAMD5E5_GMAC_USE_MII + bool "Use MII interface for Ethernet" + default n + ---help--- + If selected, use MII interface to Ethernet PHY. Otherwise, RMII will be used. + +endmenu # GMAC device driver options +endif # SAMD5E5_GMAC + diff --git a/arch/arm/src/samd5e5/Make.defs b/arch/arm/src/samd5e5/Make.defs index 82722da2ff..71e5de2ca8 100644 --- a/arch/arm/src/samd5e5/Make.defs +++ b/arch/arm/src/samd5e5/Make.defs @@ -154,6 +154,7 @@ endif ifeq ($(CONFIG_SAMD5E5_GMAC),y) CHIP_CSRCS += sam_gmac.c +CHIP_CSRCS += sam_ethernet.c endif ifeq ($(CONFIG_SAMD5E5_USB),y) diff --git a/arch/arm/src/samd5e5/hardware/sam_gmac.h b/arch/arm/src/samd5e5/hardware/sam_gmac.h new file mode 100644 index 0000000000..79815edda3 --- /dev/null +++ b/arch/arm/src/samd5e5/hardware/sam_gmac.h @@ -0,0 +1,1015 @@ +/************************************************************************************ + * arch/arm/src/same5d5/hardware/sam_gmac.h + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_SAMA5_HARDWARE_SAM_GMAC_H +#define __ARCH_ARM_SRC_SAMA5_HARDWARE_SAM_GMAC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include "hardware/sam_memorymap.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* GMAC Register Offsets ************************************************************/ + +#define SAM_GMAC_NCR_OFFSET 0x0000 /* Network Control Register */ +#define SAM_GMAC_NCFGR_OFFSET 0x0004 /* Network Configuration Register */ +#define SAM_GMAC_NSR_OFFSET 0x0008 /* Network Status Register */ +#define SAM_GMAC_UR_OFFSET 0x000c /* User Register */ +#define SAM_GMAC_DCFGR_OFFSET 0x0010 /* DMA Configuration Register */ +#define SAM_GMAC_TSR_OFFSET 0x0014 /* Transmit Status Register */ +#define SAM_GMAC_RBQB_OFFSET 0x0018 /* Receive Buffer Queue Base Address */ +#define SAM_GMAC_TBQB_OFFSET 0x001c /* Transmit Buffer Queue Base Address */ +#define SAM_GMAC_RSR_OFFSET 0x0020 /* Receive Status Register */ +#define SAM_GMAC_ISR_OFFSET 0x0024 /* Interrupt Status Register */ +#define SAM_GMAC_IER_OFFSET 0x0028 /* Interrupt Enable Register */ +#define SAM_GMAC_IDR_OFFSET 0x002c /* Interrupt Disable Register */ +#define SAM_GMAC_IMR_OFFSET 0x0030 /* Interrupt Mask Register */ +#define SAM_GMAC_MAN_OFFSET 0x0034 /* PHY Maintenance Register */ +#define SAM_GMAC_RPQ_OFFSET 0x0038 /* Received Pause Quantum Register */ +#define SAM_GMAC_TPQ_OFFSET 0x003c /* Transmit Pause Quantum Register */ +#define SAM_GMAC_TPSF_OFFSET 0x0040 /* TX Partial Store and Forward Register */ +#define SAM_GMAC_RPSF_OFFSET 0x0044 /* RX Partial Store and Forward Register */ + /* 0x0048-0x007c Reserved */ +#define SAM_GMAC_HRB_OFFSET 0x0080 /* Hash Register Bottom [31:0] */ +#define SAM_GMAC_HRT_OFFSET 0x0084 /* Hash Register Top [63:32] */ +#define SAM_GMAC_SAB_OFFSET(n) (0x0088 + (((n)-1) << 3)) /* n=1..4 */ +#define SAM_GMAC_SAT_OFFSET(n) (0x008c + (((n)-1) << 3)) /* n=1..4 */ +#define SAM_GMAC_SAB1_OFFSET 0x0088 /* Specific Address 1 Bottom [31:0] Register */ +#define SAM_GMAC_SAT1_OFFSET 0x008c /* Specific Address 1 Top [47:32] Register */ +#define SAM_GMAC_SAB2_OFFSET 0x0090 /* Specific Address 2 Bottom [31:0] Register */ +#define SAM_GMAC_SAT2_OFFSET 0x0094 /* Specific Address 2 Top [47:32] Register */ +#define SAM_GMAC_SAB3_OFFSET 0x0098 /* Specific Address 3 Bottom [31:0] Register */ +#define SAM_GMAC_SAT3_OFFSET 0x009c /* Specific Address 3 Top [47:32] Register */ +#define SAM_GMAC_SAB4_OFFSET 0x00a0 /* Specific Address 4 Bottom [31:0] Register */ +#define SAM_GMAC_SAT4_OFFSET 0x00a4 /* Specific Address 4 Top [47:32] Register */ +#define SAM_GMAC_TIDM_OFFSET(n) (0x00a8 + (((n)-1) << 2)) /* n=1..4 */ +#define SAM_GMAC_TIDM1_OFFSET 0x00a8 /* Type ID Match 1 Register */ +#define SAM_GMAC_TIDM2_OFFSET 0x00ac /* Type ID Match 2 Register */ +#define SAM_GMAC_TIDM3_OFFSET 0x00b0 /* Type ID Match 3 Register */ +#define SAM_GMAC_TIDM4_OFFSET 0x00b4 /* Type ID Match 4 Register */ +#define SAM_GMAC_WOL_OFFSET 0x00b8 /* Wake on LAN Register */ +#define SAM_GMAC_IPGS_OFFSET 0x00bc /* IPG Stretch Register */ +#define SAM_GMAC_SVLAN_OFFSET 0x00c0 /* Stacked VLAN Register */ +#define SAM_GMAC_TPFCP_OFFSET 0x00c4 /* Transmit PFC Pause Register */ +#define SAM_GMAC_SAMB1_OFFSET 0x00c8 /* Specific Address 1 Mask Bottom [31:0] Register */ +#define SAM_GMAC_SAMT1_OFFSET 0x00cc /* Specific Address 1 Mask Top [47:32] Register */ + /* 0x00fc Reserved */ +#define SAM_GMAC_OTLO_OFFSET 0x0100 /* Octets Transmitted [31:0] Register */ +#define SAM_GMAC_OTHI_OFFSET 0x0104 /* Octets Transmitted [47:32] Register */ +#define SAM_GMAC_FT_OFFSET 0x0108 /* Frames Transmitted Register */ +#define SAM_GMAC_BCFT_OFFSET 0x010c /* Broadcast Frames Transmitted Register */ +#define SAM_GMAC_MFT_OFFSET 0x0110 /* Multicast Frames Transmitted Register */ +#define SAM_GMAC_PFT_OFFSET 0x0114 /* Pause Frames Transmitted Register */ +#define SAM_GMAC_BFT64_OFFSET 0x0118 /* 64 Byte Frames Transmitted Register */ +#define SAM_GMAC_TBFT127_OFFSET 0x011c /* 65 to 127 Byte Frames Transmitted Register */ +#define SAM_GMAC_TBFT255_OFFSET 0x0120 /* 128 to 255 Byte Frames Transmitted Register */ +#define SAM_GMAC_TBFT511_OFFSET 0x0124 /* 256 to 511 Byte Frames Transmitted Register */ +#define SAM_GMAC_TBFT1023_OFFSET 0x0128 /* 512 to 1023 Byte Frames Transmitted Register */ +#define SAM_GMAC_TBFT1518_OFFSET 0x012c /* 1024 to 1518 Byte Frames Transmitted Register */ +#define SAM_GMAC_GTBFT1518_OFFSET 0x0130 /* Greater Than 1518 Byte Frames Transmitted Register */ +#define SAM_GMAC_TUR_OFFSET 0x0134 /* Transmit Under Runs Register */ +#define SAM_GMAC_SCF_OFFSET 0x0138 /* Single Collision Frames Register */ +#define SAM_GMAC_MCF_OFFSET 0x013c /* Multiple Collision Frames Register */ +#define SAM_GMAC_EC_OFFSET 0x0140 /* Excessive Collisions Register */ +#define SAM_GMAC_LC_OFFSET 0x0144 /* Late Collisions Register */ +#define SAM_GMAC_DTF_OFFSET 0x0148 /* Deferred Transmission Frames Register */ +#define SAM_GMAC_CSE_OFFSET 0x014c /* Carrier Sense Errors Register */ +#define SAM_GMAC_ORLO_OFFSET 0x0150 /* Octets Received [31:0] Received */ +#define SAM_GMAC_ORHI_OFFSET 0x0154 /* Octets Received [47:32] Received */ +#define SAM_GMAC_FR_OFFSET 0x0158 /* Frames Received Register */ +#define SAM_GMAC_BCFR_OFFSET 0x015c /* Broadcast Frames Received Register */ +#define SAM_GMAC_MFR_OFFSET 0x0160 /* Multicast Frames Received Register */ +#define SAM_GMAC_PFR_OFFSET 0x0164 /* Pause Frames Received Register */ +#define SAM_GMAC_BFR64_OFFSET 0x0168 /* 64 Byte Frames Received Register */ +#define SAM_GMAC_TBFR127_OFFSET 0x016c /* 65 to 127 Byte Frames Received Register */ +#define SAM_GMAC_TBFR255_OFFSET 0x0170 /* 128 to 255 Byte Frames Received Register */ +#define SAM_GMAC_TBFR511_OFFSET 0x0174 /* 256 to 511Byte Frames Received Register */ +#define SAM_GMAC_TBFR1023_OFFSET 0x0178 /* 512 to 1023 Byte Frames Received Register */ +#define SAM_GMAC_TBFR1518_OFFSET 0x017c /* 1024 to 1518 Byte Frames Received Register */ +#define SAM_GMAC_TMXBFR_OFFSET 0x0180 /* 1519 to Maximum Byte Frames Received Register */ +#define SAM_GMAC_UFR_OFFSET 0x0184 /* Undersize Frames Received Register */ +#define SAM_GMAC_OFR_OFFSET 0x0188 /* Oversize Frames Received Register */ +#define SAM_GMAC_JR_OFFSET 0x018c /* Jabbers Received Register */ +#define SAM_GMAC_FCSE_OFFSET 0x0190 /* Frame Check Sequence Errors Register */ +#define SAM_GMAC_LFFE_OFFSET 0x0194 /* Length Field Frame Errors Register */ +#define SAM_GMAC_RSE_OFFSET 0x0198 /* Receive Symbol Errors Register */ +#define SAM_GMAC_AE_OFFSET 0x019c /* Alignment Errors Register */ +#define SAM_GMAC_RRE_OFFSET 0x01a0 /* Receive Resource Errors Register */ +#define SAM_GMAC_ROE_OFFSET 0x01a4 /* Receive Overrun Register */ +#define SAM_GMAC_IHCE_OFFSET 0x01a8 /* IP Header Checksum Errors Register */ +#define SAM_GMAC_TCE_OFFSET 0x01ac /* TCP Checksum Errors Register */ +#define SAM_GMAC_UCE_OFFSET 0x01b0 /* UDP Checksum Errors Register */ +#define SAM_GMAC_TSSS_OFFSET 0x01c8 /* 1588 Timer Sync Strobe Seconds Register */ +#define SAM_GMAC_TSSN_OFFSET 0x01cc /* 1588 Timer Sync Strobe Nanoseconds Register */ +#define SAM_GMAC_TS_OFFSET 0x01d0 /* 1588 Timer Seconds Register */ +#define SAM_GMAC_TN_OFFSET 0x01d4 /* 1588 Timer Nanoseconds Register */ +#define SAM_GMAC_TA_OFFSET 0x01d8 /* 1588 Timer Adjust Register */ +#define SAM_GMAC_TI_OFFSET 0x01dc /* 1588 Timer Increment Register */ +#define SAM_GMAC_EFTS_OFFSET 0x01e0 /* PTP Event Frame Transmitted Seconds */ +#define SAM_GMAC_EFTN_OFFSET 0x01e4 /* PTP Event Frame Transmitted Nanoseconds */ +#define SAM_GMAC_EFRS_OFFSET 0x01e8 /* PTP Event Frame Received Seconds */ +#define SAM_GMAC_EFRN_OFFSET 0x01ec /* PTP Event Frame Received Nanoseconds */ +#define SAM_GMAC_PEFTS_OFFSET 0x01f0 /* PTP Peer Event Frame Transmitted Seconds */ +#define SAM_GMAC_PEFTN_OFFSET 0x01f4 /* PTP Peer Event Frame Transmitted Nanoseconds */ +#define SAM_GMAC_PEFRS_OFFSET 0x01f8 /* PTP Peer Event Frame Received Seconds */ +#define SAM_GMAC_PEFRN_OFFSET 0x01fc /* PTP Peer Event Frame Received Nanoseconds */ + /* 0x0200-0x023c Reserved */ + /* 0x0280-0x0298 Reserved */ +#define SAM_GMAC_ISRPQ_OFFSET(n) (0x400 + ((n) << 2)) /* n=0..6 */ +#define SAM_GMAC_ISRPQ0_OFFSET 0x400 /* Interrupt Status Register Priority Queue 0 */ +#define SAM_GMAC_ISRPQ1_OFFSET 0x404 /* Interrupt Status Register Priority Queue 1 */ +#define SAM_GMAC_ISRPQ2_OFFSET 0x408 /* Interrupt Status Register Priority Queue 2 */ +#define SAM_GMAC_ISRPQ3_OFFSET 0x40c /* Interrupt Status Register Priority Queue 3 */ +#define SAM_GMAC_ISRPQ4_OFFSET 0x410 /* Interrupt Status Register Priority Queue 4 */ +#define SAM_GMAC_ISRPQ5_OFFSET 0x414 /* Interrupt Status Register Priority Queue 5 */ +#define SAM_GMAC_ISRPQ6_OFFSET 0x418 /* Interrupt Status Register Priority Queue 6 */ +#define SAM_GMAC_TBQBAPQ_OFFSET(n) (0x440 + ((n) << 2)) /* n=0..6 */ +#define SAM_GMAC_TBQBAPQ0_OFFSET 0x440 /* Transmit Buffer Queue Base Address Priority Queue 0 */ +#define SAM_GMAC_TBQBAPQ1_OFFSET 0x444 /* Transmit Buffer Queue Base Address Priority Queue 1 */ +#define SAM_GMAC_TBQBAPQ2_OFFSET 0x448 /* Transmit Buffer Queue Base Address Priority Queue 2 */ +#define SAM_GMAC_TBQBAPQ3_OFFSET 0x44c /* Transmit Buffer Queue Base Address Priority Queue 3 */ +#define SAM_GMAC_TBQBAPQ4_OFFSET 0x450 /* Transmit Buffer Queue Base Address Priority Queue 4 */ +#define SAM_GMAC_TBQBAPQ5_OFFSET 0x454 /* Transmit Buffer Queue Base Address Priority Queue 5 */ +#define SAM_GMAC_TBQBAPQ6_OFFSET 0x458 /* Transmit Buffer Queue Base Address Priority Queue 6 */ +#define SAM_GMAC_RBQBAPQ_OFFSET(n) (0x480 + ((n) << 2)) /* n=0..6 */ +#define SAM_GMAC_RBQBAPQ0_OFFSET 0x480 /* Receive Buffer Queue Base Address Priority Queue 0 */ +#define SAM_GMAC_RBQBAPQ1_OFFSET 0x484 /* Receive Buffer Queue Base Address Priority Queue 1 */ +#define SAM_GMAC_RBQBAPQ2_OFFSET 0x488 /* Receive Buffer Queue Base Address Priority Queue 2 */ +#define SAM_GMAC_RBQBAPQ3_OFFSET 0x48c /* Receive Buffer Queue Base Address Priority Queue 3 */ +#define SAM_GMAC_RBQBAPQ4_OFFSET 0x490 /* Receive Buffer Queue Base Address Priority Queue 4 */ +#define SAM_GMAC_RBQBAPQ5_OFFSET 0x494 /* Receive Buffer Queue Base Address Priority Queue 5 */ +#define SAM_GMAC_RBQBAPQ6_OFFSET 0x498 /* Receive Buffer Queue Base Address Priority Queue 6 */ +#define SAM_GMAC_RBSRPQ_OFFSET(n) (0x4a0 + ((n) << 2)) /* n=0..6 */ +#define SAM_GMAC_RBSRPQ0_OFFSET 0x4a0 /* Receive Buffer Size Register Priority Queue 0 */ +#define SAM_GMAC_RBSRPQ1_OFFSET 0x4a4 /* Receive Buffer Size Register Priority Queue 1 */ +#define SAM_GMAC_RBSRPQ2_OFFSET 0x4a8 /* Receive Buffer Size Register Priority Queue 2 */ +#define SAM_GMAC_RBSRPQ3_OFFSET 0x4ac /* Receive Buffer Size Register Priority Queue 3 */ +#define SAM_GMAC_RBSRPQ4_OFFSET 0x4b0 /* Receive Buffer Size Register Priority Queue 4 */ +#define SAM_GMAC_RBSRPQ5_OFFSET 0x4b4 /* Receive Buffer Size Register Priority Queue 5 */ +#define SAM_GMAC_RBSRPQ6_OFFSET 0x4b8 /* Receive Buffer Size Register Priority Queue 6 */ +#define SAM_GMAC_ST1RPQ_OFFSET(n) (0x500 + ((n) << 2)) /* n=0..15 */ +#define SAM_GMAC_ST1RPQ0_OFFSET 0x500 /* Screening Type1 Register Priority Queue 0 */ +#define SAM_GMAC_ST1RPQ1_OFFSET 0x504 /* Screening Type1 Register Priority Queue 1 */ +#define SAM_GMAC_ST1RPQ2_OFFSET 0x508 /* Screening Type1 Register Priority Queue 2 */ +#define SAM_GMAC_ST1RPQ3_OFFSET 0x50c /* Screening Type1 Register Priority Queue 3 */ +#define SAM_GMAC_ST1RPQ4_OFFSET 0x510 /* Screening Type1 Register Priority Queue 4 */ +#define SAM_GMAC_ST1RPQ5_OFFSET 0x514 /* Screening Type1 Register Priority Queue 5 */ +#define SAM_GMAC_ST1RPQ6_OFFSET 0x518 /* Screening Type1 Register Priority Queue 6 */ +#define SAM_GMAC_ST1RPQ7_OFFSET 0x51c /* Screening Type1 Register Priority Queue 7 */ +#define SAM_GMAC_ST1RPQ8_OFFSET 0x520 /* Screening Type1 Register Priority Queue 8 */ +#define SAM_GMAC_ST1RPQ9_OFFSET 0x524 /* Screening Type1 Register Priority Queue 9 */ +#define SAM_GMAC_ST1RPQ10_OFFSET 0x528 /* Screening Type1 Register Priority Queue 10 */ +#define SAM_GMAC_ST1RPQ11_OFFSET 0x52c /* Screening Type1 Register Priority Queue 11 */ +#define SAM_GMAC_ST1RPQ12_OFFSET 0x530 /* Screening Type1 Register Priority Queue 12 */ +#define SAM_GMAC_ST1RPQ13_OFFSET 0x534 /* Screening Type1 Register Priority Queue 13 */ +#define SAM_GMAC_ST1RPQ14_OFFSET 0x538 /* Screening Type1 Register Priority Queue 14 */ +#define SAM_GMAC_ST1RPQ15_OFFSET 0x53c /* Screening Type1 Register Priority Queue 15 */ +#define SAM_GMAC_ST2RPQ_OFFSET(n) (0x540 + ((n) << 2)) /* n=0..15 */ +#define SAM_GMAC_ST2RPQ0_OFFSET 0x540 /* Screening Type2 Register Priority Queue 0 */ +#define SAM_GMAC_ST2RPQ1_OFFSET 0x544 /* Screening Type2 Register Priority Queue 1 */ +#define SAM_GMAC_ST2RPQ2_OFFSET 0x548 /* Screening Type2 Register Priority Queue 2 */ +#define SAM_GMAC_ST2RPQ3_OFFSET 0x54c /* Screening Type2 Register Priority Queue 3 */ +#define SAM_GMAC_ST2RPQ4_OFFSET 0x550 /* Screening Type2 Register Priority Queue 4 */ +#define SAM_GMAC_ST2RPQ5_OFFSET 0x554 /* Screening Type2 Register Priority Queue 5 */ +#define SAM_GMAC_ST2RPQ6_OFFSET 0x558 /* Screening Type2 Register Priority Queue 6 */ +#define SAM_GMAC_ST2RPQ7_OFFSET 0x55c /* Screening Type2 Register Priority Queue 7 */ +#define SAM_GMAC_ST2RPQ8_OFFSET 0x560 /* Screening Type2 Register Priority Queue 8 */ +#define SAM_GMAC_ST2RPQ9_OFFSET 0x564 /* Screening Type2 Register Priority Queue 9 */ +#define SAM_GMAC_ST2RPQ10_OFFSET 0x568 /* Screening Type2 Register Priority Queue 10 */ +#define SAM_GMAC_ST2RPQ11_OFFSET 0x56c /* Screening Type2 Register Priority Queue 11 */ +#define SAM_GMAC_ST2RPQ12_OFFSET 0x570 /* Screening Type2 Register Priority Queue 12 */ +#define SAM_GMAC_ST2RPQ13_OFFSET 0x574 /* Screening Type2 Register Priority Queue 13 */ +#define SAM_GMAC_ST2RPQ14_OFFSET 0x578 /* Screening Type2 Register Priority Queue 14 */ +#define SAM_GMAC_ST2RPQ15_OFFSET 0x57c /* Screening Type2 Register Priority Queue 15 */ +#define SAM_GMAC_IERPQ_OFFSET(n) (0x600 + ((n) << 2)) /* n=0..6 */ +#define SAM_GMAC_IERPQ0_OFFSET 0x600 /* Interrupt Enable Register Priority Queue 0 */ +#define SAM_GMAC_IERPQ1_OFFSET 0x604 /* Interrupt Enable Register Priority Queue 1 */ +#define SAM_GMAC_IERPQ2_OFFSET 0x608 /* Interrupt Enable Register Priority Queue 2 */ +#define SAM_GMAC_IERPQ3_OFFSET 0x60c /* Interrupt Enable Register Priority Queue 3 */ +#define SAM_GMAC_IERPQ4_OFFSET 0x610 /* Interrupt Enable Register Priority Queue 4 */ +#define SAM_GMAC_IERPQ5_OFFSET 0x614 /* Interrupt Enable Register Priority Queue 5 */ +#define SAM_GMAC_IERPQ6_OFFSET 0x618 /* Interrupt Enable Register Priority Queue 6 */ +#define SAM_GMAC_IDRPQ_OFFSET(n) (0x620 + ((n) << 2)) /* n=0..6 */ +#define SAM_GMAC_IDRPQ0_OFFSET 0x620 /* Interrupt Disable Register Priority Queue 0 */ +#define SAM_GMAC_IDRPQ1_OFFSET 0x624 /* Interrupt Disable Register Priority Queue 1 */ +#define SAM_GMAC_IDRPQ2_OFFSET 0x628 /* Interrupt Disable Register Priority Queue 2 */ +#define SAM_GMAC_IDRPQ3_OFFSET 0x62c /* Interrupt Disable Register Priority Queue 3 */ +#define SAM_GMAC_IDRPQ4_OFFSET 0x630 /* Interrupt Disable Register Priority Queue 4 */ +#define SAM_GMAC_IDRPQ5_OFFSET 0x630 /* Interrupt Disable Register Priority Queue 5 */ +#define SAM_GMAC_IDRPQ6_OFFSET 0x638 /* Interrupt Disable Register Priority Queue 6 */ +#define SAM_GMAC_IMRPQ_OFFSET(n) (0x640 + ((n) << 2)) /* n=0..6 */ +#define SAM_GMAC_IMRPQ0_OFFSET 0x640 /* Interrupt Mask Register Priority Queue 0 */ +#define SAM_GMAC_IMRPQ1_OFFSET 0x644 /* Interrupt Mask Register Priority Queue 1 */ +#define SAM_GMAC_IMRPQ2_OFFSET 0x648 /* Interrupt Mask Register Priority Queue 2 */ +#define SAM_GMAC_IMRPQ3_OFFSET 0x64c /* Interrupt Mask Register Priority Queue 3 */ +#define SAM_GMAC_IMRPQ4_OFFSET 0x650 /* Interrupt Mask Register Priority Queue 4 */ +#define SAM_GMAC_IMRPQ5_OFFSET 0x654 /* Interrupt Mask Register Priority Queue 5 */ +#define SAM_GMAC_IMRPQ6_OFFSET 0x658 /* Interrupt Mask Register Priority Queue 6 */ + +/* GMAC Register Addresses *********************************************************/ + +#define SAM_GMAC_NCR (SAM_GMAC_BASE+SAM_GMAC_NCR_OFFSET) +#define SAM_GMAC_NCFGR (SAM_GMAC_BASE+SAM_GMAC_NCFGR_OFFSET) +#define SAM_GMAC_NSR (SAM_GMAC_BASE+SAM_GMAC_NSR_OFFSET) +#define SAM_GMAC_UR (SAM_GMAC_BASE+SAM_GMAC_UR_OFFSET) +#define SAM_GMAC_DCFGR (SAM_GMAC_BASE+SAM_GMAC_DCFGR_OFFSET) +#define SAM_GMAC_TSR (SAM_GMAC_BASE+SAM_GMAC_TSR_OFFSET) +#define SAM_GMAC_RBQB (SAM_GMAC_BASE+SAM_GMAC_RBQB_OFFSET) +#define SAM_GMAC_TBQB (SAM_GMAC_BASE+SAM_GMAC_TBQB_OFFSET) +#define SAM_GMAC_RSR (SAM_GMAC_BASE+SAM_GMAC_RSR_OFFSET) +#define SAM_GMAC_ISR (SAM_GMAC_BASE+SAM_GMAC_ISR_OFFSET) +#define SAM_GMAC_IER (SAM_GMAC_BASE+SAM_GMAC_IER_OFFSET) +#define SAM_GMAC_IDR (SAM_GMAC_BASE+SAM_GMAC_IDR_OFFSET) +#define SAM_GMAC_IMR (SAM_GMAC_BASE+SAM_GMAC_IMR_OFFSET) +#define SAM_GMAC_MAN (SAM_GMAC_BASE+SAM_GMAC_MAN_OFFSET) +#define SAM_GMAC_RPQ (SAM_GMAC_BASE+SAM_GMAC_RPQ_OFFSET) +#define SAM_GMAC_TPQ (SAM_GMAC_BASE+SAM_GMAC_TPQ_OFFSET) +#define SAM_GMAC_TPSF (SAM_GMAC_BASE+SAM_GMAC_TPSF_OFFSET) +#define SAM_GMAC_RPSF (SAM_GMAC_BASE+SAM_GMAC_RPSF_OFFSET) +#define SAM_GMAC_HRB (SAM_GMAC_BASE+SAM_GMAC_HRB_OFFSET) +#define SAM_GMAC_HRT (SAM_GMAC_BASE+SAM_GMAC_HRT_OFFSET) +#define SAM_GMAC_SAB(n) (SAM_GMAC_BASE+SAM_GMAC_SAB_OFFSET(n)) +#define SAM_GMAC_SAT(n) (SAM_GMAC_BASE+SAM_GMAC_SAT_OFFSET(n)) +#define SAM_GMAC_SAB1 (SAM_GMAC_BASE+SAM_GMAC_SAB1_OFFSET) +#define SAM_GMAC_SAT1 (SAM_GMAC_BASE+SAM_GMAC_SAT1_OFFSET) +#define SAM_GMAC_SAB2 (SAM_GMAC_BASE+SAM_GMAC_SAB2_OFFSET) +#define SAM_GMAC_SAT2 (SAM_GMAC_BASE+SAM_GMAC_SAT2_OFFSET) +#define SAM_GMAC_SAB3 (SAM_GMAC_BASE+SAM_GMAC_SAB3_OFFSET) +#define SAM_GMAC_SAT3 (SAM_GMAC_BASE+SAM_GMAC_SAT3_OFFSET) +#define SAM_GMAC_SAB4 (SAM_GMAC_BASE+SAM_GMAC_SAB4_OFFSET) +#define SAM_GMAC_SAT4 (SAM_GMAC_BASE+SAM_GMAC_SAT4_OFFSET) +#define SAM_GMAC_TIDM(n) (SAM_GMAC_BASE+SAM_GMAC_TIDM_OFFSET(n)) +#define SAM_GMAC_TIDM1 (SAM_GMAC_BASE+SAM_GMAC_TIDM1_OFFSET) +#define SAM_GMAC_TIDM2 (SAM_GMAC_BASE+SAM_GMAC_TIDM2_OFFSET) +#define SAM_GMAC_TIDM3 (SAM_GMAC_BASE+SAM_GMAC_TIDM3_OFFSET) +#define SAM_GMAC_TIDM4 (SAM_GMAC_BASE+SAM_GMAC_TIDM4_OFFSET) +#define SAM_GMAC_WOL (SAM_GMAC_BASE+SAM_GMAC_WOL_OFFSET) +#define SAM_GMAC_IPGS (SAM_GMAC_BASE+SAM_GMAC_IPGS_OFFSET) +#define SAM_GMAC_SVLAN (SAM_GMAC_BASE+SAM_GMAC_SVLAN_OFFSET) +#define SAM_GMAC_TPFCP (SAM_GMAC_BASE+SAM_GMAC_TPFCP_OFFSET) +#define SAM_GMAC_SAMB1 (SAM_GMAC_BASE+SAM_GMAC_SAMB1_OFFSET) +#define SAM_GMAC_SAMT1 (SAM_GMAC_BASE+SAM_GMAC_SAMT1_OFFSET) +#define SAM_GMAC_OTLO (SAM_GMAC_BASE+SAM_GMAC_OTLO_OFFSET) +#define SAM_GMAC_OTHI (SAM_GMAC_BASE+SAM_GMAC_OTHI_OFFSET) +#define SAM_GMAC_FT (SAM_GMAC_BASE+SAM_GMAC_FT_OFFSET) +#define SAM_GMAC_BCFT (SAM_GMAC_BASE+SAM_GMAC_BCFT_OFFSET) +#define SAM_GMAC_MFT (SAM_GMAC_BASE+SAM_GMAC_MFT_OFFSET) +#define SAM_GMAC_PFT (SAM_GMAC_BASE+SAM_GMAC_PFT_OFFSET) +#define SAM_GMAC_BFT64 (SAM_GMAC_BASE+SAM_GMAC_BFT64_OFFSET) +#define SAM_GMAC_TBFT127 (SAM_GMAC_BASE+SAM_GMAC_TBFT127_OFFSET) +#define SAM_GMAC_TBFT255 (SAM_GMAC_BASE+SAM_GMAC_TBFT255_OFFSET) +#define SAM_GMAC_TBFT511 (SAM_GMAC_BASE+SAM_GMAC_TBFT511_OFFSET) +#define SAM_GMAC_TBFT1023 (SAM_GMAC_BASE+SAM_GMAC_TBFT1023_OFFSET) +#define SAM_GMAC_TBFT1518 (SAM_GMAC_BASE+SAM_GMAC_TBFT1518_OFFSET) +#define SAM_GMAC_GTBFT1518 (SAM_GMAC_BASE+SAM_GMAC_GTBFT1518_OFFSET) +#define SAM_GMAC_TUR (SAM_GMAC_BASE+SAM_GMAC_TUR_OFFSET) +#define SAM_GMAC_SCF (SAM_GMAC_BASE+SAM_GMAC_SCF_OFFSET) +#define SAM_GMAC_MCF (SAM_GMAC_BASE+SAM_GMAC_MCF_OFFSET) +#define SAM_GMAC_EC (SAM_GMAC_BASE+SAM_GMAC_EC_OFFSET) +#define SAM_GMAC_LC (SAM_GMAC_BASE+SAM_GMAC_LC_OFFSET) +#define SAM_GMAC_DTF (SAM_GMAC_BASE+SAM_GMAC_DTF_OFFSET) +#define SAM_GMAC_CSE (SAM_GMAC_BASE+SAM_GMAC_CSE_OFFSET) +#define SAM_GMAC_ORLO (SAM_GMAC_BASE+SAM_GMAC_ORLO_OFFSET) +#define SAM_GMAC_ORHI (SAM_GMAC_BASE+SAM_GMAC_ORHI_OFFSET) +#define SAM_GMAC_FR (SAM_GMAC_BASE+SAM_GMAC_FR_OFFSET) +#define SAM_GMAC_BCFR (SAM_GMAC_BASE+SAM_GMAC_BCFR_OFFSET) +#define SAM_GMAC_MFR (SAM_GMAC_BASE+SAM_GMAC_MFR_OFFSET) +#define SAM_GMAC_PFR (SAM_GMAC_BASE+SAM_GMAC_PFR_OFFSET) +#define SAM_GMAC_BFR64 (SAM_GMAC_BASE+SAM_GMAC_BFR64_OFFSET) +#define SAM_GMAC_TBFR127 (SAM_GMAC_BASE+SAM_GMAC_TBFR127_OFFSET) +#define SAM_GMAC_TBFR255 (SAM_GMAC_BASE+SAM_GMAC_TBFR255_OFFSET) +#define SAM_GMAC_TBFR511 (SAM_GMAC_BASE+SAM_GMAC_TBFR511_OFFSET) +#define SAM_GMAC_TBFR1023 (SAM_GMAC_BASE+SAM_GMAC_TBFR1023_OFFSET) +#define SAM_GMAC_TBFR1518 (SAM_GMAC_BASE+SAM_GMAC_TBFR1518_OFFSET) +#define SAM_GMAC_TMXBFR (SAM_GMAC_BASE+SAM_GMAC_TMXBFR_OFFSET) +#define SAM_GMAC_UFR (SAM_GMAC_BASE+SAM_GMAC_UFR_OFFSET) +#define SAM_GMAC_OFR (SAM_GMAC_BASE+SAM_GMAC_OFR_OFFSET) +#define SAM_GMAC_JR (SAM_GMAC_BASE+SAM_GMAC_JR_OFFSET) +#define SAM_GMAC_FCSE (SAM_GMAC_BASE+SAM_GMAC_FCSE_OFFSET) +#define SAM_GMAC_LFFE (SAM_GMAC_BASE+SAM_GMAC_LFFE_OFFSET) +#define SAM_GMAC_RSE (SAM_GMAC_BASE+SAM_GMAC_RSE_OFFSET) +#define SAM_GMAC_AE (SAM_GMAC_BASE+SAM_GMAC_AE_OFFSET) +#define SAM_GMAC_RRE (SAM_GMAC_BASE+SAM_GMAC_RRE_OFFSET) +#define SAM_GMAC_ROE (SAM_GMAC_BASE+SAM_GMAC_ROE_OFFSET) +#define SAM_GMAC_IHCE (SAM_GMAC_BASE+SAM_GMAC_IHCE_OFFSET) +#define SAM_GMAC_TCE (SAM_GMAC_BASE+SAM_GMAC_TCE_OFFSET) +#define SAM_GMAC_UCE (SAM_GMAC_BASE+SAM_GMAC_UCE_OFFSET) +#define SAM_GMAC_TSSS (SAM_GMAC_BASE+SAM_GMAC_TSSS_OFFSET) +#define SAM_GMAC_TSSN (SAM_GMAC_BASE+SAM_GMAC_TSSN_OFFSET) +#define SAM_GMAC_TS (SAM_GMAC_BASE+SAM_GMAC_TS_OFFSET) +#define SAM_GMAC_TN (SAM_GMAC_BASE+SAM_GMAC_TN_OFFSET) +#define SAM_GMAC_TA (SAM_GMAC_BASE+SAM_GMAC_TA_OFFSET) +#define SAM_GMAC_TI (SAM_GMAC_BASE+SAM_GMAC_TI_OFFSET) +#define SAM_GMAC_EFTS (SAM_GMAC_BASE+SAM_GMAC_EFTS_OFFSET) +#define SAM_GMAC_EFTN (SAM_GMAC_BASE+SAM_GMAC_EFTN_OFFSET) +#define SAM_GMAC_EFRS (SAM_GMAC_BASE+SAM_GMAC_EFRS_OFFSET) +#define SAM_GMAC_EFRN (SAM_GMAC_BASE+SAM_GMAC_EFRN_OFFSET) +#define SAM_GMAC_PEFTS (SAM_GMAC_BASE+SAM_GMAC_PEFTS_OFFSET) +#define SAM_GMAC_PEFTN (SAM_GMAC_BASE+SAM_GMAC_PEFTN_OFFSET) +#define SAM_GMAC_PEFRS (SAM_GMAC_BASE+SAM_GMAC_PEFRS_OFFSET) +#define SAM_GMAC_PEFRN (SAM_GMAC_BASE+SAM_GMAC_PEFRN_OFFSET) +#define SAM_GMAC_ISRPQ(n) (SAM_GMAC_BASE+SAM_GMAC_ISRPQ_OFFSET(n)) +#define SAM_GMAC_ISRPQ0 (SAM_GMAC_BASE+SAM_GMAC_ISRPQ0_OFFSET) +#define SAM_GMAC_ISRPQ1 (SAM_GMAC_BASE+SAM_GMAC_ISRPQ1_OFFSET) +#define SAM_GMAC_ISRPQ2 (SAM_GMAC_BASE+SAM_GMAC_ISRPQ2_OFFSET) +#define SAM_GMAC_ISRPQ3 (SAM_GMAC_BASE+SAM_GMAC_ISRPQ3_OFFSET) +#define SAM_GMAC_ISRPQ4 (SAM_GMAC_BASE+SAM_GMAC_ISRPQ4_OFFSET) +#define SAM_GMAC_ISRPQ5 (SAM_GMAC_BASE+SAM_GMAC_ISRPQ5_OFFSET) +#define SAM_GMAC_ISRPQ6 (SAM_GMAC_BASE+SAM_GMAC_ISRPQ6_OFFSET) +#define SAM_GMAC_TBQBAPQ(n) (SAM_GMAC_BASE+SAM_GMAC_TBQBAPQ_OFFSET(n)) +#define SAM_GMAC_TBQBAPQ0 (SAM_GMAC_BASE+SAM_GMAC_TBQBAPQ0_OFFSET) +#define SAM_GMAC_TBQBAPQ1 (SAM_GMAC_BASE+SAM_GMAC_TBQBAPQ1_OFFSET) +#define SAM_GMAC_TBQBAPQ2 (SAM_GMAC_BASE+SAM_GMAC_TBQBAPQ2_OFFSET) +#define SAM_GMAC_TBQBAPQ3 (SAM_GMAC_BASE+SAM_GMAC_TBQBAPQ3_OFFSET) +#define SAM_GMAC_TBQBAPQ4 (SAM_GMAC_BASE+SAM_GMAC_TBQBAPQ4_OFFSET) +#define SAM_GMAC_TBQBAPQ5 (SAM_GMAC_BASE+SAM_GMAC_TBQBAPQ5_OFFSET) +#define SAM_GMAC_TBQBAPQ6 (SAM_GMAC_BASE+SAM_GMAC_TBQBAPQ6_OFFSET) +#define SAM_GMAC_RBQBAPQ(n) (SAM_GMAC_BASE+SAM_GMAC_RBQBAPQ_OFFSET(n)) +#define SAM_GMAC_RBQBAPQ0 (SAM_GMAC_BASE+SAM_GMAC_RBQBAPQ0_OFFSET) +#define SAM_GMAC_RBQBAPQ1 (SAM_GMAC_BASE+SAM_GMAC_RBQBAPQ1_OFFSET) +#define SAM_GMAC_RBQBAPQ2 (SAM_GMAC_BASE+SAM_GMAC_RBQBAPQ2_OFFSET) +#define SAM_GMAC_RBQBAPQ3 (SAM_GMAC_BASE+SAM_GMAC_RBQBAPQ3_OFFSET) +#define SAM_GMAC_RBQBAPQ4 (SAM_GMAC_BASE+SAM_GMAC_RBQBAPQ4_OFFSET) +#define SAM_GMAC_RBQBAPQ5 (SAM_GMAC_BASE+SAM_GMAC_RBQBAPQ5_OFFSET) +#define SAM_GMAC_RBQBAPQ6 (SAM_GMAC_BASE+SAM_GMAC_RBQBAPQ6_OFFSET) +#define SAM_GMAC_RBSRPQ(n) (SAM_GMAC_BASE+SAM_GMAC_RBSRPQ_OFFSET(n)) +#define SAM_GMAC_RBSRPQ0 (SAM_GMAC_BASE+SAM_GMAC_RBSRPQ0_OFFSET) +#define SAM_GMAC_RBSRPQ1 (SAM_GMAC_BASE+SAM_GMAC_RBSRPQ1_OFFSET) +#define SAM_GMAC_RBSRPQ2 (SAM_GMAC_BASE+SAM_GMAC_RBSRPQ2_OFFSET) +#define SAM_GMAC_RBSRPQ3 (SAM_GMAC_BASE+SAM_GMAC_RBSRPQ3_OFFSET) +#define SAM_GMAC_RBSRPQ4 (SAM_GMAC_BASE+SAM_GMAC_RBSRPQ4_OFFSET) +#define SAM_GMAC_RBSRPQ5 (SAM_GMAC_BASE+SAM_GMAC_RBSRPQ5_OFFSET) +#define SAM_GMAC_RBSRPQ6 (SAM_GMAC_BASE+SAM_GMAC_RBSRPQ6_OFFSET) +#define SAM_GMAC_ST1RPQ(n) (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ_OFFSET(n)) +#define SAM_GMAC_ST1RPQ0 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ0_OFFSET) +#define SAM_GMAC_ST1RPQ1 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ1_OFFSET) +#define SAM_GMAC_ST1RPQ2 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ2_OFFSET) +#define SAM_GMAC_ST1RPQ3 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ3_OFFSET) +#define SAM_GMAC_ST1RPQ4 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ4_OFFSET) +#define SAM_GMAC_ST1RPQ5 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ5_OFFSET) +#define SAM_GMAC_ST1RPQ6 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ6_OFFSET) +#define SAM_GMAC_ST1RPQ7 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ7_OFFSET) +#define SAM_GMAC_ST1RPQ8 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ8_OFFSET) +#define SAM_GMAC_ST1RPQ9 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ9_OFFSET) +#define SAM_GMAC_ST1RPQ10 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ10_OFFSET) +#define SAM_GMAC_ST1RPQ11 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ11_OFFSET) +#define SAM_GMAC_ST1RPQ12 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ12_OFFSET) +#define SAM_GMAC_ST1RPQ13 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ13_OFFSET) +#define SAM_GMAC_ST1RPQ14 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ14_OFFSET) +#define SAM_GMAC_ST1RPQ15 (SAM_GMAC_BASE+SAM_GMAC_ST1RPQ15_OFFSET) +#define SAM_GMAC_ST2RPQ(n) (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ_OFFSET(n)) +#define SAM_GMAC_ST2RPQ0 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ0_OFFSET) +#define SAM_GMAC_ST2RPQ1 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ1_OFFSET) +#define SAM_GMAC_ST2RPQ2 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ2_OFFSET) +#define SAM_GMAC_ST2RPQ3 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ3_OFFSET) +#define SAM_GMAC_ST2RPQ4 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ4_OFFSET) +#define SAM_GMAC_ST2RPQ5 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ5_OFFSET) +#define SAM_GMAC_ST2RPQ6 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ6_OFFSET) +#define SAM_GMAC_ST2RPQ7 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ7_OFFSET) +#define SAM_GMAC_ST2RPQ8 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ8_OFFSET) +#define SAM_GMAC_ST2RPQ9 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ9_OFFSET) +#define SAM_GMAC_ST2RPQ10 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ10_OFFSET) +#define SAM_GMAC_ST2RPQ11 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ11_OFFSET) +#define SAM_GMAC_ST2RPQ12 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ12_OFFSET) +#define SAM_GMAC_ST2RPQ13 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ13_OFFSET) +#define SAM_GMAC_ST2RPQ14 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ14_OFFSET) +#define SAM_GMAC_ST2RPQ15 (SAM_GMAC_BASE+SAM_GMAC_ST2RPQ15_OFFSET) +#define SAM_GMAC_IERPQ(n) (SAM_GMAC_BASE+SAM_GMAC_IERPQ_OFFSET(n)) +#define SAM_GMAC_IERPQ0 (SAM_GMAC_BASE+SAM_GMAC_IERPQ0_OFFSET) +#define SAM_GMAC_IERPQ1 (SAM_GMAC_BASE+SAM_GMAC_IERPQ1_OFFSET) +#define SAM_GMAC_IERPQ2 (SAM_GMAC_BASE+SAM_GMAC_IERPQ2_OFFSET) +#define SAM_GMAC_IERPQ3 (SAM_GMAC_BASE+SAM_GMAC_IERPQ3_OFFSET) +#define SAM_GMAC_IERPQ4 (SAM_GMAC_BASE+SAM_GMAC_IERPQ4_OFFSET) +#define SAM_GMAC_IERPQ5 (SAM_GMAC_BASE+SAM_GMAC_IERPQ5_OFFSET) +#define SAM_GMAC_IERPQ6 (SAM_GMAC_BASE+SAM_GMAC_IERPQ6_OFFSET) +#define SAM_GMAC_IDRPQ(n) (SAM_GMAC_BASE+SAM_GMAC_IDRPQ_OFFSET(n)) +#define SAM_GMAC_IDRPQ0 (SAM_GMAC_BASE+SAM_GMAC_IDRPQ0_OFFSET) +#define SAM_GMAC_IDRPQ1 (SAM_GMAC_BASE+SAM_GMAC_IDRPQ1_OFFSET) +#define SAM_GMAC_IDRPQ2 (SAM_GMAC_BASE+SAM_GMAC_IDRPQ2_OFFSET) +#define SAM_GMAC_IDRPQ3 (SAM_GMAC_BASE+SAM_GMAC_IDRPQ3_OFFSET) +#define SAM_GMAC_IDRPQ4 (SAM_GMAC_BASE+SAM_GMAC_IDRPQ4_OFFSET) +#define SAM_GMAC_IDRPQ5 (SAM_GMAC_BASE+SAM_GMAC_IDRPQ5_OFFSET) +#define SAM_GMAC_IDRPQ6 (SAM_GMAC_BASE+SAM_GMAC_IDRPQ6_OFFSET) +#define SAM_GMAC_IMRPQ(n) (SAM_GMAC_BASE+SAM_GMAC_IMRPQ_OFFSET(n)) +#define SAM_GMAC_IMRPQ0 (SAM_GMAC_BASE+SAM_GMAC_IMRPQ0_OFFSET) +#define SAM_GMAC_IMRPQ1 (SAM_GMAC_BASE+SAM_GMAC_IMRPQ1_OFFSET) +#define SAM_GMAC_IMRPQ2 (SAM_GMAC_BASE+SAM_GMAC_IMRPQ2_OFFSET) +#define SAM_GMAC_IMRPQ3 (SAM_GMAC_BASE+SAM_GMAC_IMRPQ3_OFFSET) +#define SAM_GMAC_IMRPQ4 (SAM_GMAC_BASE+SAM_GMAC_IMRPQ4_OFFSET) +#define SAM_GMAC_IMRPQ5 (SAM_GMAC_BASE+SAM_GMAC_IMRPQ5_OFFSET) +#define SAM_GMAC_IMRPQ6 (SAM_GMAC_BASE+SAM_GMAC_IMRPQ6_OFFSET) + +/* GMAC Register Bit Definitions ***************************************************/ + +/* Network Control Register */ + +#define GMAC_NCR_LBL (1 << 1) /* Bit 1: Loopback local */ +#define GMAC_NCR_RXEN (1 << 2) /* Bit 2: Receive enable */ +#define GMAC_NCR_TXEN (1 << 3) /* Bit 3: Transmit enable */ +#define GMAC_NCR_MPE (1 << 4) /* Bit 4: Management port enable */ +#define GMAC_NCR_CLRSTAT (1 << 5) /* Bit 5: Clear statistics registers */ +#define GMAC_NCR_INCSTAT (1 << 6) /* Bit 6: Increment statistics registers */ +#define GMAC_NCR_WESTAT (1 << 7) /* Bit 7: Write enable for statistics registers */ +#define GMAC_NCR_BP (1 << 8) /* Bit 8: Back pressure */ +#define GMAC_NCR_TSTART (1 << 9) /* Bit 9: Start transmission */ +#define GMAC_NCR_THALT (1 << 10) /* Bit 10: Transmit halt */ +#define GMAC_NCR_TXPF (1 << 11) /* Bit 11: Transmit Pause Frame */ +#define GMAC_NCR_TXZQPF (1 << 12) /* Bit 12: Transmit Zero Quantum Pause Frame */ +#define GMAC_NCR_RDS (1 << 14) /* Bit 14: Read Snapshot */ +#define GMAC_NCR_SRTSM (1 << 15) /* Bit 15: Store Receive Time Stamp to Memory */ +#define GMAC_NCR_ENPBPR (1 << 16) /* Bit 16: Enable PFC Priority-based Pause Reception */ +#define GMAC_NCR_TXPBPF (1 << 17) /* Bit 17: Transmit PFC Priority-based Pause Frame */ +#define GMAC_NCR_FNP (1 << 18) /* Bit 18: Flush Next Packet */ + +/* Network Configuration Register */ + +#define GMAC_NCFGR_SPD (1 << 0) /* Bit 0: Speed */ +#define GMAC_NCFGR_FD (1 << 1) /* Bit 1: Full Duplex */ +#define GMAC_NCFGR_DNVLAN (1 << 2) /* Bit 2: Discard Non-VLAN FRAMES */ +#define GMAC_NCFGR_JFRAME (1 << 3) /* Bit 3: Jumbo Frames */ +#define GMAC_NCFGR_CAF (1 << 4) /* Bit 4: Copy All Frames */ +#define GMAC_NCFGR_NBC (1 << 5) /* Bit 5: No Broadcast */ +#define GMAC_NCFGR_MTIHEN (1 << 6) /* Bit 6: Multicast Hash Enable */ +#define GMAC_NCFGR_UNIHEN (1 << 7) /* Bit 7: Unicast Hash Enable */ +#define GMAC_NCFGR_MAXFS (1 << 8) /* Bit 8: Receive 1536 bytes frames */ +#define GMAC_NCFGR_RTY (1 << 12) /* Bit 12: Retry test */ +#define GMAC_NCFGR_PEN (1 << 13) /* Bit 13: Pause Enable */ +#define GMAC_NCFGR_RXBUFO_SHIFT (14) /* Bits 14-15: Receive Buffer Offset */ +#define GMAC_NCFGR_RXBUFO_MASK (3 << GMAC_NCFGR_RXBUFO_SHIFT) +#define GMAC_NCFGR_LFERD (1 << 16) /* Bit 16: Length Field Error Frame Discard */ +#define GMAC_NCFGR_RFCS (1 << 17) /* Bit 17: Remove FCS */ +#define GMAC_NCFGR_CLK_SHIFT (18) /* Bits 18-20: MDC clock division */ +#define GMAC_NCFGR_CLK_MASK (7 << GMAC_NCFGR_CLK_SHIFT) +# define GMAC_NCFGR_CLK_DIV8 (0 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 8 (MCK up to 20 MHz) */ +# define GMAC_NCFGR_CLK_DIV16 (1 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 16 (MCK up to 40 MHz) */ +# define GMAC_NCFGR_CLK_DIV32 (2 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 32 (MCK up to 80 MHz) */ +# define GMAC_NCFGR_CLK_DIV48 (3 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 48 (MCK up to 120 MHz) */ +# define GMAC_NCFGR_CLK_DIV64 (4 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 64 (MCK up to 160 MHz) */ +# define GMAC_NCFGR_CLK_DIV96 (5 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 96 (MCK up to 240 MHz) */ +#define GMAC_NCFGR_DBW_SHIFT (21) /* Bits 21-22: Data Bus Width */ +#define GMAC_NCFGR_DBW_MASK (3 << GMAC_NCFGR_DBW_SHIFT) +# define GMAC_NCFGR_DBW_32 (0 << GMAC_NCFGR_DBW_SHIFT) /* 32-bit data bus width */ +# define GMAC_NCFGR_DBW_64 (1 << GMAC_NCFGR_DBW_SHIFT) /* 64-bit data bus width */ +#define GMAC_NCFGR_DCPF (1 << 23) /* Bit 23: Disable Copy of Pause Frames */ +#define GMAC_NCFGR_RXCOEN (1 << 24) /* Bit 24: Receive Checksum Offload Enable */ +#define GMAC_NCFGR_EFRHD (1 << 25) /* Bit 25: Enable Frames Received in Half Duplex */ +#define GMAC_NCFGR_IRXFCS (1 << 26) /* Bit 26: Ignore RX FCS */ +#define GMAC_NCFGR_IPGSEN (1 << 28) /* Bit 28: IP Stretch Enable */ +#define GMAC_NCFGR_RXBP (1 << 29) /* Bit 29: Receive Bad Preamble */ +#define GMAC_NCFGR_IRXER (1 << 30) /* Bit 30: Ignore IPG GRXER */ + +/* Network Status Register */ + +#define GMAC_NSR_MDIO (1 << 1) /* Bit 1: MDIO Input Status */ +#define GMAC_NSR_IDLE (1 << 2) /* Bit 2: PHY management logic idle */ + +/* User Register */ + +#define GMAC_UR_MII (1 << 0) /* Bit 0: MII Mode */ + +/* DMA Configuration Register */ + +#define GMAC_DCFGR_FBLDO_SHIFT (0) /* Bits 0-4: Fixed Burst Length for DMA Data Operations */ +#define GMAC_DCFGR_FBLDO_MASK (31 << GMAC_DCFGR_FBLDO_SHIFT) +# define GMAC_DCFGR_FBLDO_SINGLE (1 << GMAC_DCFGR_FBLDO_SHIFT) /* 00001: Always use SINGLE AHB bursts */ +# define GMAC_DCFGR_FBLDO_INCR4 (4 << GMAC_DCFGR_FBLDO_SHIFT) /* 001xx: Attempt to use INCR4 AHB bursts */ +# define GMAC_DCFGR_FBLDO_INCR8 (8 << GMAC_DCFGR_FBLDO_SHIFT) /* 01xxx: Attempt to use INCR8 AHB bursts */ +# define GMAC_DCFGR_FBLDO_INCR16 (16 << GMAC_DCFGR_FBLDO_SHIFT) /* 1xxxx: Attempt to use INCR16 AHB bursts */ +#define GMAC_DCFGR_ESMA (1 << 6) /* Bit 6: Endian Swap Mode Enable for Management Descriptor Accesses */ +#define GMAC_DCFGR_ESPA (1 << 7) /* Bit 7: Endian Swap Mode Enable for Packet Data Accesses */ +#define GMAC_DCFGR_RXBMS_SHIFT (8) /* Bits 8-9: Receiver Packet Buffer Memory Size Select */ +#define GMAC_DCFGR_RXBMS_MASK (3 << GMAC_DCFGR_RXBMS_SHIFT) +# define GMAC_DCFGR_RXBMS_EIGHTH (0 << GMAC_DCFGR_RXBMS_SHIFT) /* 1/2 Kbyte Memory Size */ +# define GMAC_DCFGR_RXBMS_QTR (1 << GMAC_DCFGR_RXBMS_SHIFT) /* 1Kbyte Memory Size */ +# define GMAC_DCFGR_RXBMS_HALF (2 << GMAC_DCFGR_RXBMS_SHIFT) /* 2 Kbytes Memory Size */ +# define GMAC_DCFGR_RXBMS_FULL (3 << GMAC_DCFGR_RXBMS_SHIFT) /* 4 Kbytes Memory Size */ +#define GMAC_DCFGR_TXPBMS (1 << 10) /* Bit 10: Transmitter Packet Buffer Memory Size Select */ +#define GMAC_DCFGR_TXCOEN (1 << 11) /* Bit 11: Transmitter Checksum Generation Offload Enable */ +#define GMAC_DCFGR_DRBS_SHIFT (16) /* Bits 16-23: DMA Receive Buffer Size */ +#define GMAC_DCFGR_DRBS_MASK (0xff << GMAC_DCFGR_DRBS_SHIFT) +# define GMAC_DCFGR_DRBS(n) ((uint32_t)(n) << GMAC_DCFGR_DRBS_SHIFT) +#define GMAC_DCFGR_DDRP (1 << 24) /* Bit 24: DMA Discard Receive Packets */ + +/* Transmit Status Register */ + +#define GMAC_TSR_UBR (1 << 0) /* Bit 0: Used Bit Read */ +#define GMAC_TSR_COL (1 << 1) /* Bit 1: Collision Occurred */ +#define GMAC_TSR_RLE (1 << 2) /* Bit 2: Retry Limit exceeded */ +#define GMAC_TSR_TXGO (1 << 3) /* Bit 3: Transmit Go */ +#define GMAC_TSR_TFC (1 << 4) /* Bit 4: Transmit Frame Corruption due to AHB error */ +#define GMAC_TSR_TXCOMP (1 << 5) /* Bit 5: Transmit Complete */ +#define GMAC_TSR_UND (1 << 6) /* Bit 6: Transmit Underrun */ +#define GMAC_TSR_LCO (1 << 7) /* Bit 7: Late Collision Occurred */ +#define GMAC_TSR_HRESP (1 << 8) /* Bit 8: HRESP Not OK */ + +/* Receive Buffer Queue Base Address */ + +#define GMAC_RBQB_MASK (0xfffffffc) /* Bits 2-31: Receive buffer queue base address */ + +/* Transmit Buffer Queue Base Address */ + +#define GMAC_TBQB_MASK (0xfffffffc) /* Bits 2-31: Transmit buffer queue base address */ + +/* Receive Status Register */ + +#define GMAC_RSR_BNA (1 << 0) /* Bit 0: Buffer Not Available */ +#define GMAC_RSR_REC (1 << 1) /* Bit 1: Frame Received */ +#define GMAC_RSR_RXOVR (1 << 2) /* Bit 2: Receive Overrun */ +#define GMAC_RSR_HNO (1 << 3) /* Bit 3: HRESP Not OK */ + +/* Interrupt Status Register, Interrupt Enable Register, Interrupt Disable Register */ + +#define GMAC_INT_MFS (1 << 0) /* Bit 0: Management Frame Sent */ +#define GMAC_INT_RCOMP (1 << 1) /* Bit 1: Receive Complete */ +#define GMAC_INT_RXUBR (1 << 2) /* Bit 2: Receive Used Bit Read */ +#define GMAC_INT_TXUBR (1 << 3) /* Bit 3: Transmit Used Bit Read */ +#define GMAC_INT_TUR (1 << 4) /* Bit 4: Transmit Under Run */ +#define GMAC_INT_RLEX (1 << 5) /* Bit 5: Retry Limit Exceeded or Late Collision */ +#define GMAC_INT_TFC (1 << 6) /* Bit 6: Transmit Frame Corruption due to AHB error */ +#define GMAC_INT_TCOMP (1 << 7) /* Bit 7: Transmit Complete */ +#define GMAC_INT_ROVR (1 << 10) /* Bit 10: Receive Overrun */ +#define GMAC_INT_HRESP (1 << 11) /* Bit 11: HRESP not OK */ +#define GMAC_INT_PFNZ (1 << 12) /* Bit 12: Pause Frame with Non-zero Pause Quantum */ +#define GMAC_INT_PTZ (1 << 13) /* Bit 13: Pause Time Zero */ +#define GMAC_INT_PFTR (1 << 14) /* Bit 14: Pause Frame Transmitted */ +#define GMAC_INT_EXINT (1 << 15) /* Bit 15: External Interrupt (not in ISR) */ +#define GMAC_INT_DRQFR (1 << 18) /* Bit 18: PTP Delay Request Frame Received */ +#define GMAC_INT_SFR (1 << 19) /* Bit 19: PTP Sync Frame Received */ +#define GMAC_INT_DRQFT (1 << 20) /* Bit 20: PTP Delay Request Frame Transmitted */ +#define GMAC_INT_SFT (1 << 21) /* Bit 21: PTP Sync Frame Transmitted */ +#define GMAC_INT_PDRQFR (1 << 22) /* Bit 22: PDelay Request Frame Received */ +#define GMAC_INT_PDRSFR (1 << 23) /* Bit 23: PDelay Response Frame Received */ +#define GMAC_INT_PDRQFT (1 << 24) /* Bit 24: PDelay Request Frame Transmitted */ +#define GMAC_INT_PDRSFT (1 << 25) /* Bit 25: PDelay Response Frame Transmitted */ +#define GMAC_INT_SRI (1 << 26) /* Bit 26: TSU Seconds Register Increment (not in IMR) */ +#define GMAC_INT_WOL (1 << 28) /* Bit 28: Wake On LAN (not in IMR) */ + +#define GMAC_INT_ALL (0x17fcfcff) +#define GMAC_INT_UNUSED (0xe8030300) + +/* PHY Maintenance Register */ + +#define GMAC_MAN_DATA_SHIFT (0) /* Bits 0-15: PHY data */ +#define GMAC_MAN_DATA_MASK (0x0000ffff << GMAC_MAN_DATA_SHIFT) +# define GMAC_MAN_DATA(n) ((uint32_t)(n) << GMAC_MAN_DATA_SHIFT) +#define GMAC_MAN_WTN_SHIFT (16) /* Bits 16-17: Must be written to b10 */ +#define GMAC_MAN_WTN_MASK (3 << GMAC_MAN_WTN_SHIFT) +# define GMAC_MAN_WTN (2 << GMAC_MAN_WTN_SHIFT) +#define GMAC_MAN_REGA_SHIFT (18) /* Bits 18-22: Register Address */ +#define GMAC_MAN_REGA_MASK (31 << GMAC_MAN_REGA_SHIFT) +# define GMAC_MAN_REGA(n) ((uint32_t)(n) << GMAC_MAN_REGA_SHIFT) +#define GMAC_MAN_PHYA_SHIFT (23) /* Bits 23-27: PHY Address */ +#define GMAC_MAN_PHYA_MASK (31 << GMAC_MAN_PHYA_SHIFT) +# define GMAC_MAN_PHYA(n) ((uint32_t)(n) << GMAC_MAN_PHYA_SHIFT) +#define GMAC_MAN_OP_SHIFT (28) /* Bits 28-29: Operation */ +#define GMAC_MAN_OP_MASK (3 << GMAC_MAN_OP_SHIFT) +# define GMAC_MAN_READ (2 << GMAC_MAN_OP_SHIFT) +# define GMAC_MAN_WRITE (1 << GMAC_MAN_OP_SHIFT) +#define GMAC_MAN_CLTTO (1 << 30) /* Bit 30: Clause 22 Operation */ +#define GMAC_MAN_WZO (1 << 31) /* Bit 31: Write ZERO */ + +/* Received Pause Quantum Register */ + +#define GMAC_RPQ_MASK (0x0000ffff) /* Bits 0-15: Received Pause Quantum */ + +/* Transmit Pause Quantum Register */ + +#define GMAC_TPQ_MASK (0x0000ffff) /* Bits 0-15: Transmit Pause Quantum */ + +/* TX Partial Store and Forward Register */ + +#define GMAC_TPSF_TPB1ADR_SHIFT (0) /* Bits 0-11: Transmit Partial Store and Forward Address */ +#define GMAC_TPSF_TPB1ADR_MASK (0xfff << GMAC_TPSF_TPB1ADR_SHIFT) +# define GMAC_TPSF_TPB1ADR(n) ((uint32_t)(n) << GMAC_TPSF_TPB1ADR_SHIFT) +#define GMAC_TPSF_ENTXP (1 << 31) /* Bit 31: Enable TX Partial Store and Forward Operation */ + +/* RX Partial Store and Forward Register */ + +#define GMAC_RPSF_RPB1ADR_SHIFT (0) /* Bits 0-11: Receive Partial Store and Forward Address */ +#define GMAC_RPSF_RPB1ADR_MASK (0xfff << GMAC_RPSF_RPB1ADR_SHIFT) +# define GMAC_RPSF_RPB1ADR(n) ((uint32_t)(n) << GMAC_RPSF_RPB1ADR_SHIFT) +#define GMAC_RPSF_ENRXP (1 << 31) /* Bit 31: Enable RX Partial Store and Forward Operation */ + +/* Hash Register Bottom [31:0] (32-bit value) */ +/* Hash Register Top [63:32] (32-bit value) */ + +/* Specific Address 1 Bottom [31:0] Register (32-bit value) */ +/* Specific Address 1 Top [47:32] Register */ + +#define GMAC_SAT1_MASK (0x0000ffff) /* Bits 0-15: Specific Address 1 [47:32] */ + +/* Specific Address 2 Bottom [31:0] Register (32-bit value) */ +/* Specific Address 2 Top [47:32] Register */ + +#define GMAC_SAT2_MASK (0x0000ffff) /* Bits 0-15: Specific Address 2 [47:32] */ + +/* Specific Address 3 Bottom [31:0] Register (32-bit value) */ +/* Specific Address 3 Top [47:32] Register */ + +#define GMAC_SAT3_MASK (0x0000ffff) /* Bits 0-15: Specific Address 3 [47:32] */ + +/* Specific Address 4 Bottom [31:0] Register (32-bit value) */ +/* Specific Address 4 Top [47:32] Register */ + +#define GMAC_SAT4_MASK (0x0000ffff) /* Bits 0-15: Specific Address 4 [47:32] */ + +/* Type ID Match 1 Register */ + +#define GMAC_TIDM1_MASK (0x0000ffff) /* Bits 0-15: Type ID Match 1 */ + +/* Type ID Match 2 Register */ + +#define GMAC_TIDM2_MASK (0x0000ffff) /* Bits 0-15: Type ID Match 2 */ + +/* Type ID Match 3 Register */ + +#define GMAC_TIDM3_MASK (0x0000ffff) /* Bits 0-15: Type ID Match 3 */ + +/* Type ID Match 4 Register */ + +#define GMAC_TIDM4_MASK (0x0000ffff) /* Bits 0-15: Type ID Match 4 */ + +/* Wake on LAN Register */ + +#define GMAC_WOL_IP_SHIFT (0) /* Bits 0-15: ARP request IP address */ +#define GMAC_WOL_IP_MASK (0x0000ffff << GMAC_WOL_IP_SHIFT) +#define GMAC_WOL_MAG (1 << 16) /* Bit 16: Magic packet event enable */ +#define GMAC_WOL_ARP (1 << 17) /* Bit 17: ARP request event enable */ +#define GMAC_WOL_SA1 (1 << 18) /* Bit 18: Specific address register 1 event enable */ +#define GMAC_WOL_MTI (1 << 19) /* Bit 19: Multicast hash event enable */ + +/* IPG Stretch Register */ + +#define GMAC_IPGS_MASK (0x0000ffff) /* Bits 0-15: Frame Length */ + +/* Stacked VLAN Register */ + +#define GMAC_SVLAN_VLANTYP_SHIFT (0) /* Bits 0-15: User Defined VLAN_TYPE Field */ +#define GMAC_SVLAN_VLANTYP_MASK (0xffff << GMAC_SVLAN_VLANTYP_SHIFT) +# define GMAC_SVLAN_VLANTYP(n) ((uint32_t)(n) << GMAC_SVLAN_VLANTYP_SHIFT) +#define GMAC_SVLAN_ESVLAN (1 << 31) /* Bit 31: Enable Stacked VLAN Processing Mode */ + +/* Transmit PFC Pause Register */ + +#define GMAC_TPFCP_PEV_SHIFT (0) /* Bits 0-7: Priority Enable Vector */ +#define GMAC_TPFCP_PEV_MASK (0xff << GMAC_TPFCP_PEV_SHIFT) +#define GMAC_TPFCP_PQ_SHIFT (8) /* Bits 8-15: Pause Quantum */ +#define GMAC_TPFCP_PQ_MASK (0xff << GMAC_TPFCP_PQ_SHIFT) + +/* Specific Address 1 Mask Bottom [31:0] Register (32-bit mask) */ +/* Specific Address 1 Mask Top [47:32] Register */ + +#define GMAC_SAMT1_MASK (0x0000ffff) /* Bits 0-15: Specific Address 1 Mask [47:32] */ + +/* Octets Transmitted [31:0] Register (32-bit value) */ +/* Octets Transmitted [47:32] Register */ + +#define GMAC_OTHI_MASK (0x0000ffff) /* Bits 0-15: Transmitted Octets [47:32] */ + +/* Frames Transmitted Register (32-bit value) */ +/* Broadcast Frames Transmitted Register (32-bit value) */ +/* Multicast Frames Transmitted Register (32-bit value) */ + +/* Pause Frames Transmitted Register */ + +#define GMAC_PFT_MASK (0x0000ffff) /* Bits 0-15: Pause Frames Transmitted */ + +/* 64 Byte Frames Transmitted Register (32-bit value) */ +/* 65 to 127 Byte Frames Transmitted Register (32-bit value) */ +/* 128 to 255 Byte Frames Transmitted Register (32-bit value) */ +/* 256 to 511 Byte Frames Transmitted Register (32-bit value) */ +/* 512 to 1023 Byte Frames Transmitted Register (32-bit value) */ +/* 1024 to 1518 Byte Frames Transmitted Register (32-bit value) */ +/* Greater Than 1518 Byte Frames Transmitted Register (32-bit value) */ + +/* Transmit Under Runs Register */ + +#define GMAC_TUR_MASK (0x000003ff) /* Bits 0-9: Transmit Under Runs */ + +/* Single Collision Frames Register */ + +#define GMAC_SCF_MASK (0x0003ffff) /* Bits 0-17: Single Collisions */ + +/* Multiple Collision Frames Register */ + +#define GMAC_MCF_MASK (0x0003ffff) /* Bits 0-17: Multiple Collisions */ + +/* Excessive Collisions Register */ + +#define GMAC_EC_MASK (0x000003ff) /* Bits 0-9: Excessive Collisions */ + +/* Late Collisions Register */ + +#define GMAC_LC_MASK (0x000003ff) /* Bits 0-9: Late Collisions */ + +/* Deferred Transmission Frames Register */ + +#define GMAC_DTF_MASK (0x0003ffff) /* Bits 0-17: Deferred Transmission */ + +/* Carrier Sense Errors Register */ + +#define GMAC_CSE_MASK (0x000003ff) /* Bits 0-9: Carrier Sense Error */ + +/* Octets Received [31:0] Received (32-bit value) */ +/* Octets Received [47:32] Received */ + +#define GMAC_ORHI_MASK (0x0000ffff) /* Bits 0-15: Received Octets [47:32] */ + +/* Frames Received Register (32-bit value) */ +/* Broadcast Frames Received Register (32-bit value) */ +/* Multicast Frames Received Register (32-bit value) */ +/* Pause Frames Received Register */ + +#define GMAC_PFR_MASK (0x0000ffff) /* Bits 0-15: Pause Frames Received */ + +/* 64 Byte Frames Received Register (32-bit value) */ +/* 65 to 127 Byte Frames Received Register (32-bit value) */ +/* 128 to 255 Byte Frames Received Register (32-bit value) */ +/* 256 to 511Byte Frames Received Register (32-bit value) */ +/* 512 to 1023 Byte Frames Received Register (32-bit value) */ +/* 1024 to 1518 Byte Frames Received Register (32-bit value) */ +/* 1519 to Maximum Byte Frames Received Register (32-bit value) */ + +/* Undersize Frames Received Register */ + +#define GMAC_UFR_MASK (0x000003ff) /* Bits 0-9: Undersize Frames Received */ + +/* Oversize Frames Received Register */ + +#define GMAC_OFR_MASK (0x000003ff) /* Bits 0-9: Oversized Frames Received */ + +/* Jabbers Received Register */ + +#define GMAC_JR_MASK (0x000003ff) /* Bits 0-9: Jabbers Received */ + +/* Frame Check Sequence Errors Register */ + +#define GMAC_FCSE_MASK (0x000003ff) /* Bits 0-9: Frame Check Sequence Errors */ + +/* Length Field Frame Errors Register */ + +#define GMAC_LFFE_MASK (0x000003ff) /* Bits 0-9: Length Field Frame Errors */ + +/* Receive Symbol Errors Register */ + +#define GMAC_RSE_MASK (0x000003ff) /* Bits 0-9: Receive Symbol Errors */ + +/* Alignment Errors Register */ + +#define GMAC_AE_MASK (0x000003ff) /* Bits 0-9: Alignment Errors */ + +/* Receive Resource Errors Register */ + +#define GMAC_RRE_MASK (0x0003ffff) /* Bits 0-17: Receive Resource Errors */ + +/* Receive Overrun Register */ + +#define GMAC_ROE_MASK (0x000003ff) /* Bits 0-9: Receive Overruns */ + +/* IP Header Checksum Errors Register */ + +#define GMAC_IHCE_MASK (0x000000ff) /* Bits 0-7: IP Header Checksum Errors */ + +/* TCP Checksum Errors Register */ + +#define GMAC_TCE_MASK (0x000000ff) /* Bits 0-7: TCP Header Checksum Errors */ + +/* UDP Checksum Errors Register */ + +#define GMAC_UCE_MASK (0x000000ff) /* Bits 0-7: UDP Header Checksum Errors */ + +/* 1588 Timer Sync Strobe Seconds Register (32-bit value) */ +/* 1588 Timer Sync Strobe Nanoseconds Register */ + +#define GMAC_TSSN_MASK (0x3fffffff) /* Bits 0-29: Value Timer Nanoseconds Register Capture */ + +/* 1588 Timer Seconds Register (32-bit value) */ +/* 1588 Timer Nanoseconds Register */ + +#define GMAC_TN_MASK (0x3fffffff) /* Bits 0-29: Timer Count in Nanoseconds */ + +/* 1588 Timer Adjust Register */ + +#define GMAC_TA_ITDT_SHIFT (0) /* Bits 0-29: Increment/Decrement */ +#define GMAC_TA_ITDT_MASK (0x3fffffff) +#define GMAC_TA_ADJ (1 << 31) /* Bit 31: Adjust 1588 Timer */ + +/* 1588 Timer Increment Register */ + +#define GMAC_TI_CNS_SHIFT (0) /* Bits 0-7: Count Nanoseconds */ +#define GMAC_TI_CNS_MASK (0xff << GMAC_TI_CNS_SHIFT) +# define GMAC_TI_CNS(n) ((uint32_t)(n) << GMAC_TI_CNS_SHIFT) +#define GMAC_TI_ACNS_SHIFT (8) /* Bits 8-15: Alternative Count Nanoseconds */ +#define GMAC_TI_ACNS_MASK (0xff << GMAC_TI_ACNS_SHIFT) +# define GMAC_TI_ACNS(n) ((uint32_t)(n) << GMAC_TI_ACNS_SHIFT) +#define GMAC_TI_NIT_SHIFT (16) /* Bits 16-23: Number of Increments */ +#define GMAC_TI_NIT_MASK (0xff << GMAC_TI_NIT_SHIFT) +# define GMAC_TI_NIT(n) ((uint32_t)(n) << GMAC_TI_NIT_SHIFT) + +/* PTP Event Frame Transmitted Seconds (32-bit value) */ +/* PTP Event Frame Transmitted Nanoseconds */ + +#define GMAC_EFTN_MASK (0x3fffffff) /* Bits 0-29: Register Update */ + +/* PTP Event Frame Received Seconds (32-bit value) */ +/* PTP Event Frame Received Nanoseconds */ + +#define GMAC_EFRN_MASK (0x3fffffff) /* Bits 0-29: Register Update */ + +/* PTP Peer Event Frame Transmitted Seconds (32-bit value) */ +/* PTP Peer Event Frame Transmitted Nanoseconds */ + +#define GMAC_PEFTN_MASK (0x3fffffff) /* Bits 0-29: Register Update */ + +/* PTP Peer Event Frame Received Seconds (32-bit value) */ +/* PTP Peer Event Frame Received Nanoseconds */ + +#define GMAC_PEFRS_MASK (0x3fffffff) /* Bits 0-29: Register Update */ + +/* Interrupt Status Register Priority Queue 0-6 + * Interrupt Enable Register Priority Queue 0-6 + * Interrupt Disable Register Priority Queue 0-6 + * Interrupt Mask Register Priority Queue 0-6 + * + * Use these definitions: + * + * GMAC_INT_RCOMP Bit 1: Receive Complete + * GMAC_INT_RXUBR Bit 2: Receive Used Bit Read + * GMAC_INT_RLEX Bit 5: Retry Limit Exceeded or + * Late Collision + * GMAC_INT_TFC Bit 6: Transmit Frame Corruption + * due to AHB error + * GMAC_INT_TCOMP Bit 7: Transmit Complete + * GMAC_INT_ROVR Bit 10: Receive Overrun + * GMAC_INT_HRESP Bit 11: HRESP not OK + */ + +/* Transmit Buffer Queue Base Address Priority Queue 0-6 */ + +#define GMAC_TBQBAPQ0_MASK (0xfffffffc) /* Bits 2-31: Transmit Buffer Queue Base Address */ + +/* Receive Buffer Queue Base Address Priority Queue 0-6 */ + +#define GMAC_RBQBAPQ0_MASK (0xfffffffc) /* Bits 2-31: Receive Buffer Queue Base Address */ + +/* Receive Buffer Size Register Priority Queue 0-6 */ + +#define GMAC_RBSRPQ0_MASK (0x0000ffff) /* Bits 0-15: Receive Buffer Size */ + +/* Screening Type1 Register Priority Queue 0-15 */ + +#define GMAC_ST1RPQ0_QNB_SHIFT (0) /* Bits 0-3: Que Number (0->7) */ +#define GMAC_ST1RPQ0_QNB_MASK (15 << GMAC_ST1RPQ0_QNB_SHIFT) +# define GMAC_ST1RPQ0_QNB(n) ((uint32_t)(n) << GMAC_ST1RPQ0_QNB_SHIFT) +#define GMAC_ST1RPQ0_DSTCM_SHIFT (4) /* Bits 4-11: Differentiated Services or Traffic Class Match */ +#define GMAC_ST1RPQ0_DSTCM_MASK (0xff << GMAC_ST1RPQ0_DSTCM_SHIFT) +# define GMAC_ST1RPQ0_DSTCM(n) ((uint32_t)(n) << GMAC_ST1RPQ0_DSTCM_SHIFT) +#define GMAC_ST1RPQ0_UDPM_SHIFT (12) /* Bits 12-27: UDP Port Match */ +#define GMAC_ST1RPQ0_UDPM_MASK (0xffff << GMAC_ST1RPQ0_UDPM_SHIFT) +# define GMAC_ST1RPQ0_UDPM(n) ((uint32_t)(n) << GMAC_ST1RPQ0_UDPM_SHIFT) +#define GMAC_ST1RPQ0_DSTCE (1 << 28) /* Bit 28: Differentiated Services or Traffic Class Match Enable */ +#define GMAC_ST1RPQ0_UDPE (1 << 29) /* Bit 29: UDP Port Match Enable */ + +/* Screening Type2 Register Priority Queue 0-15 */ + +#define GMAC_ST2RPQ0_QNB_SHIFT (0) /* Bits 0-3: Que Number (0->7) */ +#define GMAC_ST2RPQ0_QNB_MASK (15 << GMAC_ST2RPQ0_QNB_SHIFT) +# define GMAC_ST2RPQ0_QNB(n) ((uint32_t)(n) << GMAC_ST2RPQ0_QNB_SHIFT) +#define GMAC_ST2RPQ0_VLANP_SHIFT (4) /* Bits 4-7: VLAN Priority */ +#define GMAC_ST2RPQ0_VLANP_MASK (15 << GMAC_ST2RPQ0_VLANP_SHIFT) +# define GMAC_ST2RPQ0_VLANP(n) ((uint32_t)(n) << GMAC_ST2RPQ0_VLANP_SHIFT) +#define GMAC_ST2RPQ0_VLANE (1 << 8) /* Bit 8: VLAN Enable */ + +/* Descriptors **********************************************************************/ + +/* Receive buffer descriptor: Address word */ + +#define GMACRXD_ADDR_OWNER (1 << 0) /* Bit 0: 1=Software owns; 0=GMAC owns */ +#define GMACRXD_ADDR_WRAP (1 << 1) /* Bit 1: Last descriptor in list */ +#define GMACRXD_ADDR_MASK (0xfffffffc) /* Bits 2-31: Aligned buffer address */ + +/* Receive buffer descriptor: Control word */ + +#define GMACRXD_STA_FRLEN_SHIFT (0) /* Bits 0-12: Length of frame */ +#define GMACRXD_STA_FRLEN_MASK (0x00000fff << GMACRXD_STA_FRLEN_SHIFT) +#define GMACRXD_STA_JFRLEN_SHIFT (0) /* Bits 0-13: Length of jumbo frame */ +#define GMACRXD_STA_JFRLEN_MASK (0x00001fff << GMACRXD_STA_JFRLEN_SHIFT) +#define GMACRXD_STA_BADFCS (1 << 13) /* Bit 13: Frame had bad FCS */ +#define GMACRXD_STA_SOF (1 << 14) /* Bit 14: Start of frame */ +#define GMACRXD_STA_EOF (1 << 15) /* Bit 15: End of frame */ +#define GMACRXD_STA_CFI (1 << 16) /* Bit 16: Canonical format indicator (CFI) bit */ +#define GMACRXD_STA_VLPRIO_SHIFT (17) /* Bits 17-19: VLAN priority */ +#define GMACRXD_STA_VLPRIO_MASK (7 << GMACRXD_STA_VLANPRIO_SHIFT) +#define GMACRXD_STA_PRIODET (1 << 20) /* Bit 20: Priority tag detected */ +#define GMACRXD_STA_VLANTAG (1 << 21) /* Bit 21: VLAN tag detected */ +#define GMACRXD_STA_TYPID_SHIFT (22) /* Bits 22-23: Type ID register match */ +#define GMACRXD_STA_TYPID_MASK (3 << GMACRXD_STA_TYPID_SHIFT) +# define GMACRXD_STA_TYPID1 (0 << GMACRXD_STA_TYPID_SHIFT) /* Type ID register 1 match */ +# define GMACRXD_STA_TYPID2 (1 << GMACRXD_STA_TYPID_SHIFT) /* Type ID register 2 match */ +# define GMACRXD_STA_TYPID3 (2 << GMACRXD_STA_TYPID_SHIFT) /* Type ID register 3 match */ +# define GMACRXD_STA_TYPID4 (3 << GMACRXD_STA_TYPID_SHIFT) /* Type ID register 4 match */ +#define GMACRXD_STA_SNAP_SHIFT (22) /* Bits 22-23: Specific Address Register match */ +#define GMACRXD_STA_SNAP_MASK (3 << GMACRXD_STA_SNAP_SHIFT) +# define GMACRXD_STA_SNAP_NOCHK (0 << GMACRXD_STA_SNAP_SHIFT) /* Checksum not checked */ +# define GMACRXD_STA_SNAP_IPCHK (1 << GMACRXD_STA_SNAP_SHIFT) /* IP header checksum checked */ +# define GMACRXD_STA_SNAP_TCPCHK (2 << GMACRXD_STA_SNAP_SHIFT) /* IP header and TCP checksum checked */ +# define GMACRXD_STA_SNAP_UDPCHK (3 << GMACRXD_STA_SNAP_SHIFT) /* IP header and UDP checksum checked */ +#define GMACRXD_STA_TYPID (1 << 24) /* Bit 24: Type ID match found */ +#define GMACRXD_STA_SNAP (1 << 24) /* Bit 24: Frame was SNAP encoded */ +#define GMACRXD_STA_ADDR_SHIFT (25) /* Bits 25-26: Specific Address Register match */ +#define GMACRXD_STA_ADDR_MASK (3 << GMACRXD_STA_ADDR_SHIFT) +# define GMACRXD_STA_ADDR1_MATCH (0 << GMACRXD_STA_ADDR_SHIFT) /* Specific address register 1 match */ +# define GMACRXD_STA_ADDR2_MATCH (1 << GMACRXD_STA_ADDR_SHIFT) /* Specific address register 2 match */ +# define GMACRXD_STA_ADDR3_MATCH (2 << GMACRXD_STA_ADDR_SHIFT) /* Specific address register 3 match */ +# define GMACRXD_STA_ADDR4_MATCH (3 << GMACRXD_STA_ADDR_SHIFT) /* Specific address register 4 match */ +#define GMACRXD_STA_ADDRMATCH (1 << 27) /* Bit 27: Specific Address Register match found */ + /* Bit 28: Reserved */ +#define GMACRXD_STA_UCAST (1 << 29) /* Bit 29: Unicast hash match */ +#define GMACRXD_STA_MCAST (1 << 30) /* Bit 30: Multicast hash match */ +#define GMACRXD_STA_BCAST (1 << 31) /* Bit 31: Global all ones broadcast address detected */ + +/* Transmit buffer descriptor: Address word (un-aligned, 32-bit address */ + +/* Transmit buffer descriptor: Control word */ + +#define GMACTXD_STA_BUFLEN_SHIFT (0) /* Bits 0-13: Length of buffer */ +#define GMACTXD_STA_BUFLEN_MASK (0x00003fff << GMACTXD_STA_BUFLEN_SHIFT) + /* Bit 14: Reserved */ +#define GMACTXD_STA_LAST (1 << 15) /* Bit 15: Last buffer in the current frame */ +#define GMACTXD_STA_NOCRC (1 << 16) /* Bit 16: No CRC */ + /* Bits 17-19: Reserved */ +#define GMACTXD_STA_CKERR_SHIFT (20) /* Bits 20-22: Transmit checksum generation errors */ +#define GMACTXD_STA_CKERR_MASK (7 << GMACTXD_STA_CKERR_SHIFT) +# define GMACTXD_STA_CKERR_OK (0 << GMACTXD_STA_CKERR_SHIFT) /* No Error */ +# define GMACTXD_STA_CKERR_VLAN (1 << GMACTXD_STA_CKERR_SHIFT) /* VLAN header error */ +# define GMACTXD_STA_CKERR_SNAP (2 << GMACTXD_STA_CKERR_SHIFT) /* SNAP header error */ +# define GMACTXD_STA_CKERR_IP (3 << GMACTXD_STA_CKERR_SHIFT) /* Bad IP type */ +# define GMACTXD_STA_CKERR_UNK (4 << GMACTXD_STA_CKERR_SHIFT) /* Not VLAN, SNAP or IP */ +# define GMACTXD_STA_CKERR_FRAG (5 << GMACTXD_STA_CKERR_SHIFT) /* Bad packet fragmentation */ +# define GMACTXD_STA_CKERR_PROTO (6 << GMACTXD_STA_CKERR_SHIFT) /* Not TCP or UDP */ +# define GMACTXD_STA_CKERR_END (7 << GMACTXD_STA_CKERR_SHIFT) /* Premature end of packet */ + /* Bits 23-25: Reserved */ +#define GMACTXD_STA_LCOL (1 << 26) /* Bit 26: Late collision */ +#define GMACTXD_STA_TFC (1 << 27) /* Bit 27: Transmit Frame Corruption due to AHB error */ +#define GMACTXD_STA_TXUR (1 << 28) /* Bit 28: Transmit underrun */ +#define GMACTXD_STA_TXERR (1 << 29) /* Bit 29: Retry limit exceeded, transmit error detected */ +#define GMACTXD_STA_WRAP (1 << 30) /* Bit 30: Last descriptor in descriptor list */ +#define GMACTXD_STA_USED (1 << 31) /* Bit 31: Zero for the GMAC to read from buffer */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ +/* Receive buffer descriptor */ + +struct gmac_rxdesc_s +{ + uint32_t addr; /* Buffer address */ + uint32_t status; /* RX status and controls */ +}; + +/* Transmit buffer descriptor */ + +struct gmac_txdesc_s +{ + uint32_t addr; /* Buffer address */ + uint32_t status; /* TX status and controls */ +}; + +#endif /* __ARCH_ARM_SRC_SAMA5_HARDWARE_SAM_GMAC_H */ diff --git a/arch/arm/src/samd5e5/hardware/sam_memorymap.h b/arch/arm/src/samd5e5/hardware/sam_memorymap.h index ef08130b63..e0814f19e3 100644 --- a/arch/arm/src/samd5e5/hardware/sam_memorymap.h +++ b/arch/arm/src/samd5e5/hardware/sam_memorymap.h @@ -42,7 +42,7 @@ #include -#if defined(CONFIG_ARCH_CHIP_SAMD5X) || defined(ARCH_CHIP_SAME5X) +#if defined(CONFIG_ARCH_CHIP_SAMD5X) || defined(CONFIG_ARCH_CHIP_SAME5X) # include "hardware/samd5e5_memorymap.h" #else # error "Unsupported SAMD5/E5 family" diff --git a/arch/arm/src/samd5e5/hardware/sam_pinmap.h b/arch/arm/src/samd5e5/hardware/sam_pinmap.h index ac72745021..9f9189de4f 100644 --- a/arch/arm/src/samd5e5/hardware/sam_pinmap.h +++ b/arch/arm/src/samd5e5/hardware/sam_pinmap.h @@ -42,7 +42,7 @@ #include -#if defined(CONFIG_ARCH_CHIP_SAMD5X) || defined(ARCH_CHIP_SAME5X) +#if defined(CONFIG_ARCH_CHIP_SAMD5X) || defined(CONFIG_ARCH_CHIP_SAME5X) # include "hardware/samd5e5_pinmap.h" #else # error "Unsupported SAMD5/E5 family" diff --git a/arch/arm/src/samd5e5/sam_ethernet.c b/arch/arm/src/samd5e5/sam_ethernet.c new file mode 100644 index 0000000000..d668911442 --- /dev/null +++ b/arch/arm/src/samd5e5/sam_ethernet.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * arch/arm/src/samd5e5/sam_ethernet.c + * + * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include "sam_ethernet.h" + +#ifdef CONFIG_NET + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_gmac_initialize + * + * Description: + * Initialize the GMAC driver + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_SAMD5E5_GMAC +static inline void up_gmac_initialize(void) +{ + int ret; + + /* Initialize the GMAC driver */ + + ret = sam_gmac_initialize(); + if (ret < 0) + { + nerr("ERROR: sam_gmac_initialize failed: %d\n", ret); + } +} +#else +# define up_gmac_initialize() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_netinitialize + * + * Description: + * This is the "standard" network initialization logic called from the + * low-level initialization logic in up_initialize.c. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +void up_netinitialize(void) +{ + up_gmac_initialize(); +} + +#endif /* CONFIG_NET */ diff --git a/arch/arm/src/samd5e5/sam_ethernet.h b/arch/arm/src/samd5e5/sam_ethernet.h new file mode 100644 index 0000000000..d9f6003ef1 --- /dev/null +++ b/arch/arm/src/samd5e5/sam_ethernet.h @@ -0,0 +1,149 @@ +/**************************************************************************** + * arch/arm/src/samd5e5/sam_ethernet.h + * + * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_SAMD5E5_SAM_ETHERNET_H +#define __ARCH_ARM_SRC_SAMD5E5_SAM_ETHERNET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" +#include "hardware/sam_gmac.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Understood PHY types */ + +#define SAMD5E5_PHY_DM9161 0 +#define SAMD5E5_PHY_LAN8700 1 +#define SAMD5E5_PHY_KSZ8051 2 +#define SAMD5E5_PHY_KSZ8081 3 +#define SAMD5E5_PHY_KSZ90x1 4 + +/* Definitions for use with sam_phy_boardinitialize */ + +# if defined(CONFIG_ETH0_PHY_DM9161) +# define SAMD5E5_GMAC_PHY_DM9161 1 +# define SAMD5E5_GMAC_PHY_TYPE SAMD5E5_PHY_DM9161 +# elif defined(CONFIG_ETH0_PHY_LAN8700) +# define SAMD5E5_GMAC_PHY_LAN8700 1 +# define SAMD5E5_GMAC_PHY_TYPE SAMD5E5_PHY_LAN8700 +# elif defined(CONFIG_ETH0_PHY_KSZ8051) +# define SAMD5E5_GMAC_PHY_KSZ8051 1 +# define SAMD5E5_GMAC_PHY_TYPE SAMD5E5_PHY_KSZ8051 +# elif defined(CONFIG_ETH0_PHY_KSZ8081) +# define SAMD5E5_GMAC_PHY_KSZ8081 1 +# define SAMD5E5_GMAC_PHY_TYPE SAMD5E5_PHY_KSZ8081 +# elif defined(CONFIG_ETH0_PHY_KSZ90x1) +# define SAMD5E5_GMAC_PHY_KSZ90x1 1 +# define SAMD5E5_GMAC_PHY_TYPE SAMD5E5_PHY_KSZ90x1 +# else +# error ETH0 PHY unrecognized +# endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Function: sam_gmac_initialize + * + * Description: + * Initialize the GMAC driver. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * Called very early in the initialization sequence. + * + ****************************************************************************/ + +#ifdef CONFIG_SAMD5E5_GMAC +int sam_gmac_initialize(void); +#endif + +/**************************************************************************** + * Function: sam_phy_boardinitialize + * + * Description: + * Some boards require specialized initialization of the PHY before it can + * be used. This may include such things as configuring GPIOs, resetting + * the PHY, etc. If CONFIG_SAMD5E5_GMAC_PHYINIT is defined in the + * configuration then the board specific logic must provide + * sam_phyinitialize(); The SAMD5E5 Ethernet driver will call this + * function one time before it first uses the PHY. + * + * Input Parameters: + * intf - Always zero for now. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ************************************************************************************/ + +#ifdef CONFIG_SAMD5E5_GMAC_PHYINIT +int sam_phy_boardinitialize(int intf); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_SAMD5E5_SAM_ETHERNET_H */ + diff --git a/arch/arm/src/samd5e5/sam_gmac.c b/arch/arm/src/samd5e5/sam_gmac.c new file mode 100644 index 0000000000..8cc07e1e63 --- /dev/null +++ b/arch/arm/src/samd5e5/sam_gmac.c @@ -0,0 +1,3831 @@ +/**************************************************************************** + * arch/arm/src/samd5e5/sam_gmac.c + * + * Copyright (C) 2013-2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * SAMD5E5D3 Series Data Sheet + * Atmel NoOS sample code. + * + * The Atmel sample code has a BSD compatible license that requires this + * copyright notice: + * + * Copyright (c) 2012, Atmel Corporation + * + * 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. Neither the names NuttX nor Atmel nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_NET_PKT +# include +#endif + +#include "up_arch.h" +#include "up_internal.h" + +#include "chip.h" +#include "hardware/sam_pinmap.h" +#include "sam_periphclks.h" +#include "sam_ethernet.h" +#include "sam_port.h" +#include + +#if defined(CONFIG_NET) && defined(CONFIG_SAMD5E5_GMAC) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* If processing is not done at the interrupt level, then work queue support + * is required. + */ + +#if !defined(CONFIG_SCHED_WORKQUEUE) +# error Work queue support is required +#endif + +/* The low priority work queue is preferred. If it is not enabled, LPWORK + * will be the same as HPWORK. + * + * NOTE: However, the network should NEVER run on the high priority work + * queue! That queue is intended only to service short back end interrupt + * processing that never suspends. Suspending the high priority work queue + * may bring the system to its knees! + */ + +#define ETHWORK LPWORK + +/* Number of buffer for RX */ + +#ifndef CONFIG_SAMD5E5_GMAC_NRXBUFFERS +# define CONFIG_SAMD5E5_GMAC_NRXBUFFERS 16 +#endif + +/* Number of buffer for TX */ + +#ifndef CONFIG_SAMD5E5_GMAC_NTXBUFFERS +# define CONFIG_SAMD5E5_GMAC_NTXBUFFERS 8 +#endif + +#undef CONFIG_SAMD5E5_GMAC_NBC + +#ifndef CONFIG_SAMD5E5_GMAC_PHYADDR +# error "CONFIG_SAMD5E5_GMAC_PHYADDR must be defined in the NuttX configuration" +#endif + +/* PHY definitions */ + +#ifdef SAMD5E5_GMAC_PHY_KSZ8081 +# define GMII_OUI_MSB 0x0022 +# define GMII_OUI_LSB GMII_PHYID2_OUI(5) +#else +# error Unknown PHY +#endif + +/* GMAC buffer sizes, number of buffers, and number of descriptors. *********/ + +#define GMAC_RX_UNITSIZE 128 /* Fixed size for RX buffer */ +#define GMAC_TX_UNITSIZE CONFIG_NET_ETH_PKTSIZE /* MAX size for Ethernet packet */ + +/* The MAC can support frame lengths up to 1536 bytes */ + +#define GMAC_MAX_FRAMELEN 1536 +#if CONFIG_NET_ETH_PKTSIZE > GMAC_MAX_FRAMELEN +# error CONFIG_NET_ETH_PKTSIZE is too large +#endif + +/* We need at least one more free buffer than transmit buffers */ + +#define SAM_GMAC_NFREEBUFFERS (CONFIG_SAMD5E5_GMAC_NTXBUFFERS+1) + +/* Extremely detailed register debug that you would normally never want + * enabled. + */ + +#ifndef CONFIG_DEBUG_NET_INFO +# undef CONFIG_SAMD5E5_GMAC_REGDEBUG +#endif + +#ifdef CONFIG_NET_DUMPPACKET +# define sam_dumppacket(m,a,n) lib_dumpbuffer(m,a,n) +#else +# define sam_dumppacket(m,a,n) +#endif + +/* Timing *******************************************************************/ + +/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per + * second + */ + +#define SAM_WDDELAY (1*CLK_TCK) + +/* TX timeout = 1 minute */ + +#define SAM_TXTIMEOUT (60*CLK_TCK) + +/* PHY read/write delays in loop counts */ + +#define PHY_RETRY_MAX 300000 + +/* Helpers ******************************************************************/ + +/* This is a helper pointer for accessing the contents of the GMAC + * header + */ + +#define BUF ((struct eth_hdr_s *)priv->dev.d_buf) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The sam_gmac_s encapsulates all state information for the GMAC peripheral */ + +struct sam_gmac_s +{ + uint8_t ifup : 1; /* true:ifup false:ifdown */ + WDOG_ID txpoll; /* TX poll timer */ + WDOG_ID txtimeout; /* TX timeout timer */ + struct work_s irqwork; /* For deferring interrupt work to the work queue */ + struct work_s pollwork; /* For deferring poll work to the work queue */ + + /* This holds the information visible to the NuttX network */ + + struct net_driver_s dev; /* Interface understood by the network */ + + /* Used to track transmit and receive descriptors */ + + uint8_t phyaddr; /* PHY address (pre-defined by pins on reset) */ + uint16_t txhead; /* Circular buffer head index */ + uint16_t txtail; /* Circualr buffer tail index */ + uint16_t rxndx; /* RX index for current processing RX descriptor */ + + uint8_t *rxbuffer; /* Allocated RX buffers */ + uint8_t *txbuffer; /* Allocated TX buffers */ + struct gmac_rxdesc_s *rxdesc; /* Allocated RX descriptors */ + struct gmac_txdesc_s *txdesc; /* Allocated TX descriptors */ + + /* Debug stuff */ + +#ifdef CONFIG_SAMD5E5_GMAC_REGDEBUG + bool wrlast; /* Last was a write */ + uintptr_t addrlast; /* Last address */ + uint32_t vallast; /* Last value */ + int ntimes; /* Number of times */ +#endif +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The driver state singleton */ + +static struct sam_gmac_s g_gmac; + +/* A single packet buffer is used + * + * REVISIT: It might be possible to use this option to send and receive + * messages directly into the DMA buffers, saving a copy. There might be + * complications on the receiving side, however, where buffers may wrap + * and where the size of the received frame will typically be smaller than + * a full packet. + */ + +static uint8_t g_pktbuf[MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE]; + +#ifdef CONFIG_SAMD5E5_GMAC_PREALLOCATE +/* Preallocated data */ + +/* TX descriptors list */ + +static struct gmac_txdesc_s g_txdesc[CONFIG_SAMD5E5_GMAC_NTXBUFFERS] + __attribute__((aligned(8))); + +/* RX descriptors list */ + +static struct gmac_rxdesc_s g_rxdesc[CONFIG_SAMD5E5_GMAC_NRXBUFFERS] + __attribute__((aligned(8))); + +/* Transmit Buffers + * + * 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 + */ + +static uint8_t g_txbuffer[CONFIG_SAMD5E5_GMAC_NTXBUFFERS * GMAC_TX_UNITSIZE] + __attribute__((aligned(8))); + +/* Receive Buffers */ + +static uint8_t g_rxbuffer[CONFIG_SAMD5E5_GMAC_NRXBUFFERS * GMAC_RX_UNITSIZE] + __attribute__((aligned(8))); +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Register operations ******************************************************/ + +#if defined(CONFIG_SAMD5E5_GMAC_REGDEBUG) && defined(CONFIG_DEBUG_FEATURES) +static bool sam_checkreg(struct sam_gmac_s *priv, bool wr, + uint32_t regval, uintptr_t address); +static uint32_t sam_getreg(struct sam_gmac_s *priv, uintptr_t addr); +static void sam_putreg(struct sam_gmac_s *priv, uintptr_t addr, uint32_t val); +#else +# define sam_getreg(priv,addr) getreg32(addr) +# define sam_putreg(priv,addr,val) putreg32(val,addr) +#endif + +/* Buffer management */ + +static uint16_t sam_txinuse(struct sam_gmac_s *priv); +static uint16_t sam_txfree(struct sam_gmac_s *priv); +static int sam_buffer_initialize(struct sam_gmac_s *priv); +static void sam_buffer_free(struct sam_gmac_s *priv); + +/* Common TX logic */ + +static int sam_transmit(struct sam_gmac_s *priv); +static int sam_txpoll(struct net_driver_s *dev); +static void sam_dopoll(struct sam_gmac_s *priv); + +/* Interrupt handling */ + +static int sam_recvframe(struct sam_gmac_s *priv); +static void sam_receive(struct sam_gmac_s *priv); +static void sam_txdone(struct sam_gmac_s *priv); + +static void sam_interrupt_work(FAR void *arg); +static int sam_gmac_interrupt(int irq, void *context, FAR void *arg); + +/* Watchdog timer expirations */ + +static void sam_txtimeout_work(FAR void *arg); +static void sam_txtimeout_expiry(int argc, uint32_t arg, ...); + +static void sam_poll_work(FAR void *arg); +static void sam_poll_expiry(int argc, uint32_t arg, ...); + +/* NuttX callback functions */ + +static int sam_ifup(struct net_driver_s *dev); +static int sam_ifdown(struct net_driver_s *dev); + +static void sam_txavail_work(FAR void *arg); +static int sam_txavail(struct net_driver_s *dev); + +#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) +static unsigned int sam_hashindx(const uint8_t *mac); +static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac); +#endif +#ifdef CONFIG_NET_MCASTGROUP +static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac); +#endif + +#ifdef CONFIG_NETDEV_IOCTL +static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); +#endif + +/* PHY Initialization */ + +#if defined(CONFIG_DEBUG_NET) && defined(CONFIG_DEBUG_INFO) +static void sam_phydump(struct sam_gmac_s *priv); +#else +# define sam_phydump(priv) +#endif + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int sam_phyintenable(struct sam_gmac_s *priv); +#endif +static void sam_enablemdio(struct sam_gmac_s *priv); +static void sam_disablemdio(struct sam_gmac_s *priv); +static int sam_phywait(struct sam_gmac_s *priv); +static int sam_phyreset(struct sam_gmac_s *priv); +static int sam_phyfind(struct sam_gmac_s *priv, uint8_t *phyaddr); +static int sam_phyread(struct sam_gmac_s *priv, uint8_t phyaddr, + uint8_t regaddr, uint16_t *phyval); +static int sam_phywrite(struct sam_gmac_s *priv, uint8_t phyaddr, + uint8_t regaddr, uint16_t phyval); +#ifdef CONFIG_SAMD5E5_GMAC_AUTONEG +static int sam_autonegotiate(struct sam_gmac_s *priv); +#else +static void sam_linkspeed(struct sam_gmac_s *priv); +#endif +static void sam_mdcclock(struct sam_gmac_s *priv); +static int sam_phyinit(struct sam_gmac_s *priv); + +/* GMAC Initialization */ + +static void sam_txreset(struct sam_gmac_s *priv); +static void sam_rxreset(struct sam_gmac_s *priv); +static void sam_gmac_reset(struct sam_gmac_s *priv); +static void sam_macaddress(struct sam_gmac_s *priv); +#ifdef CONFIG_NET_ICMPv6 +static void sam_ipv6multicast(struct sam_gmac_s *priv); +#endif +static int sam_gmac_configure(struct sam_gmac_s *priv); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sam_checkreg + * + * Description: + * Check if the current register access is a duplicate of the preceding. + * + * Input Parameters: + * regval - The value to be written + * address - The address of the register to write to + * + * Returned Value: + * true: This is the first register access of this type. + * flase: This is the same as the preceding register access. + * + ****************************************************************************/ + +#ifdef CONFIG_SAMD5E5_GMAC_REGDEBUG +static bool sam_checkreg(struct sam_gmac_s *priv, bool wr, uint32_t regval, + uintptr_t address) +{ + if (wr == priv->wrlast && /* Same kind of access? */ + regval == priv->vallast && /* Same value? */ + address == priv->addrlast) /* Same address? */ + { + /* Yes, then just keep a count of the number of times we did this. */ + + priv->ntimes++; + return false; + } + else + { + /* Did we do the previous operation more than once? */ + + if (priv->ntimes > 0) + { + /* Yes... show how many times we did it */ + + ninfo("...[Repeats %d times]...\n", priv->ntimes); + } + + /* Save information about the new access */ + + priv->wrlast = wr; + priv->vallast = regval; + priv->addrlast = address; + priv->ntimes = 0; + } + + /* Return true if this is the first time that we have done this operation */ + + return true; +} +#endif + +/**************************************************************************** + * Name: sam_getreg + * + * Description: + * Read any 32-bit register using an absolute + * + ****************************************************************************/ + +#ifdef CONFIG_SAMD5E5_GMAC_REGDEBUG +static uint32_t sam_getreg(struct sam_gmac_s *priv, uintptr_t address) +{ + uint32_t regval = getreg32(address); + + if (sam_checkreg(priv, false, regval, address)) + { + ninfo("%08x->%08x\n", address, regval); + } + + return regval; +} +#endif + +/**************************************************************************** + * Name: sam_putreg + * + * Description: + * Write to any 32-bit register using an absolute address + * + ****************************************************************************/ + +#ifdef CONFIG_SAMD5E5_GMAC_REGDEBUG +static void sam_putreg(struct sam_gmac_s *priv, uintptr_t address, + uint32_t regval) +{ + if (sam_checkreg(priv, true, regval, address)) + { + ninfo("%08x<-%08x\n", address, regval); + } + + putreg32(regval, address); +} +#endif + +/**************************************************************************** + * Function: sam_txinuse + * + * Description: + * Return the number of TX buffers in-use + * + * Input Parameters: + * priv - The GMAC driver state + * + * Returned Value: + * The number of TX buffers in-use + * + ****************************************************************************/ + +static uint16_t sam_txinuse(struct sam_gmac_s *priv) +{ + uint32_t txhead32 = (uint32_t)priv->txhead; + if ((uint32_t)priv->txtail > txhead32) + { + txhead32 += CONFIG_SAMD5E5_GMAC_NTXBUFFERS; + } + + return (uint16_t)(txhead32 - (uint32_t)priv->txtail); +} + +/**************************************************************************** + * Function: sam_txfree + * + * Description: + * Return the number of TX buffers available + * + * Input Parameters: + * priv - The GMAC driver state + * + * Returned Value: + * The number of TX buffers available + * + ****************************************************************************/ + +static uint16_t sam_txfree(struct sam_gmac_s *priv) +{ + /* The number available is equal to the total number of buffers, minus the + * number of buffers in use. Notice that that actual number of buffers is + * the configured size minus 1. + */ + + return (CONFIG_SAMD5E5_GMAC_NTXBUFFERS - 1) - sam_txinuse(priv); +} + +/**************************************************************************** + * Function: sam_buffer_initialize + * + * Description: + * Allocate aligned TX and RX descriptors and buffers. For the case of + * pre-allocated structures, the function degenerates to a few assignements. + * + * Input Parameters: + * priv - The GMAC driver state + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * Called very early in the initialization sequence. + * + ****************************************************************************/ + +static int sam_buffer_initialize(struct sam_gmac_s *priv) +{ +#ifdef CONFIG_SAMD5E5_GMAC_PREALLOCATE + /* Use pre-allocated buffers */ + + priv->txdesc = g_txdesc; + priv->rxdesc = g_rxdesc; + priv->txbuffer = g_txbuffer; + priv->rxbuffer = g_rxbuffer; + +#else + size_t allocsize; + + /* Allocate buffers */ + + allocsize = CONFIG_SAMD5E5_GMAC_NTXBUFFERS * sizeof(struct gmac_txdesc_s); + priv->txdesc = (struct gmac_txdesc_s *)kmm_memalign(8, allocsize); + if (!priv->txdesc) + { + nerr("ERROR: Failed to allocate TX descriptors\n"); + return -ENOMEM; + } + + memset(priv->txdesc, 0, allocsize); + + allocsize = CONFIG_SAMD5E5_GMAC_NRXBUFFERS * sizeof(struct gmac_rxdesc_s); + priv->rxdesc = (struct gmac_rxdesc_s *)kmm_memalign(8, allocsize); + if (!priv->rxdesc) + { + nerr("ERROR: Failed to allocate RX descriptors\n"); + sam_buffer_free(priv); + return -ENOMEM; + } + + memset(priv->rxdesc, 0, allocsize); + + allocsize = CONFIG_SAMD5E5_GMAC_NTXBUFFERS * GMAC_TX_UNITSIZE; + priv->txbuffer = (uint8_t *)kmm_memalign(8, allocsize); + if (!priv->txbuffer) + { + nerr("ERROR: Failed to allocate TX buffer\n"); + sam_buffer_free(priv); + return -ENOMEM; + } + + allocsize = CONFIG_SAMD5E5_GMAC_NRXBUFFERS * GMAC_RX_UNITSIZE; + priv->rxbuffer = (uint8_t *)kmm_memalign(8, allocsize); + if (!priv->rxbuffer) + { + nerr("ERROR: Failed to allocate RX buffer\n"); + sam_buffer_free(priv); + return -ENOMEM; + } + +#endif + + DEBUGASSERT(((uintptr_t)priv->rxdesc & 7) == 0 && + ((uintptr_t)priv->rxbuffer & 7) == 0 && + ((uintptr_t)priv->txdesc & 7) == 0 && + ((uintptr_t)priv->txbuffer & 7) == 0); + return OK; +} + +/**************************************************************************** + * Function: sam_buffer_free + * + * Description: + * Free aligned TX and RX descriptors and buffers. For the case of + * pre-allocated structures, the function does nothing. + * + * Input Parameters: + * priv - The GMAC driver state + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sam_buffer_free(struct sam_gmac_s *priv) +{ +#ifndef CONFIG_SAMD5E5_GMAC_PREALLOCATE + /* Free allocated buffers */ + + if (priv->txdesc) + { + kmm_free(priv->txdesc); + priv->txdesc = NULL; + } + + if (priv->rxdesc) + { + kmm_free(priv->rxdesc); + priv->rxdesc = NULL; + } + + if (priv->txbuffer) + { + kmm_free(priv->txbuffer); + priv->txbuffer = NULL; + } + + if (priv->rxbuffer) + { + kmm_free(priv->rxbuffer); + priv->rxbuffer = NULL; + } +#endif +} + +/**************************************************************************** + * Function: sam_transmit + * + * Description: + * Start hardware transmission. Called either from the TX done interrupt + * handling or from watchdog based polling. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int sam_transmit(struct sam_gmac_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + volatile struct gmac_txdesc_s *txdesc; + uintptr_t virtaddr; + uint32_t regval; + uint32_t status; + + ninfo("d_len: %d txhead: %d txtail: %d\n", + dev->d_len, priv->txhead, priv->txtail); + sam_dumppacket("Transmit packet", dev->d_buf, dev->d_len); + + /* Check parameter */ + + if (dev->d_len > GMAC_TX_UNITSIZE) + { + nerr("ERROR: Packet too big: %d\n", dev->d_len); + return -EINVAL; + } + + /* Pointer to the current TX descriptor */ + + txdesc = &priv->txdesc[priv->txhead]; + + /* If no free TX descriptor, buffer can't be sent */ + + if (sam_txfree(priv) < 1) + { + nerr("ERROR: No free TX descriptors\n"); + return -EBUSY; + } + + /* Setup/Copy data to transmition buffer */ + + if (dev->d_len > 0) + { + /* Driver managed the ring buffer */ + + virtaddr = txdesc->addr; + memcpy((void *)virtaddr, dev->d_buf, dev->d_len); + up_clean_dcache((uint32_t)virtaddr, (uint32_t)virtaddr + dev->d_len); + } + + /* Update TX descriptor status. */ + + status = dev->d_len | GMACTXD_STA_LAST; + if (priv->txhead == CONFIG_SAMD5E5_GMAC_NTXBUFFERS - 1) + { + status |= GMACTXD_STA_WRAP; + } + + /* Update the descriptor status and flush the updated value to RAM */ + + txdesc->status = status; + up_clean_dcache((uint32_t)txdesc, + (uint32_t)txdesc + sizeof(struct gmac_txdesc_s)); + + /* Increment the head index */ + + if (++priv->txhead >= CONFIG_SAMD5E5_GMAC_NTXBUFFERS) + { + priv->txhead = 0; + } + + /* Now start transmission (if it is not already done) */ + + regval = sam_getreg(priv, SAM_GMAC_NCR); + regval |= GMAC_NCR_TSTART; + sam_putreg(priv, SAM_GMAC_NCR, regval); + + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + + (void)wd_start(priv->txtimeout, SAM_TXTIMEOUT, sam_txtimeout_expiry, 1, + (uint32_t)priv); + + /* Set d_len to zero meaning that the d_buf[] packet buffer is again + * available. + */ + + dev->d_len = 0; + + /* If we have no more available TX descriptors, then we must disable the + * RCOMP interrupt to stop further RX processing. Why? Because EACH RX + * packet that is dispatched is also an opportunity to reply with a TX + * packet. So, if we cannot handle an RX packet reply, then we disable + * all RX packet processing. + */ + + if (sam_txfree(priv) < 1) + { + ninfo("Disabling RX interrupts\n"); + sam_putreg(priv, SAM_GMAC_IDR, GMAC_INT_RCOMP); + } + + return OK; +} + +/**************************************************************************** + * Function: sam_txpoll + * + * Description: + * The transmitter is available, check if the network has any outgoing packets ready + * to send. This is a callback from devif_poll(). devif_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send timesout and the interface is reset + * 3. During normal TX polling + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int sam_txpoll(struct net_driver_s *dev) +{ + struct sam_gmac_s *priv = (struct sam_gmac_s *)dev->d_private; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* Look up the destination MAC address and add it to the Ethernet + * header. + */ + +#ifdef CONFIG_NET_IPv4 +#ifdef CONFIG_NET_IPv6 + if (IFF_IS_IPv4(priv->dev.d_flags)) +#endif + { + arp_out(&priv->dev); + } +#endif /* CONFIG_NET_IPv4 */ + +#ifdef CONFIG_NET_IPv6 +#ifdef CONFIG_NET_IPv4 + else +#endif + { + neighbor_out(&priv->dev); + } +#endif /* CONFIG_NET_IPv6 */ + + if (!devif_loopback(&priv->dev)) + { + /* Send the packet */ + + sam_transmit(priv); + + /* Check if there are any free TX descriptors. We cannot perform + * the TX poll if we do not have buffering for another packet. + */ + + if (sam_txfree(priv) == 0) + { + /* We have to terminate the poll if we have no more descriptors + * available for another transfer. + */ + + return -EBUSY; + } + } + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: sam_dopoll + * + * Description: + * The function is called in order to perform an out-of-sequence TX poll. + * This is done: + * + * 1. After completion of a transmission (sam_txdone), + * 2. When new TX data is available (sam_txavail), and + * 3. After a TX timeout to restart the sending process (sam_txtimeout_expiry). + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void sam_dopoll(struct sam_gmac_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + + /* Check if there are any free TX descriptors. We cannot perform the + * TX poll if we do not have buffering for another packet. + */ + + if (sam_txfree(priv) > 0) + { + /* If we have the descriptor, then poll the network for new XMIT data. */ + + (void)devif_poll(dev, sam_txpoll); + } +} + +/**************************************************************************** + * Function: sam_recvframe + * + * Description: + * The function is called when a frame is received. It scans the RX + * descriptors of the received frame and assembles the full packet/ + * + * NOTE: This function will silently discard any packets containing errors. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * OK if a packet was successfully returned; -EAGAIN if there are no + * further packets available + * + * Assumptions: + * - Global interrupts are disabled by interrupt handling logic. + * - The RX descriptor D-cache list has been invalided to force fetching + * from RAM. + * + ****************************************************************************/ + +static int sam_recvframe(struct sam_gmac_s *priv) +{ + volatile struct gmac_rxdesc_s *rxdesc; + struct net_driver_s *dev; + const uint8_t *src; + uint8_t *dest; + uintptr_t physaddr; + uint32_t rxndx; + uint32_t pktlen; + uint16_t copylen; + bool isframe; + + /* Process received RX descriptor. The ownership bit is set by the GMAC + * once it has successfully written a frame to memory. + */ + + dev = &priv->dev; + dev->d_len = 0; + + dest = dev->d_buf; + pktlen = 0; + + rxndx = priv->rxndx; + rxdesc = &priv->rxdesc[rxndx]; + isframe = false; + + /* Invalidate the RX descriptor to force re-fetching from RAM */ + + up_invalidate_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + sizeof(struct gmac_rxdesc_s)); + + ninfo("rxndx: %d\n", rxndx); + + while ((rxdesc->addr & GMACRXD_ADDR_OWNER) != 0) + { + /* The start of frame bit indicates the beginning of a frame. Discard + * any previous fragments. + */ + + if ((rxdesc->status & GMACRXD_STA_SOF) != 0) + { + /* Skip previous fragments */ + + while (rxndx != priv->rxndx) + { + /* Give ownership back to the GMAC */ + + rxdesc = &priv->rxdesc[priv->rxndx]; + rxdesc->addr &= ~(GMACRXD_ADDR_OWNER); + + /* Flush the modified RX descriptor to RAM */ + + up_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + sizeof(struct gmac_rxdesc_s)); + + /* Increment the RX index */ + + if (++priv->rxndx >= CONFIG_SAMD5E5_GMAC_NRXBUFFERS) + { + priv->rxndx = 0; + } + } + + /* Reset the packet data pointer and packet length */ + + dest = dev->d_buf; + pktlen = 0; + + /* Start to gather buffers into the packet buffer */ + + isframe = true; + } + + /* Increment the working index */ + + if (++rxndx >= CONFIG_SAMD5E5_GMAC_NRXBUFFERS) + { + rxndx = 0; + } + + /* Copy data into the packet buffer */ + + if (isframe) + { + if (rxndx == priv->rxndx) + { + nerr("ERROR: No EOF (Invalid of buffers too small)\n"); + do + { + /* Give ownership back to the GMAC */ + + rxdesc = &priv->rxdesc[priv->rxndx]; + rxdesc->addr &= ~(GMACRXD_ADDR_OWNER); + + /* Flush the modified RX descriptor to RAM */ + + up_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + sizeof(struct gmac_rxdesc_s)); + + /* Increment the RX index */ + + if (++priv->rxndx >= CONFIG_SAMD5E5_GMAC_NRXBUFFERS) + { + priv->rxndx = 0; + } + } + while (rxndx != priv->rxndx); + return -EIO; + } + + /* Get the number of bytes to copy from the buffer */ + + copylen = GMAC_RX_UNITSIZE; + if ((pktlen + copylen) > CONFIG_NET_ETH_PKTSIZE) + { + copylen = CONFIG_NET_ETH_PKTSIZE - pktlen; + } + + /* Get the data source. Invalidate the source memory region to + * force reload from RAM. + */ + + physaddr = (uintptr_t)(rxdesc->addr & GMACRXD_ADDR_MASK); + src = (const uint8_t *)physaddr; + + up_invalidate_dcache((uintptr_t)src, (uintptr_t)src + copylen); + + /* And do the copy */ + + memcpy(dest, src, copylen); + dest += copylen; + pktlen += copylen; + + /* If the end of frame has been received, return the data */ + + if ((rxdesc->status & GMACRXD_STA_EOF) != 0) + { + /* Frame size from the GMAC */ + + dev->d_len = (rxdesc->status & GMACRXD_STA_FRLEN_MASK); + ninfo("packet %d-%d (%d)\n", priv->rxndx, rxndx, dev->d_len); + + /* All data have been copied in the application frame buffer, + * release the RX descriptor + */ + + while (priv->rxndx != rxndx) + { + /* Give ownership back to the GMAC */ + + rxdesc = &priv->rxdesc[priv->rxndx]; + rxdesc->addr &= ~(GMACRXD_ADDR_OWNER); + + /* Flush the modified RX descriptor to RAM */ + + up_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + sizeof(struct gmac_rxdesc_s)); + + /* Increment the RX index */ + + if (++priv->rxndx >= CONFIG_SAMD5E5_GMAC_NRXBUFFERS) + { + priv->rxndx = 0; + } + } + + /* Check if the device packet buffer was large enough to accept + * all of the data. + */ + + ninfo("rxndx: %d d_len: %d\n", priv->rxndx, dev->d_len); + + if (pktlen < dev->d_len) + { + nerr("ERROR: Buffer size %d; frame size %d\n", dev->d_len, pktlen); + return -E2BIG; + } + + return OK; + } + } + + /* We have not encount the SOF yet... discard this fragment and keep looking */ + + else + { + /* Give ownership back to the GMAC */ + + rxdesc->addr &= ~(GMACRXD_ADDR_OWNER); + + /* Flush the modified RX descriptor to RAM */ + + up_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + sizeof(struct gmac_rxdesc_s)); + + priv->rxndx = rxndx; + } + + /* Process the next buffer */ + + rxdesc = &priv->rxdesc[rxndx]; + + /* Invalidate the RX descriptor to force re-fetching from RAM */ + + up_invalidate_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + sizeof(struct gmac_rxdesc_s)); + } + + /* isframe indicates that we have found a SOF. If we've received a SOF, + * but not an EOF in the sequential buffers we own, it must mean that we + * have a partial packet. This should only happen if there was a Buffer + * Not Available (BNA) error. When bursts of data come in, quickly + * filling the available buffers, before our interrupts can even service + * them. Eventually, the ring buffer loops back on itself and the + * peripheral sees it cannot write the next fragment of the packet. + * + * In this case, we keep the rxndx at the start of the last frame, since + * the peripheral will finish writing the packet there next. + */ + + if (!isframe) + { + priv->rxndx = rxndx; + } + + ninfo("rxndx: %d\n", priv->rxndx); + return -EAGAIN; +} + +/**************************************************************************** + * Function: sam_receive + * + * Description: + * An interrupt was received indicating the availability of onr or more + * new RX packets in FIFO memory. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void sam_receive(struct sam_gmac_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + + /* Loop while while sam_recvframe() successfully retrieves valid + * GMAC frames. + */ + + while (sam_recvframe(priv) == OK) + { + sam_dumppacket("Received packet", dev->d_buf, dev->d_len); + + /* Check if the packet is a valid size for the network buffer configuration + * (this should not happen) + */ + + if (dev->d_len > CONFIG_NET_ETH_PKTSIZE) + { + nwarn("WARNING: Dropped, Too big: %d\n", dev->d_len); + continue; + } + +#ifdef CONFIG_NET_PKT + /* When packet sockets are enabled, feed the frame into the packet tap */ + + pkt_input(&priv->dev); +#endif + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv4 + if (BUF->type == HTONS(ETHTYPE_IP)) + { + ninfo("IPv4 frame\n"); + + /* Handle ARP on input then give the IPv4 packet to the network + * layer + */ + + arp_ipin(&priv->dev); + ipv4_input(&priv->dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* Update the Ethernet header with the correct MAC address */ + +#ifdef CONFIG_NET_IPv6 + if (IFF_IS_IPv4(priv->dev.d_flags)) +#endif + { + arp_out(&priv->dev); + } +#ifdef CONFIG_NET_IPv6 + else + { + neighbor_out(&priv->dev); + } +#endif + + /* And send the packet */ + + sam_transmit(priv); + } + } + else +#endif +#ifdef CONFIG_NET_IPv6 + if (BUF->type == HTONS(ETHTYPE_IP6)) + { + ninfo("Iv6 frame\n"); + + /* Give the IPv6 packet to the network layer */ + + ipv6_input(&priv->dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* Update the Ethernet header with the correct MAC address */ + +#ifdef CONFIG_NET_IPv4 + if (IFF_IS_IPv4(priv->dev.d_flags)) + { + arp_out(&priv->dev); + } + else +#endif +#ifdef CONFIG_NET_IPv6 + { + neighbor_out(&priv->dev); + } +#endif + + /* And send the packet */ + + sam_transmit(priv); + } + } + else +#endif +#ifdef CONFIG_NET_ARP + if (BUF->type == htons(ETHTYPE_ARP)) + { + ninfo("ARP frame\n"); + + /* Handle ARP packet */ + + arp_arpin(&priv->dev); + + /* If the above function invocation resulted in data that should be + * sent out on the network, the field d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + sam_transmit(priv); + } + } + else +#endif + { + nwarn("WARNING: Dropped, Unknown type: %04x\n", BUF->type); + } + } +} + +/**************************************************************************** + * Function: sam_txdone + * + * Description: + * An interrupt was received indicating that one or more frames have + * completed transmission. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void sam_txdone(struct sam_gmac_s *priv) +{ + struct gmac_txdesc_s *txdesc; + + /* Are there any outstanding transmissions? Loop until either (1) all of + * the TX descriptors have been examined, or (2) until we encounter the + * first descriptor that is still in use by the hardware. + */ + + while (priv->txhead != priv->txtail) + { + /* Yes.. check the next buffer at the tail of the list */ + + txdesc = &priv->txdesc[priv->txtail]; + up_invalidate_dcache((uintptr_t)txdesc, + (uintptr_t)txdesc + sizeof(struct gmac_txdesc_s)); + + /* Is this TX descriptor still in use? */ + + if ((txdesc->status & GMACTXD_STA_USED) == 0) + { + /* Yes.. the descriptor is still in use. However, I have seen a + * case (only repeatable on start-up) where the USED bit is never + * set. Yikes! If we have encountered the first still busy + * descriptor, then we should also have TQBD equal to the descriptor + * address. If it is not, then treat is as used anyway. + */ + +#warning REVISIT + if (priv->txtail == 0 && + (uintptr_t)txdesc != sam_getreg(priv, SAM_GMAC_TBQB)) + { + txdesc->status = (uint32_t)GMACTXD_STA_USED; + up_clean_dcache((uintptr_t)txdesc, + (uintptr_t)txdesc + sizeof(struct gmac_txdesc_s)); + } + else + { + /* Otherwise, the descriptor is truly in use. Break out of the + * loop now. + */ + + break; + } + } + + /* Increment the tail index */ + + if (++priv->txtail >= CONFIG_SAMD5E5_GMAC_NTXBUFFERS) + { + /* Wrap to the beginning of the TX descriptor list */ + + priv->txtail = 0; + } + + /* At least one TX descriptor is available. Re-enable RX interrupts. + * RX interrupts may previously have been disabled when we ran out of + * TX descriptors (see comments in sam_transmit()). + */ + + sam_putreg(priv, SAM_GMAC_IER, GMAC_INT_RCOMP); + } + + /* Then poll the network for new XMIT data */ + + sam_dopoll(priv); +} + +/**************************************************************************** + * Function: sam_interrupt_work + * + * Description: + * Perform interrupt related work from the worker thread + * + * Input Parameters: + * arg - The argument passed when work_queue() was called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +static void sam_interrupt_work(FAR void *arg) +{ + FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg; + uint32_t isr; + uint32_t rsr; + uint32_t tsr; + uint32_t imr; + uint32_t regval; + uint32_t pending; + uint32_t clrbits; + + /* Process pending Ethernet interrupts */ + + net_lock(); + isr = sam_getreg(priv, SAM_GMAC_ISR); + rsr = sam_getreg(priv, SAM_GMAC_RSR); + tsr = sam_getreg(priv, SAM_GMAC_TSR); + imr = sam_getreg(priv, SAM_GMAC_IMR); + + pending = isr & ~(imr | GMAC_INT_UNUSED); + ninfo("isr: %08x pending: %08x\n", isr, pending); + + /* Check for the completion of a transmission. This should be done before + * checking for received data (because receiving can cause another transmission + * before we had a chance to handle the last one). + * + * ISR:TCOMP is set when a frame has been transmitted. Cleared on read. + * TSR:COMP is set when a frame has been transmitted. Cleared by writing a + * one to this bit. + */ + + if ((pending & GMAC_INT_TCOMP) != 0 || (tsr & GMAC_TSR_TXCOMP) != 0) + { + /* A frame has been transmitted */ + + clrbits = GMAC_TSR_TXCOMP; + + /* Check for Retry Limit Exceeded (RLE) */ + + if ((tsr & GMAC_TSR_RLE) != 0) + { + /* Status RLE & Number of discarded buffers */ + + clrbits = GMAC_TSR_RLE | sam_txinuse(priv); + sam_txreset(priv); + + nerr("ERROR: Retry Limit Exceeded TSR: %08x\n", tsr); + + regval = sam_getreg(priv, SAM_GMAC_NCR); + regval |= GMAC_NCR_TXEN; + sam_putreg(priv, SAM_GMAC_NCR, regval); + } + + /* Check Collision Occurred (COL) */ + + if ((tsr & GMAC_TSR_COL) != 0) + { + nerr("ERROR: Collision occurred TSR: %08x\n", tsr); + clrbits |= GMAC_TSR_COL; + } + + /* Check for Transmit Frame Corruption due to AHB error (TFC) */ + + if ((tsr & GMAC_TSR_TFC) != 0) + { + nerr("ERROR: Buffers exhausted mid-frame TSR: %08x\n", tsr); + clrbits |= GMAC_TSR_TFC; + } + + /* Check for Transmit Underrun (UND) + * + * ISR:UND is set transmit DMA was not able to read data from memory, + * either because the bus was not granted in time, because a not + * OK hresp(bus error) was returned or because a used bit was read + * midway through frame transmission. If this occurs, the + * transmitter forces bad CRC. Cleared by writing a one to this bit. + */ + + if ((tsr & GMAC_TSR_UND) != 0) + { + nerr("ERROR: Transmit Underrun TSR: %08x\n", tsr); + clrbits |= GMAC_TSR_UND; + } + + /* Check for HRESP not OK */ + + if ((tsr & GMAC_TSR_HRESP) != 0) + { + nerr("ERROR: HRESP not OK: %08x\n", tsr); + clrbits |= GMAC_TSR_HRESP; + } + + /* Check for Late Collitions (LCO) */ + + if ((tsr & GMAC_TSR_LCO) != 0) + { + nerr("ERROR: Late collision: %08x\n", tsr); + clrbits |= GMAC_TSR_LCO; + } + + /* Clear status */ + + sam_putreg(priv, SAM_GMAC_TSR, clrbits); + + /* And handle the TX done event */ + + sam_txdone(priv); + } + + /* Check for the receipt of an RX packet. + * + * RXCOMP indicates that a packet has been received and stored in memory. + * The RXCOMP bit is cleared whent he interrupt status register was read. + * RSR:REC indicates that one or more frames have been received and placed + * in memory. This indication is cleared by writing a one to this bit. + */ + + if ((pending & GMAC_INT_RCOMP) != 0 || (rsr & GMAC_RSR_REC) != 0) + { + clrbits = GMAC_RSR_REC; + + /* Check for Receive Overrun. + * + * RSR:RXOVR will be set if the RX FIFO is not able to store the + * receive frame due to a FIFO overflow, or if the receive status + * was not taken at the end of the frame. This bit is also set in + * DMA packet buffer mode if the packet buffer overflows. For DMA + * operation, the buffer will be recovered if an overrun occurs. This + * bit is cleared when set to 1. + */ + + if ((rsr & GMAC_RSR_RXOVR) != 0) + { + nerr("ERROR: Receiver overrun RSR: %08x\n", rsr); + clrbits |= GMAC_RSR_RXOVR; + } + + /* Check for buffer not available (BNA) + * + * RSR:BNA means that an attempt was made to get a new buffer and the + * pointer indicated that it was owned by the processor. The DMA will + * reread the pointer each time an end of frame is received until a + * valid pointer is found. This bit is set following each descriptor + * read attempt that fails, even if consecutive pointers are + * unsuccessful and software has in the mean time cleared the status + * flag. Cleared by writing a one to this bit. + */ + + if ((rsr & GMAC_RSR_BNA) != 0) + { + nerr("ERROR: Buffer not available RSR: %08x\n", rsr); + clrbits |= GMAC_RSR_BNA; + } + + /* Check for HRESP not OK (HNO) */ + + if ((rsr & GMAC_RSR_HNO) != 0) + { + nerr("ERROR: HRESP not OK: %08x\n", rsr); + clrbits |= GMAC_RSR_HNO; + } + + /* Clear status */ + + sam_putreg(priv, SAM_GMAC_RSR, clrbits); + + /* Handle the received packet */ + + sam_receive(priv); + } + +#ifdef CONFIG_DEBUG_NET + /* Check for PAUSE Frame received (PFRE). + * + * ISR:PFRE indicates that a pause frame has been received. Cleared on a read. + */ + + if ((pending & GMAC_INT_PFNZ) != 0) + { + nwarn("WARNING: Pause frame received\n"); + } + + /* Check for Pause Time Zero (PTZ) + * + * ISR:PTZ is set Pause Time Zero + */ + + if ((pending & GMAC_INT_PTZ) != 0) + { + nwarn("WARNING: Pause TO!\n"); + } +#endif + + net_unlock(); + + /* Re-enable Ethernet interrupts */ + + up_enable_irq(SAM_IRQ_GMAL); +} + +/**************************************************************************** + * Function: sam_gmac_interrupt + * + * Description: + * Hardware interrupt handler + * + * Input Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + * Assumptions: + * + ****************************************************************************/ + +static int sam_gmac_interrupt(int irq, void *context, FAR void *arg) +{ + struct sam_gmac_s *priv = &g_gmac; + uint32_t tsr; + + /* Disable further Ethernet interrupts. Because Ethernet interrupts are + * also disabled if the TX timeout event occurs, there can be no race + * condition here. + */ + + up_disable_irq(SAM_IRQ_GMAL); + + /* Check for the completion of a transmission. Careful: + * + * ISR:TCOMP is set when a frame has been transmitted. Cleared on read (so + * we cannot read it here). + * TSR:TXCOMP is set when a frame has been transmitted. Cleared by writing a + * one to this bit. + */ + + tsr = sam_getreg(priv, SAM_GMAC_TSR_OFFSET); + if ((tsr & GMAC_TSR_TXCOMP) != 0) + { + /* If a TX transfer just completed, then cancel the TX timeout so + * there will be do race condition between any subsequent timeout + * expiration and the deferred interrupt processing. + */ + + wd_cancel(priv->txtimeout); + } + + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(ETHWORK, &priv->irqwork, sam_interrupt_work, priv, 0); + return OK; +} + +/**************************************************************************** + * Function: sam_txtimeout_work + * + * Description: + * Perform TX timeout related work from the worker thread + * + * Input Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +static void sam_txtimeout_work(FAR void *arg) +{ + FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg; + + nerr("ERROR: Timeout!\n"); + + /* Reset the hardware. Just take the interface down, then back up again. */ + + net_lock(); + sam_ifdown(&priv->dev); + sam_ifup(&priv->dev); + + /* Then poll the network for new XMIT data */ + + sam_dopoll(priv); + net_unlock(); +} + +/**************************************************************************** + * Function: sam_txtimeout_expiry + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the hardware and start again. + * + * Input Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void sam_txtimeout_expiry(int argc, uint32_t arg, ...) +{ + FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg; + + /* Disable further Ethernet interrupts. This will prevent some race + * conditions with interrupt work. There is still a potential race + * condition with interrupt work that is already queued and in progress. + */ + + up_disable_irq(SAM_IRQ_GMAL); + + /* Schedule to perform the TX timeout processing on the worker thread. */ + + work_queue(ETHWORK, &priv->irqwork, sam_txtimeout_work, priv, 0); +} + +/**************************************************************************** + * Function: sam_poll_work + * + * Description: + * Perform periodic polling from the worker thread + * + * Input Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +static void sam_poll_work(FAR void *arg) +{ + FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg; + struct net_driver_s *dev = &priv->dev; + + /* Check if there are any free TX descriptors. We cannot perform the + * TX poll if we do not have buffering for another packet. + */ + + net_lock(); + if (sam_txfree(priv) > 0) + { + /* Update TCP timing states and poll the network for new XMIT data. */ + + (void)devif_timer(dev, sam_txpoll); + } + + /* Setup the watchdog poll timer again */ + + (void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv); + net_unlock(); +} + +/**************************************************************************** + * Function: sam_poll_expiry + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Input Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void sam_poll_expiry(int argc, uint32_t arg, ...) +{ + FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg; + + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(ETHWORK, &priv->pollwork, sam_poll_work, priv, 0); +} + +/**************************************************************************** + * Function: sam_ifup + * + * Description: + * NuttX Callback: Bring up the GMAC interface when an IP address is + * provided + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int sam_ifup(struct net_driver_s *dev) +{ + struct sam_gmac_s *priv = (struct sam_gmac_s *)dev->d_private; + int ret; + + ninfo("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24); + + /* Configure the GMAC interface for normal operation. */ + + ninfo("Initialize the GMAC\n"); + sam_gmac_configure(priv); + + /* Set the MAC address (should have been configured while we were down) */ + + sam_macaddress(priv); + +#ifdef CONFIG_NET_ICMPv6 + /* Set up IPv6 multicast address filtering */ + + sam_ipv6multicast(priv); +#endif + + /* Initialize for PHY access */ + + ret = sam_phyinit(priv); + if (ret < 0) + { + nerr("ERROR: sam_phyinit failed: %d\n", ret); + return ret; + } + +#ifdef CONFIG_SAMD5E5_GMAC_AUTONEG + /* Auto Negotiate, working in RMII mode */ + + ret = sam_autonegotiate(priv); + if (ret < 0) + { + nerr("ERROR: sam_autonegotiate failed: %d\n", ret); + return ret; + } +#else + /* Just force the configured link speed */ + + sam_linkspeed(priv); +#endif + + /* Enable normal MAC operation */ + + ninfo("Enable normal operation\n"); + + /* Set and activate a timer process */ + + (void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, (uint32_t)priv); + + /* Enable the GMAC interrupt */ + + priv->ifup = true; + up_enable_irq(SAM_IRQ_GMAL); + return OK; +} + +/**************************************************************************** + * Function: sam_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int sam_ifdown(struct net_driver_s *dev) +{ + struct sam_gmac_s *priv = (struct sam_gmac_s *)dev->d_private; + irqstate_t flags; + + ninfo("Taking the network down\n"); + + /* Disable the GMAC interrupt */ + + flags = enter_critical_section(); + up_disable_irq(SAM_IRQ_GMAL); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(priv->txpoll); + wd_cancel(priv->txtimeout); + + /* Put the GMAC in its reset, non-operational state. This should be + * a known configuration that will guarantee the sam_ifup() always + * successfully brings the interface back up. + */ + + sam_gmac_reset(priv); + + /* Mark the device "down" */ + + priv->ifup = false; + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Function: sam_txavail_work + * + * Description: + * Perform an out-of-cycle poll on the worker thread. + * + * Input Parameters: + * arg - Reference to the NuttX driver state structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * Called on the higher priority worker thread. + * + ****************************************************************************/ + +static void sam_txavail_work(FAR void *arg) +{ + FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg; + + ninfo("ifup: %d\n", priv->ifup); + + /* Ignore the notification if the interface is not yet up */ + + net_lock(); + if (priv->ifup) + { + /* Poll the network for new XMIT data */ + + sam_dopoll(priv); + } + + net_unlock(); +} + +/**************************************************************************** + * Function: sam_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int sam_txavail(struct net_driver_s *dev) +{ + FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)dev->d_private; + + /* Is our single work structure available? It may not be if there are + * pending interrupt actions and we will have to ignore the Tx + * availability action. + */ + + if (work_available(&priv->pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(ETHWORK, &priv->pollwork, sam_txavail_work, priv, 0); + } + + return OK; +} + +/**************************************************************************** + * Name: sam_hashindx + * + * Description: + * Cacuclate the hash address register index. The hash address register + * is 64 bits long and takes up two locations in the memory map. The + * destination address is reduced to a 6-bit index into the 64-bit Hash + * Register using the following hash function: The hash function is an XOR + * of every sixth bit of the destination address. + * + * ndx:05 = da:05 ^ da:11 ^ da:17 ^ da:23 ^ da:29 ^ da:35 ^ da:41 ^ da:47 + * ndx:04 = da:04 ^ da:10 ^ da:16 ^ da:22 ^ da:28 ^ da:34 ^ da:40 ^ da:46 + * ndx:03 = da:03 ^ da:09 ^ da:15 ^ da:21 ^ da:27 ^ da:33 ^ da:39 ^ da:45 + * ndx:02 = da:02 ^ da:08 ^ da:14 ^ da:20 ^ da:26 ^ da:32 ^ da:38 ^ da:44 + * ndx:01 = da:01 ^ da:07 ^ da:13 ^ da:19 ^ da:25 ^ da:31 ^ da:37 ^ da:43 + * ndx:00 = da:00 ^ da:06 ^ da:12 ^ da:18 ^ da:24 ^ da:30 ^ da:36 ^ da:42 + * + * Where da:00 represents the least significant bit of the first byte + * received and da:47 represents the most significant bit of the last byte + * received. + * + * Input Parameters: + * mac - The multicast address to be hashed + * + * Returned Value: + * The 6-bit hash table index + * + ****************************************************************************/ + +#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) +static unsigned int sam_hashindx(const uint8_t *mac) +{ + unsigned int ndx; + + /* Isolate: mac[0] + * ... 05 04 03 02 01 00] + */ + + ndx = mac[0]; + + /* Isolate: mac[1] mac[0] + * ...11 10 09 08] [07 06 ... + * + * Accumulate: 05 04 03 02 01 00 + * XOR: 11 10 09 08 07 06 + */ + + ndx ^= (mac[1] << 2) | (mac[0] >> 6); + + /* Isolate: mac[2] mac[1] + * ... 17 16] [15 14 13 12 ... + * + * Accumulate: 05 04 03 02 01 00 + * XOR: 11 10 09 08 07 06 + * XOR: 17 16 15 14 13 12 + */ + + ndx ^= (mac[2] << 4) | (mac[1] >> 4); + + /* Isolate: mac[2] + * [23 22 21 20 19 18 ... + * + * Accumulate: 05 04 03 02 01 00 + * XOR: 11 10 09 08 07 06 + * XOR: 17 16 15 14 13 12 + * XOR: 23 22 21 20 19 18 + */ + + ndx ^= (mac[2] >> 2); + + /* Isolate: mac[3] + * ... 29 28 27 26 25 24] + * + * Accumulate: 05 04 03 02 01 00 + * XOR: 11 10 09 08 07 06 + * XOR: 17 16 15 14 13 12 + * XOR: 23 22 21 20 19 18 + * XOR: 29 28 27 26 25 24 + */ + + ndx ^= mac[3]; + + /* Isolate: mac[4] mac[3] + * ... 35 34 33 32] [31 30 ... + * + * Accumulate: 05 04 03 02 01 00 + * XOR: 11 10 09 08 07 06 + * XOR: 17 16 15 14 13 12 + * XOR: 23 22 21 20 19 18 + * XOR: 29 28 27 26 25 24 + * XOR: 35 34 33 32 31 30 + */ + + ndx ^= (mac[4] << 2) | (mac[3] >> 6); + + /* Isolate: mac[5] mac[4] + * ... 41 40] [39 38 37 36 ... + * + * Accumulate: 05 04 03 02 01 00 + * XOR: 11 10 09 08 07 06 + * XOR: 17 16 15 14 13 12 + * XOR: 23 22 21 20 19 18 + * XOR: 29 28 27 26 25 24 + * XOR: 35 34 33 32 31 30 + * XOR: 41 40 39 38 37 36 + */ + + ndx ^= (mac[5] << 4) | (mac[4] >> 4); + + /* Isolate: mac[5] + * [47 46 45 44 43 42 ... + * + * Accumulate: 05 04 03 02 01 00 + * XOR: 11 10 09 08 07 06 + * XOR: 17 16 15 14 13 12 + * XOR: 23 22 21 20 19 18 + * XOR: 29 28 27 26 25 24 + * XOR: 35 34 33 32 31 30 + * XOR: 41 40 39 38 37 36 + * XOR: 47 46 45 44 43 42 + */ + + ndx ^= (mac[5] >> 2); + + /* Mask out the garbage bits and return the 6-bit index */ + + return ndx & 0x3f; +} +#endif /* CONFIG_NET_MCASTGROUP || CONFIG_NET_ICMPv6 */ + +/**************************************************************************** + * Function: sam_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_MCASTGROUP +static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac) +{ + struct sam_gmac_s *priv = (struct sam_gmac_s *)dev->d_private; + uintptr_t regaddr; + uint32_t regval; + unsigned int ndx; + unsigned int bit; + UNUSED(priv); + + ninfo("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + /* Calculate the 6-bit has table index */ + + ndx = sam_hashindx(mac); + + /* Add the multicast address to the hardware multicast hash table */ + + if (ndx >= 32) + { + regaddr = SAM_GMAC_HRT; /* Hash Register Top [63:32] Register */ + bit = 1 << (ndx - 32); /* Bit 0-31 */ + } + else + { + regaddr = SAM_GMAC_HRB; /* Hash Register Bottom [31:0] Register */ + bit = 1 << ndx; /* Bit 0-31 */ + } + + regval = sam_getreg(priv, regaddr); + regval |= bit; + sam_putreg(priv, regaddr, regval); + + /* The unicast hash enable and the multicast hash enable bits in the + * Network Configuration Register enable the reception of hash matched + * frames: + * + * - A multicast match will be signalled if the multicast hash enable bit + * is set, da:00 is logic 1 and the hash index points to a bit set in + * the Hash Register. + * - A unicast match will be signalled if the unicast hash enable bit is + * set, da:00 is logic 0 and the hash index points to a bit set in the + * Hash Register. + */ + + regval = sam_getreg(priv, SAM_GMAC_NCFGR); + regval &= ~GMAC_NCFGR_UNIHEN; /* Disable unicast matching */ + regval |= GMAC_NCFGR_MTIHEN; /* Enable multicast matching */ + sam_putreg(priv, SAM_GMAC_NCFGR, regval); + + return OK; +} +#endif + +/**************************************************************************** + * Function: sam_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_MCASTGROUP +static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac) +{ + struct sam_gmac_s *priv = (struct sam_gmac_s *)dev->d_private; + uint32_t regval; + unsigned int regaddr1; + unsigned int regaddr2; + unsigned int ndx; + unsigned int bit; + UNUSED(priv); + + ninfo("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + /* Calculate the 6-bit has table index */ + + ndx = sam_hashindx(mac); + + /* Remove the multicast address to the hardware multicast hast table */ + + if (ndx >= 32) + { + regaddr1 = SAM_GMAC_HRT; /* Hash Register Top [63:32] Register */ + regaddr2 = SAM_GMAC_HRB; /* Hash Register Bottom [31:0] Register */ + bit = 1 << (ndx - 32); /* Bit 0-31 */ + } + else + { + regaddr1 = SAM_GMAC_HRB; /* Hash Register Bottom [31:0] Register */ + regaddr2 = SAM_GMAC_HRT; /* Hash Register Top [63:32] Register */ + bit = 1 << ndx; /* Bit 0-31 */ + } + + regval = sam_getreg(priv, regaddr1); + regval &= ~bit; + sam_putreg(priv, regaddr1, regval); + + /* The unicast hash enable and the multicast hash enable bits in the + * Network Configuration Register enable the reception of hash matched + * frames: + * + * - A multicast match will be signalled if the multicast hash enable bit + * is set, da:00 is logic 1 and the hash index points to a bit set in + * the Hash Register. + * - A unicast match will be signalled if the unicast hash enable bit is + * set, da:00 is logic 0 and the hash index points to a bit set in the + * Hash Register. + */ + + /* Are all multicast address matches disabled? */ + + if (regval == 0 && sam_getreg(priv, regaddr2) == 0) + { + /* Yes.. disable all address matching */ + + regval = sam_getreg(priv, SAM_GMAC_NCFGR); + regval &= ~(GMAC_NCFGR_UNIHEN | GMAC_NCFGR_MTIHEN); + sam_putreg(priv, SAM_GMAC_NCFGR, regval); + } + + return OK; +} +#endif + +/**************************************************************************** + * Function: sam_ioctl + * + * Description: + * Handles driver ioctl calls: + * + * SIOCMIINOTIFY - Set up to received notifications from PHY interrupting + * events. + * + * SIOCGMIIPHY, SIOCGMIIREG, and SIOCSMIIREG: + * Executes the SIOCxMIIxxx command and responds using the request struct + * that must be provided as its 2nd parameter. + * + * When called with SIOCGMIIPHY it will get the PHY address for the device + * and write it to the req->phy_id field of the request struct. + * + * When called with SIOCGMIIREG it will read a register of the PHY that is + * specified using the req->reg_no struct field and then write its output + * to the req->val_out field. + * + * When called with SIOCSMIIREG it will write to a register of the PHY that + * is specified using the req->reg_no struct field and use req->val_in as + * its input. + * + * Input Parameters: + * dev - Ethernet device structure + * cmd - SIOCxMIIxxx command code + * arg - Request structure also used to return values + * + * Returned Value: Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_IOCTL +static int sam_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) +{ +#ifdef CONFIG_NETDEV_PHY_IOCTL + struct sam_gmac_s *priv = (struct sam_gmac_s *)dev->d_private; +#endif + int ret; + + switch (cmd) + { +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ + { + struct mii_ioctl_notify_s *req = + (struct mii_ioctl_notify_s *)((uintptr_t)arg); + + ret = phy_notify_subscribe(dev->d_ifname, req->pid, &req->event); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = sam_phyintenable(priv); + } + } + break; +#endif + + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = priv->phyaddr; + ret = OK; + } + break; + + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + + /* Enable the management port */ + + sam_enablemdio(priv); + + /* Read from the requested register */ + + ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); + + /* Disable the management port */ + + sam_disablemdio(priv); + } + break; + + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + + /* Enable the management port */ + + sam_enablemdio(priv); + + /* Write to the requested register */ + + ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); + + /* Disable the management port */ + + sam_disablemdio(priv); + } + break; +#endif /* CONFIG_NETDEV_PHY_IOCTL */ + + default: + ret = -ENOTTY; + break; + } + + return ret; +} +#endif /* CONFIG_NETDEV_IOCTL */ + +/**************************************************************************** + * Function: sam_phydump + * + * Description: + * Dump the contents of PHY registers + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_NET) && defined(CONFIG_DEBUG_INFO) +static void sam_phydump(struct sam_gmac_s *priv) +{ + uint16_t phyval; + + /* Enable management port */ + + sam_enablemdio(priv); + + ninfo("GMII Registers (Address %02x)\n", priv->phyaddr); + sam_phyread(priv, priv->phyaddr, GMII_MCR, &phyval); + ninfo(" MCR: %04x\n", phyval); + sam_phyread(priv, priv->phyaddr, GMII_MSR, &phyval); + ninfo(" MSR: %04x\n", phyval); + sam_phyread(priv, priv->phyaddr, GMII_ADVERTISE, &phyval); + ninfo(" ADVERTISE: %04x\n", phyval); + sam_phyread(priv, priv->phyaddr, GMII_LPA, &phyval); + ninfo(" LPR: %04x\n", phyval); + sam_phyread(priv, priv->phyaddr, GMII_ESTATUS, &phyval); + ninfo(" ESTATUS: %04x\n", phyval); + + /* Disable management port */ + + sam_disablemdio(priv); +} +#endif + +/**************************************************************************** + * Function: sam_phyintenable + * + * Description: + * Enable link up/down PHY interrupts. The interrupt protocol is like this: + * + * - Interrupt status is cleared when the interrupt is enabled. + * - Interrupt occurs. Interrupt is disabled (at the processor level) when + * is received. + * - Interrupt status is cleared when the interrupt is re-enabled. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno (-ETIMEDOUT) on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int sam_phyintenable(struct sam_gmac_s *priv) +{ +#if defined(SAMD5E5_GMAC_PHY_KSZ90x1) + uint16_t phyval; + int ret; + + /* Enable the management port */ + + sam_enablemdio(priv); + + /* Read the interrupt status register in order to clear any pending + * interrupts + */ + + ret = sam_phyread(priv, priv->phyaddr, GMII_KSZ90x1_ICS, &phyval); + if (ret == OK) + { + /* Enable link up/down interrupts */ + + ret = sam_phywrite(priv, priv->phyaddr, GMII_KSZ90x1_ICS, + (GMII_KSZ90x1_INT_LDEN | GMII_KSZ90x1_INT_LUEN)); + } + + /* Disable the management port */ + + sam_disablemdio(priv); + return ret; + +#else +# warning Missing logic + return -ENOSYS; +#endif +} +#endif + +/**************************************************************************** + * Function: sam_enablemdio + * + * Description: + * Enable the management port + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sam_enablemdio(struct sam_gmac_s *priv) +{ + uint32_t regval; + uint32_t enables; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_GMAC_NCR); + enables = regval & (GMAC_NCR_RXEN | GMAC_NCR_TXEN); + + regval &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN); + regval |= GMAC_NCR_MPE; + sam_putreg(priv, SAM_GMAC_NCR, regval); + + regval |= enables; + sam_putreg(priv, SAM_GMAC_NCR, regval); +} + +/**************************************************************************** + * Function: sam_disablemdio + * + * Description: + * Disable the management port + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sam_disablemdio(struct sam_gmac_s *priv) +{ + uint32_t regval; + uint32_t enables; + + /* Disable management port */ + + regval = sam_getreg(priv, SAM_GMAC_NCR); + enables = regval & (GMAC_NCR_RXEN | GMAC_NCR_TXEN); + + regval &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN); + sam_putreg(priv, SAM_GMAC_NCR, regval); + + regval &= ~GMAC_NCR_MPE; + sam_putreg(priv, SAM_GMAC_NCR, regval); + + regval |= enables; + sam_putreg(priv, SAM_GMAC_NCR, regval); +} + +/**************************************************************************** + * Function: sam_phywait + * + * Description: + * Wait for the PHY to become IDLE + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno (-ETIMEDOUT) on failure. + * + ****************************************************************************/ + +static int sam_phywait(struct sam_gmac_s *priv) +{ + volatile unsigned int retries; + + /* Loop for the configured number of attempts */ + + for (retries = 0; retries < PHY_RETRY_MAX; retries++) + { + /* Is the PHY IDLE */ + + if ((sam_getreg(priv, SAM_GMAC_NSR) & GMAC_NSR_IDLE) != 0) + { + return OK; + } + } + + return -ETIMEDOUT; +} + +/**************************************************************************** + * Function: sam_phyreset + * + * Description: + * Reset the PHY + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int sam_phyreset(struct sam_gmac_s *priv) +{ + uint16_t mcr; + int timeout; + int ret; + + ninfo(" sam_phyreset\n"); + + /* Enable management port */ + + sam_enablemdio(priv); + + /* Reset the PHY */ + + ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, GMII_MCR_RESET); + if (ret < 0) + { + nerr("ERROR: sam_phywrite failed: %d\n", ret); + } + + /* Wait for the PHY reset to complete */ + + ret = -ETIMEDOUT; + for (timeout = 0; timeout < 10; timeout++) + { + mcr = GMII_MCR_RESET; + int result = sam_phyread(priv, priv->phyaddr, GMII_MCR, &mcr); + if (result < 0) + { + nerr("ERROR: Failed to read the MCR register: %d\n", ret); + ret = result; + } + else if ((mcr & GMII_MCR_RESET) == 0) + { + ret = OK; + break; + } + } + + /* Disable management port */ + + sam_disablemdio(priv); + return ret; +} + +/**************************************************************************** + * Function: sam_phyfind + * + * Description: + * Verify the PHY address and, if it is bad, try to one that works. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int sam_phyfind(struct sam_gmac_s *priv, uint8_t *phyaddr) +{ + uint16_t phyval; + uint8_t candidate; + unsigned int offset; + int ret = -ESRCH; + + ninfo("Find a valid PHY address\n"); + + /* Enable management port */ + + sam_enablemdio(priv); + + /* Check initial candidate address */ + + candidate = *phyaddr; + + ret = sam_phyread(priv, candidate, GMII_PHYID1, &phyval); + if (ret == OK && phyval == GMII_OUI_MSB) + { + *phyaddr = candidate; + ret = OK; + } + + /* The current address does not work... try another */ + + else + { + nerr("ERROR: sam_phyread failed for PHY address %02x: %d\n", + candidate, ret); + + for (offset = 0; offset < 32; offset++) + { + /* Get the next candidate PHY address */ + + candidate = (candidate + 1) & 0x1f; + + /* Try reading the PHY ID from the candidate PHY address */ + + ret = sam_phyread(priv, candidate, GMII_PHYID1, &phyval); + if (ret == OK && phyval == GMII_OUI_MSB) + { + ret = OK; + break; + } + } + } + + if (ret == OK) + { + ninfo(" PHYID1: %04x PHY addr: %d\n", phyval, candidate); + *phyaddr = candidate; + } + + /* Disable management port */ + + sam_disablemdio(priv); + return ret; +} + +/**************************************************************************** + * Function: sam_phyread + * + * Description: + * Read a PHY register. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * phyaddr - The PHY device address + * regaddr - The PHY register address + * phyval - The location to return the 16-bit PHY register value. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int sam_phyread(struct sam_gmac_s *priv, uint8_t phyaddr, + uint8_t regaddr, uint16_t *phyval) +{ + uint32_t regval; + int ret; + + /* Make sure that the PHY is idle */ + + ret = sam_phywait(priv); + if (ret < 0) + { + nerr("ERROR: sam_phywait failed: %d\n", ret); + return ret; + } + + /* Write the PHY Maintenance register */ + + regval = GMAC_MAN_DATA(0) | GMAC_MAN_WTN | GMAC_MAN_REGA(regaddr) | + GMAC_MAN_PHYA(phyaddr) | GMAC_MAN_READ | GMAC_MAN_CLTTO; + sam_putreg(priv, SAM_GMAC_MAN, regval); + + /* Wait until the PHY is again idle */ + + ret = sam_phywait(priv); + if (ret < 0) + { + nerr("ERROR: sam_phywait failed: %d\n", ret); + return ret; + } + + /* Return the PHY data */ + + *phyval = (uint16_t)(sam_getreg(priv, SAM_GMAC_MAN) & GMAC_MAN_DATA_MASK); + return OK; +} + +/**************************************************************************** + * Function: sam_phywrite + * + * Description: + * Write to a PHY register. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * phyaddr - The PHY device address + * regaddr - The PHY register address + * phyval - The 16-bit value to write to the PHY register. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int sam_phywrite(struct sam_gmac_s *priv, uint8_t phyaddr, + uint8_t regaddr, uint16_t phyval) +{ + uint32_t regval; + int ret; + + /* Make sure that the PHY is idle */ + + ret = sam_phywait(priv); + if (ret < 0) + { + nerr("ERROR: sam_phywait failed: %d\n", ret); + return ret; + } + + /* Write the PHY Maintenance register */ + + regval = GMAC_MAN_DATA(phyval) | GMAC_MAN_WTN | GMAC_MAN_REGA(regaddr) | + GMAC_MAN_PHYA(phyaddr) | GMAC_MAN_WRITE | GMAC_MAN_CLTTO; + sam_putreg(priv, SAM_GMAC_MAN, regval); + + /* Wait until the PHY is again IDLE */ + + ret = sam_phywait(priv); + if (ret < 0) + { + nerr("ERROR: sam_phywait failed: %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Function: sam_autonegotiate + * + * Description: + * Autonegotiate speed and duplex. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_SAMD5E5_GMAC_AUTONEG +static int sam_autonegotiate(struct sam_gmac_s *priv) +{ + uint32_t regval; + uint32_t ncr; + uint32_t linkmode; + uint16_t phyval; + uint16_t phyid1; + uint16_t phyid2; + uint16_t advertise; + uint16_t lpa; + int timeout; + int ret; + + /* Enable management port */ + + sam_enablemdio(priv); + + /* Read the MS bits of the OUI from Pthe PHYID1 register */ + + ret = sam_phyread(priv, priv->phyaddr, GMII_PHYID1, &phyid1); + if (ret < 0) + { + nerr("ERROR: Failed to read PHYID1 register\n"); + goto errout; + } + + ninfo("PHYID1: %04x PHY address: %02x\n", phyid1, priv->phyaddr); + + /* Read the LS bits of the OUI from Pthe PHYID2 register */ + + ret = sam_phyread(priv, priv->phyaddr, GMII_PHYID2, &phyid2); + if (ret < 0) + { + nerr("ERROR: Failed to read PHYID2 register\n"); + goto errout; + } + + ninfo("PHYID2: %04x PHY address: %02x\n", phyid2, priv->phyaddr); + + if (phyid1 == GMII_OUI_MSB && + (phyid2 & GMII_PHYID2_OUI_MASK) == GMII_OUI_LSB) + { + ninfo(" Vendor Model Number: %04x\n", + (phyid2 & GMII_PHYID2_MODEL_MASK) >> GMII_PHYID2_MODEL_SHIFT); + ninfo(" Model Revision Number: %04x\n", + (phyid2 & GMII_PHYID2_REV_MASK) >> GMII_PHYID2_REV_SHIFT); + } + else + { + nerr("ERROR: PHY not recognized: PHYID1=%04x PHYID2=%04x\n", + phyid1, phyid2); + } + +#ifdef SAMD5E5_GMAC_PHY_KSZ90x1 + /* Set up the KSZ9020/31 PHY */ + + phyval = GMII_KSZ90x1_RCCPSR | GMII_ERCR_WRITE; + sam_phywrite(priv, priv->phyaddr, GMII_ERCR, phyval); + sam_phywrite(priv, priv->phyaddr, GMII_ERDWR, 0xf2f4); + + phyval = GMII_KSZ90x1_RRDPSR | GMII_ERCR_WRITE; + sam_phywrite(priv, priv->phyaddr, GMII_ERCR, phyval); + sam_phywrite(priv, priv->phyaddr, GMII_ERDWR, 0x2222); + + ret = sam_phywrite(priv, priv->phyaddr, GMII_KSZ90x1_ICS, 0xff00); +#endif + + /* Set the Auto_negotiation Advertisement Register, MII advertising for + * Next page 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 + */ + + advertise = GMII_ADVERTISE_100BASETXFULL | GMII_ADVERTISE_100BASETXHALF | + GMII_ADVERTISE_10BASETXFULL | GMII_ADVERTISE_10BASETXHALF | + GMII_ADVERTISE_8023; + + ret = sam_phywrite(priv, priv->phyaddr, GMII_ADVERTISE, advertise); + if (ret < 0) + { + nerr("ERROR: Failed to write ADVERTISE register\n"); + goto errout; + } + + /* Restart Auto_negotiation */ + + ret = sam_phyread(priv, priv->phyaddr, GMII_MCR, &phyval); + if (ret < 0) + { + nerr("ERROR: Failed to read MCR register: %d\n", ret); + goto errout; + } + + phyval |= GMII_MCR_ANRESTART; + + ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, phyval); + if (ret < 0) + { + nerr("ERROR: Failed to write MCR register: %d\n", ret); + goto errout; + } + + ninfo(" MCR: 0x%X\n", phyval); + + /* Wait for autonegotion to complete */ + + timeout = 0; + for (; ; ) + { + ret = sam_phyread(priv, priv->phyaddr, GMII_MSR, &phyval); + if (ret < 0) + { + nerr("ERROR: Failed to read MSR register: %d\n", ret); + goto errout; + } + + /* Check for completion of autonegotiation */ + + if ((phyval & GMII_MSR_ANEGCOMPLETE) != 0) + { + /* Yes.. break out of the loop */ + + ninfo("AutoNegotiate complete\n"); + break; + } + + /* No.. check for a timeout */ + + if (++timeout >= PHY_RETRY_MAX) + { + nerr("ERROR: TimeOut\n"); + sam_phydump(priv); + ret = -ETIMEDOUT; + goto errout; + } + } + + /* Setup the GMAC local link speed */ + + linkmode = 0; /* 10Base-T Half-Duplex */ + timeout = 0; + + for (; ; ) + { + /* Get the Autonegotiation Link partner base page */ + + ret = sam_phyread(priv, priv->phyaddr, GMII_LPA, &lpa); + if (ret < 0) + { + nerr("ERROR: Failed to read LPA register: %d\n", ret); + goto errout; + } + + /* Setup the GMAC link speed */ + + if ((advertise & GMII_ADVERTISE_100BASETXFULL) != 0 && + (lpa & GMII_LPA_100BASETXFULL) != 0) + { + /* Set MII for 100BaseTX and Full Duplex */ + + linkmode = (GMAC_NCFGR_SPD | GMAC_NCFGR_FD); + break; + } + else if ((advertise & GMII_ADVERTISE_10BASETXFULL) != 0 && + (lpa & GMII_LPA_10BASETXFULL) != 0) + { + /* Set MII for 10BaseT and Full Duplex */ + + linkmode = GMAC_NCFGR_FD; + break; + } + else if ((advertise & GMII_ADVERTISE_100BASETXHALF) != 0 && + (lpa & GMII_LPA_100BASETXHALF) != 0) + { + /* Set MII for 100BaseTX and half Duplex */ + + linkmode = GMAC_NCFGR_SPD; + break; + } + else if ((advertise & GMII_ADVERTISE_10BASETXHALF) != 0 && + (lpa & GMII_LPA_10BASETXHALF) != 0) + { + /* Set MII for 10BaseT and half Duplex */ + + break; + } + + /* Check for a timeout */ + + if (++timeout >= PHY_RETRY_MAX) + { + nerr("ERROR: TimeOut\n"); + sam_phydump(priv); + ret = -ETIMEDOUT; + goto errout; + } + } + + /* Disable RX and TX momentarily */ + + ncr = sam_getreg(priv, SAM_GMAC_NCR); + sam_putreg(priv, SAM_GMAC_NCR, ncr & ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN)); + + /* Modify the NCFGR register based on the negotiated speed and duplex */ + + regval = sam_getreg(priv, SAM_GMAC_NCFGR); + regval &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD); + regval |= linkmode; + sam_putreg(priv, SAM_GMAC_NCFGR, regval); + sam_putreg(priv, SAM_GMAC_NCR, ncr); + + /* Enable MII or RMII */ + + regval = sam_getreg(priv, SAM_GMAC_UR); +#ifdef CONFIG_SAMD5E5_GMAC_MII + regval |= GMAC_UR_MII; +#else + regval &= ~GMAC_UR_MII; +#endif + sam_putreg(priv, SAM_GMAC_UR, regval); + +errout: + + /* Disable the management port */ + + sam_disablemdio(priv); + return ret; +} +#endif + +/**************************************************************************** + * Function: sam_linkspeed + * + * Description: + * If autonegotiation is not configured, then just force the configuration + * mode + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef CONFIG_SAMD5E5_GMAC_AUTONEG +statoc void sam_linkspeed(struct sam_gmac_s *priv) +{ + uint32_t regval; + uint32_t ncr; + + /* Disable RX and TX momentarily */ + + ncr = sam_getreg(priv, SAM_GMAC_NCR); + sam_putreg(priv, SAM_GMAC_NCR, ncr & ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN)); + + /* Modify the NCFGR register based on the configured speed and duplex */ + + regval = sam_getreg(priv, SAM_GMAC_NCFGR); + regval &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD); + +#ifdef SAMD5E5_GMAC_ETHFD + regval |= GMAC_NCFGR_FD; +#endif + +#if defined(SAMD5E5_GMAC_ETH100MBPS) + regval |= GMAC_NCFGR_SPD; +#endif + + sam_puttreg(priv, SAM_GMAC_NCFGR, regval); + sam_putreg(priv, SAM_GMAC_NCR, ncr); +} +#endif + +/**************************************************************************** + * Function: sam_mdcclock + * + * Description: + * Configure the MDC clocking + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sam_mdcclock(struct sam_gmac_s *priv) +{ + uint32_t ncfgr; + uint32_t ncr; + uint32_t mck; + + /* Disable RX and TX momentarily */ + + ncr = sam_getreg(priv, SAM_GMAC_NCR); + sam_putreg(priv, SAM_GMAC_NCR, ncr & ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN)); + + /* Modify the NCFGR register based on the configured board MCK frequency */ + + ncfgr = sam_getreg(priv, SAM_GMAC_NCFGR); + ncfgr &= ~GMAC_NCFGR_CLK_MASK; + + mck = BOARD_MCK_FREQUENCY; + DEBUGASSERT(mck <= 240000000); + + if (mck <= 20000000) + { + ncfgr |= GMAC_NCFGR_CLK_DIV8; /* MCK divided by 8 (MCK up to 20 MHz) */ + } + else if (mck <= 40000000) + { + ncfgr |= GMAC_NCFGR_CLK_DIV16; /* MCK divided by 16 (MCK up to 40 MHz) */ + } + else if (mck <= 80000000) + { + ncfgr |= GMAC_NCFGR_CLK_DIV32; /* MCK divided by 32 (MCK up to 80 MHz) */ + } + else if (mck <= 120000000) + { + ncfgr |= GMAC_NCFGR_CLK_DIV48; /* MCK divided by 48 (MCK up to 120 MHz) */ + } + else if (mck <= 160000000) + { + ncfgr |= GMAC_NCFGR_CLK_DIV64; /* MCK divided by 64 (MCK up to 160 MHz) */ + } + else /* if (mck <= 240000000) */ + { + ncfgr |= GMAC_NCFGR_CLK_DIV96; /* MCK divided by 64 (MCK up to 240 MHz) */ + } + + sam_putreg(priv, SAM_GMAC_NCFGR, ncfgr); + + /* Restore RX and TX enable settings */ + + sam_putreg(priv, SAM_GMAC_NCR, ncr); +} + +/**************************************************************************** + * Function: sam_phyinit + * + * Description: + * Configure the PHY and determine the link speed/duplex. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +static int sam_phyinit(struct sam_gmac_s *priv) +{ + int ret; + + /* Configure PHY clocking */ + + sam_mdcclock(priv); + +#ifdef CONFIG_SAMD5E5_GMAC_PHYINIT + ret = sam_phy_boardinitialize(0); + if (ret < 0) + { + nerr("ERROR: Failed to initialize the PHY: %d\n", ret); + return ret; + } +#endif + + /* Check the PHY Address */ + + priv->phyaddr = CONFIG_SAMD5E5_GMAC_PHYADDR; + ret = sam_phyfind(priv, &priv->phyaddr); + if (ret < 0) + { + nerr("ERROR: sam_phyfind failed: %d\n", ret); + return ret; + } + + /* We have a PHY address. Reset the PHY */ + + sam_phyreset(priv); + return OK; +} + +/**************************************************************************** + * Function: sam_ethgpioconfig + * + * Description: + * Configure GPIOs for the GMAC interface. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +static inline void sam_ethgpioconfig(struct sam_gmac_s *priv) +{ + /* Configure PIO pins to support GMAC in MII or RMII mode */ + + sam_portconfig(PORT_GMAC_GTX0); + sam_portconfig(PORT_GMAC_GTX1); +#ifdef CONFIG_SAMD5E5_GMAC_MII + sam_portconfig(PORT_GMAC_GTX2); + sam_portconfig(PORT_GMAC_GTX3); +#endif + + sam_portconfig(PORT_GMAC_GRX0); + sam_portconfig(PORT_GMAC_GRX1); +#ifdef CONFIG_SAMD5E5_GMAC_MII + sam_portconfig(PORT_GMAC_GRX1); + sam_portconfig(PORT_GMAC_GRX2); +#endif + + /* TXCK is REFCK in RMII mode */ + + sam_portconfig(PORT_GMAC_GTXCK); +#ifdef CONFIG_SAMD5E5_GMAC_MII + sam_portconfig(PORT_GMAC_GRXCK); +#endif + + /* RXDV is CRSDV in RMII mode */ + + sam_portconfig(PORT_GMAC_GRXDV); + sam_portconfig(PORT_GMAC_GTXEN); + sam_portconfig(PORT_GMAC_GRXER); +#ifdef CONFIG_SAMD5E5_GMAC_MII + sam_portconfig(PORT_GMAC_GTXER); + sam_portconfig(PORT_GMAC_GCOL); + sam_portconfig(PORT_GMAC_GCRS); +#endif + + sam_portconfig(BOARD_GMAC_GMDC); + sam_portconfig(BOARD_GMAC_GMDIO); +} + +/**************************************************************************** + * Function: sam_txreset + * + * Description: + * Reset the transmit logic + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +static void sam_txreset(struct sam_gmac_s *priv) +{ + uint8_t *txbuffer = priv->txbuffer; + struct gmac_txdesc_s *txdesc = priv->txdesc; + uintptr_t bufaddr; + uint32_t physaddr; + uint32_t regval; + int ndx; + + /* Disable TX */ + + regval = sam_getreg(priv, SAM_GMAC_NCR); + regval &= ~GMAC_NCR_TXEN; + sam_putreg(priv, SAM_GMAC_NCR, regval); + + /* Configure the TX descriptors. */ + + priv->txhead = 0; + priv->txtail = 0; + + for (ndx = 0; ndx < CONFIG_SAMD5E5_GMAC_NTXBUFFERS; ndx++) + { + bufaddr = (uintptr_t)(&(txbuffer[ndx * GMAC_TX_UNITSIZE])); + + /* Set the buffer address and mark the descriptor as in used by + * firmware. + */ + + physaddr = bufaddr; + txdesc[ndx].addr = physaddr; + txdesc[ndx].status = (uint32_t)GMACTXD_STA_USED; + } + + /* Mark the final descriptor in the list */ + + txdesc[CONFIG_SAMD5E5_GMAC_NTXBUFFERS - 1].status = + GMACTXD_STA_USED | GMACTXD_STA_WRAP; + + /* Flush the entire TX descriptor table to RAM */ + + up_clean_dcache((uintptr_t)txdesc, + (uintptr_t)txdesc + + CONFIG_SAMD5E5_GMAC_NTXBUFFERS * sizeof(struct gmac_txdesc_s)); + + /* Set the Transmit Buffer Queue Base Register */ + + physaddr = (uintptr_t)txdesc; + sam_putreg(priv, SAM_GMAC_TBQB, physaddr); +} + +/**************************************************************************** + * Function: sam_rxreset + * + * Description: + * Reset the receive logic + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +static void sam_rxreset(struct sam_gmac_s *priv) +{ + struct gmac_rxdesc_s *rxdesc = priv->rxdesc; + uint8_t *rxbuffer = priv->rxbuffer; + uintptr_t bufaddr; + uint32_t physaddr; + uint32_t regval; + int ndx; + + /* Disable RX */ + + regval = sam_getreg(priv, SAM_GMAC_NCR); + regval &= ~GMAC_NCR_RXEN; + sam_putreg(priv, SAM_GMAC_NCR, regval); + + /* Configure the RX descriptors. */ + + priv->rxndx = 0; + for (ndx = 0; ndx < CONFIG_SAMD5E5_GMAC_NRXBUFFERS; ndx++) + { + bufaddr = (uintptr_t)(&(rxbuffer[ndx * GMAC_RX_UNITSIZE])); + DEBUGASSERT((bufaddr & ~GMACRXD_ADDR_MASK) == 0); + + /* Set the buffer address and remove GMACRXD_ADDR_OWNER and + * GMACRXD_ADDR_WRAP. + */ + + physaddr = bufaddr; + rxdesc[ndx].addr = physaddr; + rxdesc[ndx].status = 0; + } + + /* Mark the final descriptor in the list */ + + rxdesc[CONFIG_SAMD5E5_GMAC_NRXBUFFERS - 1].addr |= GMACRXD_ADDR_WRAP; + + /* Flush the entire RX descriptor table to RAM */ + + up_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + CONFIG_SAMD5E5_GMAC_NRXBUFFERS * sizeof(struct gmac_rxdesc_s)); + + /* Set the Receive Buffer Queue Base Register */ + + physaddr = (uintptr_t)rxdesc; + sam_putreg(priv, SAM_GMAC_RBQB, physaddr); +} + +/**************************************************************************** + * Function: sam_gmac_reset + * + * Description: + * Reset the GMAC block. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +static void sam_gmac_reset(struct sam_gmac_s *priv) +{ +#ifdef CONFIG_NETDEV_PHY_IOCTL + /* We are supporting PHY IOCTLs, then do not reset the MAC. If we do, + * then we cannot communicate with the PHY. So, instead, just disable + * interrupts, cancel timers, and disable TX and RX. + */ + + sam_putreg(priv, SAM_GMAC_IDR, GMAC_INT_ALL); + + /* Reset RX and TX logic */ + + sam_rxreset(priv); + sam_txreset(priv); + + /* Disable Rx and Tx, plus the statistics registers. */ + + regval = sam_getreg(priv, SAM_GMAC_NCR); + regval &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN | GMAC_NCR_WESTAT); + sam_putreg(priv, SAM_GMAC_NCR, regval); + +#else + /* Disable all GMAC interrupts */ + + sam_putreg(priv, SAM_GMAC_IDR, GMAC_INT_ALL); + + /* Reset RX and TX logic */ + + sam_rxreset(priv); + sam_txreset(priv); + + /* Make sure that RX and TX are disabled; clear statistics registers */ + + sam_putreg(priv, SAM_GMAC_NCR, GMAC_NCR_CLRSTAT); + + /* Disable clocking to the GMAC peripheral */ + + sam_ahb_gmac_disableperiph(); + sam_apb_gmac_disableperiph(); + +#endif +} + +/**************************************************************************** + * Function: sam_macaddress + * + * Description: + * Configure the selected MAC address. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static void sam_macaddress(struct sam_gmac_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + uint32_t regval; + + ninfo("%s MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->d_ifname, + dev->d_mac.ether.ether_addr_octet[0], dev->d_mac.ether.ether_addr_octet[1], + dev->d_mac.ether.ether_addr_octet[2], dev->d_mac.ether.ether_addr_octet[3], + dev->d_mac.ether.ether_addr_octet[4], dev->d_mac.ether.ether_addr_octet[5]); + + /* Set the MAC address */ + + regval = (uint32_t)dev->d_mac.ether.ether_addr_octet[0] | + (uint32_t)dev->d_mac.ether.ether_addr_octet[1] << 8 | + (uint32_t)dev->d_mac.ether.ether_addr_octet[2] << 16 | + (uint32_t)dev->d_mac.ether.ether_addr_octet[3] << 24; + sam_putreg(priv, SAM_GMAC_SAB1, regval); + + regval = (uint32_t)dev->d_mac.ether.ether_addr_octet[4] | + (uint32_t)dev->d_mac.ether.ether_addr_octet[5] << 8; + sam_putreg(priv, SAM_GMAC_SAT1, regval); +} + +/**************************************************************************** + * Function: sam_ipv6multicast + * + * Description: + * Configure the IPv6 multicast MAC address. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ICMPv6 +static void sam_ipv6multicast(struct sam_gmac_s *priv) +{ + struct net_driver_s *dev; + uint16_t tmp16; + uint8_t mac[6]; + + /* For ICMPv6, we need to add the IPv6 multicast address + * + * For IPv6 multicast addresses, the Ethernet MAC is derived by + * the four low-order octets OR'ed with the MAC 33:33:00:00:00:00, + * so for example the IPv6 address FF02:DEAD:BEEF::1:3 would map + * to the Ethernet MAC address 33:33:00:01:00:03. + * + * NOTES: This appears correct for the ICMPv6 Router Solicitation + * Message, but the ICMPv6 Neighbor Solicitation message seems to + * use 33:33:ff:01:00:03. + */ + + mac[0] = 0x33; + mac[1] = 0x33; + + dev = &priv->dev; + tmp16 = dev->d_ipv6addr[6]; + mac[2] = 0xff; + mac[3] = tmp16 >> 8; + + tmp16 = dev->d_ipv6addr[7]; + mac[4] = tmp16 & 0xff; + mac[5] = tmp16 >> 8; + + ninfo("IPv6 Multicast: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + (void)sam_addmac(dev, mac); + +#ifdef CONFIG_NET_ICMPv6_AUTOCONF + /* Add the IPv6 all link-local nodes Ethernet address. This is the + * address that we expect to receive ICMPv6 Router Advertisement + * packets. + */ + + (void)sam_addmac(dev, g_ipv6_ethallnodes.ether_addr_octet); + +#endif /* CONFIG_NET_ICMPv6_AUTOCONF */ +#ifdef CONFIG_NET_ICMPv6_ROUTER + /* Add the IPv6 all link-local routers Ethernet address. This is the + * address that we expect to receive ICMPv6 Router Solicitation + * packets. + */ + + (void)sam_addmac(dev, g_ipv6_ethallrouters.ether_addr_octet); + +#endif /* CONFIG_NET_ICMPv6_ROUTER */ +} +#endif /* CONFIG_NET_ICMPv6 */ + +/**************************************************************************** + * Function: sam_gmac_configure + * + * Description: + * Configure the GMAC interface for normal operation. + * + * Input Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int sam_gmac_configure(struct sam_gmac_s *priv) +{ + uint32_t regval; + + ninfo("Entry\n"); + + /* Enable clocking to the GMAC peripheral */ + + sam_ahb_gmac_enableperiph(); + sam_apb_gmac_enableperiph(); + + /* Disable TX, RX, clear statistics. Disable all interrupts. */ + + sam_putreg(priv, SAM_GMAC_NCR, GMAC_NCR_CLRSTAT); + sam_putreg(priv, SAM_GMAC_IDR, GMAC_INT_ALL); + + /* Clear all status bits in the receive status register. */ + + regval = (GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA | GMAC_RSR_HNO); + sam_putreg(priv, SAM_GMAC_RSR, regval); + + /* Clear all status bits in the transmit status register */ + + regval = GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE | GMAC_TSR_TXGO | + GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_UND | GMAC_TSR_HRESP | + GMAC_TSR_LCO; + sam_putreg(priv, SAM_GMAC_TSR, regval); + + /* Clear any pending interrupts */ + + (void)sam_getreg(priv, SAM_GMAC_ISR); + + /* Initial configuration: + * + * SPD = 0 : Assuming 100Base-T full duplex + * FD = 1 : Assuming 100Base-T full duplex + * DNVLAN = 0 : Don't discard non-VLAN frames + * JFRAME = 0 : Disable jumbo frames + * CAF : Depends on CONFIG_NET_PROMISCUOUS + * NBC : Depends on CONFIG_SAMD5E5_GMAC_NBC + * MTIHEN = 0 : Multicast hash disabled + * UNIHEN = 0 : Unicast hash disabled + * MAXFS = 0 : Disable receive 1536 byte frames + * RTY = 0 : Disable retry test + * PEN = 1 : Pause frames disabled + * RXBUFO = 0 : No receive buffer offset + * LFERD = 0 : No length field error discard + * RFCS = 1 : Remove FCS + * CLK = 4 : Assuming MCK <= 160MHz + * DBW = 1 : 64-bit data bus with + * DCPF = 0 : Copy of pause frames not disabled + * RXCOEN = 0 : RX checksum offload disabled + * EFRHD = 0 : Disable frames received in half duple + * IRXFCS = 0 : Disable ignore RX FCX + * IPGSEN = 0 : IP stretch disabled + * RXBP = 0 : Receive bad pre-ambled disabled + * IRXER = 0 : Disable ignore IPG GXER + */ + + regval = GMAC_NCFGR_FD | GMAC_NCFGR_PEN | + GMAC_NCFGR_RFCS | GMAC_NCFGR_CLK_DIV64 | GMAC_NCFGR_DBW_64; + +#ifdef CONFIG_NET_PROMISCUOUS + regval |= GMAC_NCFGR_CAF; +#endif + +#ifdef CONFIG_SAMD5E5_GMAC_NBC + regval |= GMAC_NCFGR_NBC; +#endif + + sam_putreg(priv, SAM_GMAC_NCFGR, regval); + + /* Reset TX and RX */ + + sam_rxreset(priv); + sam_txreset(priv); + + /* Enable Rx and Tx, plus the statistics registers. */ + + regval = sam_getreg(priv, SAM_GMAC_NCR); + regval |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN | GMAC_NCR_WESTAT); + sam_putreg(priv, SAM_GMAC_NCR, regval); + + /* Setup the interrupts for TX events, RX events, and error events */ + + regval = GMAC_INT_MFS | GMAC_INT_RCOMP | GMAC_INT_RXUBR | GMAC_INT_TXUBR | + GMAC_INT_TUR | GMAC_INT_RLEX | GMAC_INT_TFC | GMAC_INT_TCOMP | + GMAC_INT_ROVR | GMAC_INT_HRESP | GMAC_INT_PFNZ | GMAC_INT_PTZ | + GMAC_INT_PFTR | GMAC_INT_EXINT | GMAC_INT_DRQFR | GMAC_INT_SFR | + GMAC_INT_DRQFT | GMAC_INT_SFT | GMAC_INT_PDRQFR | GMAC_INT_PDRSFR | + GMAC_INT_PDRQFT | GMAC_INT_PDRSFT; + sam_putreg(priv, SAM_GMAC_IER, regval); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sam_gmac_initialize + * + * Description: + * Initialize the GMAC driver. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * Called very early in the initialization sequence. + * + ****************************************************************************/ + +int sam_gmac_initialize(void) +{ + struct sam_gmac_s *priv = &g_gmac; + int ret; + + /* Initialize the driver structure */ + + memset(priv, 0, sizeof(struct sam_gmac_s)); + priv->dev.d_buf = g_pktbuf; /* Single packet buffer */ + priv->dev.d_ifup = sam_ifup; /* I/F up (new IP address) callback */ + priv->dev.d_ifdown = sam_ifdown; /* I/F down callback */ + priv->dev.d_txavail = sam_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_MCASTGROUP + priv->dev.d_addmac = sam_addmac; /* Add multicast MAC address */ + priv->dev.d_rmmac = sam_rmmac; /* Remove multicast MAC address */ +#endif +#ifdef CONFIG_NETDEV_IOCTL + priv->dev.d_ioctl = sam_ioctl; /* Support PHY ioctl() calls */ +#endif + priv->dev.d_private = (void *)&g_gmac; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for and timing of transmissions */ + + priv->txpoll = wd_create(); + if (!priv->txpoll) + { + nerr("ERROR: Failed to create periodic poll timer\n"); + ret = -EAGAIN; + goto errout; + } + + priv->txtimeout = wd_create(); /* Create TX timeout timer */ + if (!priv->txtimeout) + { + nerr("ERROR: Failed to create periodic poll timer\n"); + ret = -EAGAIN; + goto errout_with_txpoll; + } + + /* Configure PIO pins to support GMAC */ + + sam_ethgpioconfig(priv); + + /* Allocate buffers */ + + ret = sam_buffer_initialize(priv); + if (ret < 0) + { + nerr("ERROR: sam_buffer_initialize failed: %d\n", ret); + goto errout_with_txtimeout; + } + + /* Attach the IRQ to the driver. It will not be enabled at the AIC until + * the interface is in the 'up' state. + */ + + ret = irq_attach(SAM_IRQ_GMAL, sam_gmac_interrupt, NULL); + if (ret < 0) + { + nerr("ERROR: Failed to attach the handler to the IRQ%d\n", SAM_IRQ_GMAL); + goto errout_with_buffers; + } + + /* Enable clocking to the GMAC peripheral (just for sam_ifdown()) */ + + sam_ahb_gmac_enableperiph(); + sam_apb_gmac_enableperiph(); + + /* Put the interface in the down state (disabling clocking again). */ + + ret = sam_ifdown(&priv->dev); + if (ret < 0) + { + nerr("ERROR: Failed to put the interface in the down state: %d\n", ret); + goto errout_with_buffers; + } + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + ret = netdev_register(&priv->dev, NET_LL_ETHERNET); + if (ret >= 0) + { + return ret; + } + + nerr("ERROR: netdev_register() failed: %d\n", ret); + +errout_with_buffers: + sam_buffer_free(priv); +errout_with_txtimeout: + wd_delete(priv->txtimeout); +errout_with_txpoll: + wd_delete(priv->txpoll); +errout: + return ret; +} + +#endif /* CONFIG_NET && CONFIG_SAMD5E5_GMAC */ diff --git a/boards/Kconfig b/boards/Kconfig index cb1b79b029..aed15fd802 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1336,6 +1336,15 @@ config ARCH_BOARD_SAMD21_XPLAINED This board features the ATSAMD21J18A MCU (Cortex-M0+ with 256KB of FLASH and 32KB of SRAM). +config ARCH_BOARD_SAME54_XPLAINED_PRO + bool "Atmel SAME54-Xplained Pro development board" + depends on ARCH_CHIP_SAME54P20 + select ARCH_HAVE_LEDS + select ARCH_HAVE_BUTTONS + select ARCH_HAVE_IRQBUTTONS + ---help--- + The port of NuttX to the Atmel SAME54-Xplained Pro development board. + config ARCH_BOARD_SAML21_XPLAINED bool "Atmel SAML21-Xplained Pro development board" depends on ARCH_CHIP_SAML21J18 @@ -2129,6 +2138,7 @@ config ARCH_BOARD default "sama5d4-ek" if ARCH_BOARD_SAMA5D4_EK default "samd20-xplained" if ARCH_BOARD_SAMD20_XPLAINED default "samd21-xplained" if ARCH_BOARD_SAMD21_XPLAINED + default "same54-xplained-pro" if ARCH_BOARD_SAME54_XPLAINED_PRO default "saml21-xplained" if ARCH_BOARD_SAML21_XPLAINED default "sam3u-ek" if ARCH_BOARD_SAM3UEK default "sam4cmp-db" if ARCH_BOARD_SAM4CMP_DB @@ -2439,6 +2449,9 @@ endif if ARCH_BOARD_SAMD21_XPLAINED source "boards/arm/samd2l2/samd21-xplained/Kconfig" endif +if ARCH_BOARD_SAME54_XPLAINED_PRO +source "boards/arm/samd5e5/same54-xplained-pro/Kconfig" +endif if ARCH_BOARD_SAML21_XPLAINED source "boards/arm/samd2l2/saml21-xplained/Kconfig" endif diff --git a/boards/arm/samd5e5/same54-xplained-pro/Kconfig b/boards/arm/samd5e5/same54-xplained-pro/Kconfig new file mode 100644 index 0000000000..371357c7a3 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/Kconfig @@ -0,0 +1,50 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_SAME54_XPLAINED_PRO + +choice + prompt "Execution memory" + default SAME54_XPLAINED_PRO_RUNFROMFLASH + +config SAME54_XPLAINED_PRO_RUNFROMFLASH + bool "Run from FLASH" + select BOOT_RUNFROMFLASH + ---help--- + This is the normal configuration for building SAM E54 Xplained + Pro code. + +config SAME54_XPLAINED_PRO_RUNFROMSRAM + bool "Run from SRAM" + select BOOT_RUNFROMISRAM + ---help--- + During early bring-up, it is safer to execute entirely from + SRAM until you are confident in the initialization logic. + Then you can safely switch to FLASH. + + REVISIT: This auto-selects CONFIG_BOOT_RUNFROMISRAM but I have + found, with some difficulty, that that choice still defaults to + CONFIG_BOOT_RUNFROMFLASH, causing link-time failures when running + from SRAM. + +endchoice # Execution memory + +config SAME54_XPLAINED_PRO_32KHZXTAL + bool "32.768 KHz XTAL" + default n + ---help--- + According to the schematic, a 32.768 KHz crystal is installed on + board. However, I have been unable to use this crystal and thought + perhaps it is missing or defective on my board (there is a metal + package that could be a crystal on board, but I am not certain). + Another, more likely option is that there is a coding error on my + part that prevents the 32.768 KHz crystal from usable(?) + + The configuration defaults to using the always-on OSCULP32 as the + slow clock source. This option will select instead XOSC32 as the + slow clock source. + + +endif # ARCH_BOARD_SAME54_XPLAINED_PRO diff --git a/boards/arm/samd5e5/same54-xplained-pro/README.txt b/boards/arm/samd5e5/same54-xplained-pro/README.txt new file mode 100644 index 0000000000..a844e0146c --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/README.txt @@ -0,0 +1,160 @@ +README +====== + + This directory contains the port of NuttX to the Microchip SAME54 Xplained + Pro board. This board is powered by an ATSAME54P20A: + + o Cortex M4 core running at 120 MHz + o Hardware DSP and floating point support + o 1 MB flash, 256 KB RAM + o 32-bit, 3.3V logic and power + o Dual 1 MSPS DAC (A0 and A1) + o Dual 1 MSPS ADC (8 analog pins) + o 8 x hardware SERCOM (I2C, SPI or UART) + o 16 x PWM outputs + o Stereo I2S input/output with MCK pin + o 14-bit Parallel capture controller (for camera/video in) + o Built in crypto engines with AES (256 bit), true RNG, Pubkey controller + o 10/100 Ethernet MAC + o Dual SD/MMC controller + o Dual CAN bus interfaces + o 100-TQFP + +Contents +======== + + o STATUS + o Serial Console + o LEDs + o Run from SRAM + o Configurations + +STATUS +====== + + 2019-09-17: Board port started based on Metro M4 board. + + WARNING: If you decide to invest the time to discover whey the XOSC32K + clock source is not working, be certain to use the SRAM configuration. + That configuration in FLASH is most likely lock up your board irrecoverably + is there are any start-up errors! + + +Serial Console +============== + + The onboard debugger on the SAME54 Xplained Pro provides a virtual serial + interface over the DEBUG USB port. The pins on the SAME54 are as follows: + + ----------------- ----------- + SAMD5E5 FUNCTION + ----------------- ----------- + PB24 SERCOM2 PAD1 RXD + PB25 SERCOM2 PAD0 TXD + + + An external RS-232 or serial-to-USB adapter can be connected on pins PA22 + and PA23: + + ----------------- --------- + SAMD5E5 FUNCTION + ----------------- --------- + PA23 SERCOM3 PAD1 RXD + PA22 SERCOM3 PAD0 TXD + + +LEDs +==== + + The SAME54 Xplained Pro has three LEDs, but only one is controllable by software: + + 1. LED0 near the edge of the board + + + ----------------- ----------- + SAMD5E5 FUNCTION + ----------------- ----------- + PC18 GPIO output + +Run from SRAM +============= + + I bricked my first Metro M4 board because there were problems in the + bring-up logic. These problems left the chip in a bad state that was + repeated on each reset because the code was written into FLASH and I was + unable to ever connect to it again via SWD. + + To make the bring-up less risky, I added a configuration option to build + the code to execution entirely out of SRAM. By default, the setting + CONFIG_SAME54_XPLAINED_PRO_RUNFROMFLASH=y is used and the code is built to run out of + FLASH. If CONFIG_SAME54_XPLAINED_PRO_RUNFROMSRAM=y is selected instead, then the + code is built to run out of SRAM. + + To use the code in this configuration, the program must be started a + little differently: + + gdb> mon reset + gdb> mon halt + gdb> load nuttx << Load NuttX into SRAM + gdb> file nuttx << Assuming debug symbols are enabled + gdb> mon memu32 0x20000000 << Get the address of initial stack + gdb> mon reg sp 0x200161c4 << Set the initial stack pointer using this address + gdb> mon memu32 0x20000004 << Get the address of __start entry point + gdb> mon reg pc 0x20000264 << Set the PC using this address (without bit 0 set) + gdb> si << Step in just to make sure everything is okay + gdb> [ set breakpoints ] + gdb> c << Then continue until you hit a breakpoint + + Where 0x200161c4 and 0x20000264 are the values of the initial stack and + the __start entry point that I read from SRAM + +Configurations +============== + + Each SAME54 Xplained Pro configuration is maintained in a sub-directory and + can be selected as follow: + + tools/configure.sh [OPTIONS] same54-xplained-pro: + + Do 'tools/configure.sh -h' for the list of options. If you are building + under Windows with Cygwin, you would need the -c option, for example. + + Before building, make sure that the PATH environmental variable includes the + correct path to the directory than holds your toolchain binaries. + + And then build NuttX by simply typing the following. At the conclusion of + the make, the nuttx binary will reside in an ELF file called, simply, nuttx. + + make + + The that is provided above as an argument to the tools/configure.sh + must be is one of configurations listed in the following paragraph. + + NOTES: + + 1. These configurations use the mconf-based configuration tool. To + change any of these configurations using that tool, you should: + + a. Build and install the kconfig-mconf tool. See nuttx/README.txt + see additional README.txt files in the NuttX tools repository. + + b. Execute 'make menuconfig' in nuttx/ in order to start the + reconfiguration process. + + 2. Unless stated otherwise, all configurations generate console + output on SERCOM2 which is available via USB debug. + + 3. Unless otherwise stated, the configurations are setup build under + Linux with a generic ARM EABI toolchain: + +Configuration sub-directories +----------------------------- + + nsh: + This configuration directory will built the NuttShell. See NOTES for + common configuration above and the following: + + NOTES: + + 1. The CMCC (Cortex M Cache Controller) is enabled. + diff --git a/boards/arm/samd5e5/same54-xplained-pro/configs/nsh/defconfig b/boards/arm/samd5e5/same54-xplained-pro/configs/nsh/defconfig new file mode 100644 index 0000000000..2e1ee8c3e8 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/configs/nsh/defconfig @@ -0,0 +1,55 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="same54-xplained-pro" +CONFIG_ARCH_BOARD_SAME54_XPLAINED_PRO=y +CONFIG_ARCH_CHIP="samd5e5" +CONFIG_ARCH_CHIP_SAME54P20=y +CONFIG_ARCH_CHIP_SAME5X=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=7225 +CONFIG_BUILTIN=y +CONFIG_DISABLE_ENVIRON=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=4 +CONFIG_PTHREAD_STACK_DEFAULT=1536 +CONFIG_RAM_SIZE=196608 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SAMD5E5_CMCC=y +CONFIG_SAMD5E5_EIC=y +CONFIG_SAMD5E5_SERCOM2=y +CONFIG_SAMD5E5_SERCOM3=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_START_DAY=23 +CONFIG_START_MONTH=7 +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_CXXINITIALIZE=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=1536 +CONFIG_USART2_SERIAL_CONSOLE=y +CONFIG_USART3_RXBUFSIZE=64 +CONFIG_USART3_TXBUFSIZE=64 +CONFIG_USERMAIN_STACKSIZE=1536 +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WDOG_INTRESERVE=0 diff --git a/boards/arm/samd5e5/same54-xplained-pro/include/board.h b/boards/arm/samd5e5/same54-xplained-pro/include/board.h new file mode 100644 index 0000000000..bb67025b5d --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/include/board.h @@ -0,0 +1,503 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/include/board.h + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_SAMD5E5_SAME54_XPLAINED_PRO_INCLUDE_BOARD_H +#define __BOARDS_ARM_SAMD5E5_SAME54_XPLAINED_PRO_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#endif + +/* Clocking *****************************************************************/ + +/* Overview + * + * Per the schematic Adafruit Metro M4 Pro has one on-board crystal: + * + * X4 32.768KHz XOSC32 + * + * However, I have been unsuccessful using it and have fallen back to using + * OSCULP32K(Unless CONFIG_SAME54_XPLAINED_PRO_32KHZXTAL=y) + * + * Since there is no high speed crystal, we will run from the OSC16M clock + * source. + * + * OSC48M Output = 48Mhz + * | + * FDLL Input = 48MHz + * | Output = 48MHz + * GCLK5 Input = 48MHz + * | Output = 2MHz + * DPLL0 Input = 2MHz + * | Output = 120MHz + * GCLK0 Input = 120MHz + * | Output = 120MHz + * MCK Input = 120MHz + * | Output = 120MHz + * CPU Input = 120MHz + */ + +#define BOARD_OSC32K_FREQUENCY 32768 /* OSCULP32K frequency 32.768 KHz (nominal) */ +#define BOARD_XOSC32K_FREQUENCY 32768 /* XOSC32K frequency 32.768 KHz */ +#define BOARD_DFLL_FREQUENCY 48000000 /* FDLL frequency 28MHz */ +#define BOARD_XOSC0_FREQUENCY 12000000 /* XOSC0 frequency 12MHz (disabled) */ +#define BOARD_XOSC1_FREQUENCY 12000000 /* XOSC0 frequency 12MHz (disabled)*/ +#define BOARD_DPLL0_FREQUENCY 120000000 /* DPLL0 output frueuency (120MHz) */ +#define BOARD_DPLL1_FREQUENCY 47985664 /* DPLL1 output frequency (disabled) */ + +#define BOARD_GCLK0_FREQUENCY BOARD_DPLL0_FREQUENCY +#define BOARD_GCLK1_FREQUENCY BOARD_DFLL_FREQUENCY +#define BOARD_GCLK2_FREQUENCY (BOARD_XOSC32K_FREQUENCY / 4) /* Disabled */ +#ifdef CONFIG_SAME54_XPLAINED_PRO_32KHZXTAL +# define BOARD_GCLK3_FREQUENCY BOARD_XOSC32K_FREQUENCY /* Enabled */ +#else +# define BOARD_GCLK3_FREQUENCY BOARD_OSC32K_FREQUENCY /* Always-on */ +#endif +#define BOARD_GCLK4_FREQUENCY BOARD_DPLL0_FREQUENCY +#define BOARD_GCLK5_FREQUENCY (BOARD_DFLL_FREQUENCY / 24) +#define BOARD_GCLK6_FREQUENCY BOARD_XOSC1_FREQUENCY /* Disabled */ +#define BOARD_GCLK7_FREQUENCY BOARD_XOSC1_FREQUENCY /* Disabled */ +#define BOARD_GCLK8_FREQUENCY BOARD_XOSC1_FREQUENCY /* Disabled */ +#define BOARD_GCLK9_FREQUENCY BOARD_XOSC1_FREQUENCY /* Disabled */ +#define BOARD_GCLK10_FREQUENCY BOARD_XOSC1_FREQUENCY /* Disabled */ +#define BOARD_GCLK11_FREQUENCY BOARD_XOSC1_FREQUENCY /* Disabled */ + +#define BOARD_CPU_FREQUENCY BOARD_GCLK0_FREQUENCY /* CPU frequency 120MHz */ + +/* XOSC32 */ + +#ifdef CONFIG_SAME54_XPLAINED_PRO_32KHZXTAL +# define BOARD_HAVE_XOSC32K 1 /* 32.768 KHz XOSC32 crystal installed */ +# define BOARD_XOSC32K_ENABLE TRUE /* Enable XOSC32 */ +#else +# define BOARD_HAVE_XOSC32K 0 /* No 32.768 KHz XOSC32 crystal installed */ +# define BOARD_XOSC32K_ENABLE FALSE /* Disable XOSC32 */ +#endif +#define BOARD_XOSC32K_XTALEN TRUE /* Crystal connected on XIN32 */ +#define BOARD_XOSC32K_EN32K FALSE /* No 32KHz output */ +#define BOARD_XOSC32K_EN1K FALSE /* No 1KHz output */ +#define BOARD_XOSC32K_HIGHSPEED TRUE /* High speed mode */ +#define BOARD_XOSC32K_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_XOSC32K_ONDEMAND TRUE /* Enable on-demand control */ +#define BOARD_XOSC32K_CFDEN FALSE /* Clock failure detector not enabled */ +#define BOARD_XOSC32K_CFDEO FALSE /* No clock failure event */ +#define BOARD_XOSC32K_CALIBEN FALSE /* No OSCULP32K calibration */ +#define BOARD_XOSC32K_STARTUP 0 /* Startup time: 62592us */ +#define BOARD_XOSC32K_CALIB 0 /* Dummy OSCULP32K calibration value */ +#define BOARD_XOSC32K_RTCSEL 0 /* RTC clock = ULP1K */ + +/* XOSC0 */ + +#define BOARD_HAVE_XOSC0 0 /* No XOSC0 clock/crystal installed */ +#define BOARD_XOSC0_ENABLE FALSE /* Don't enable XOSC0 */ +#define BOARD_XOSC0_XTALEN FALSE /* External clock connected */ +#define BOARD_XOSC0_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_XOSC0_ONDEMAND TRUE /* Disable on-demand control */ +#define BOARD_XOSC0_LOWGAIN FALSE /* Disable low buffer gain */ +#define BOARD_XOSC0_ENALC FALSE /* Disable automatic loop control */ +#define BOARD_XOSC0_CFDEN FALSE /* Clock failure detector not enabled */ +#define BOARD_XOSC0_SWBEN FALSE /* XOSC clock switch not enabled */ +#define BOARD_XOSC0_STARTUP 0 /* XOSC0 start-up time 31µs */ + +/* XOSC1 */ + +#define BOARD_HAVE_XOSC1 0 /* No XOSC0 clock/crystal installed */ +#define BOARD_XOSC1_ENABLE FALSE /* Don't enable XOSC1 */ +#define BOARD_XOSC1_XTALEN TRUE /* External crystal connected */ +#define BOARD_XOSC1_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_XOSC1_ONDEMAND TRUE /* Disable on-demand control */ +#define BOARD_XOSC1_LOWGAIN FALSE /* Disable low buffer gain */ +#define BOARD_XOSC1_ENALC FALSE /* Disable automatic loop control */ +#define BOARD_XOSC1_CFDEN FALSE /* Clock failure detector not enabled */ +#define BOARD_XOSC1_SWBEN FALSE /* XOSC clock switch not enabled */ +#define BOARD_XOSC1_STARTUP 0 /* XOSC0 start-up time 31µs */ + +/* GCLK */ + +#define BOARD_GCLK_SET1 0x0020 /* Pre-configure: GCLK5 needed by DPLL0 */ +#define BOARD_GCLK_SET2 0x0fdf /* Post-configure: All GCLKs except GCLK5 */ + +#define BOARD_GCLK0_ENABLE TRUE /* Enable GCLK0 */ +#define BOARD_GCLK0_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK0_OE TRUE /* Generate output on GCLK_IO */ +#define BOARD_GCLK0_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK0_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK0_SOURCE 7 /* Select DPLL0 output as GCLK0 source */ +#define BOARD_GCLK0_DIV 1 /* Division factor */ + +#define BOARD_GCLK1_ENABLE TRUE /* Enable GCLK1 */ +#define BOARD_GCLK1_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK1_OE TRUE /* Generate output on GCLK_IO */ +#define BOARD_GCLK1_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK1_SOURCE 6 /* Select DFLL output as GCLK1 source */ +#define BOARD_GCLK1_DIV 1 /* Division factor */ + +#define BOARD_GCLK2_ENABLE FALSE /* Don't enable GCLK2 */ +#define BOARD_GCLK2_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK2_OE FALSE /* No generator output of GCLK_IO */ +#define BOARD_GCLK2_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK2_SOURCE 1 /* Select XOSC1 as GCLK2 source */ +#define BOARD_GCLK2_DIV 1 /* Division factor */ + +#define BOARD_GCLK3_ENABLE TRUE /* Enable GCLK3 */ +#define BOARD_GCLK3_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK3_OE FALSE /* No generator output of GCLK_IO */ +#define BOARD_GCLK3_RUNSTDBY FALSE /* Don't run in standby */ +#ifdef CONFIG_SAME54_XPLAINED_PRO_32KHZXTAL +# define BOARD_GCLK3_SOURCE 5 /* Select XOSC32K as GCLK3 source */ +#else +# define BOARD_GCLK3_SOURCE 4 /* Select OSCULP32K as GCLK3 source */ +#endif +#define BOARD_GCLK3_DIV 1 /* Division factor */ + +#define BOARD_GCLK4_ENABLE TRUE /* Enable GCLK4 */ +#define BOARD_GCLK4_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK4_OE TRUE /* Generate output on GCLK_IO */ +#define BOARD_GCLK4_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK4_SOURCE 7 /* Select DPLL0 output as GCLK4 source */ +#define BOARD_GCLK4_DIV 1 /* Division factor */ + +#define BOARD_GCLK5_ENABLE TRUE /* Enable GCLK5 */ +#define BOARD_GCLK5_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK5_OE TRUE /* Generate output on GCLK_IO */ +#define BOARD_GCLK5_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK5_SOURCE 6 /* Select DFLL output as GCLK5 source */ +#define BOARD_GCLK5_DIV 24 /* Division factor */ + +#define BOARD_GCLK6_ENABLE FALSE /* Don't enable GCLK6 */ +#define BOARD_GCLK6_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK6_OE FALSE /* No generator output of GCLK_IO */ +#define BOARD_GCLK6_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK6_SOURCE 1 /* Select XOSC1 as GCLK6 source */ +#define BOARD_GCLK6_DIV 1 /* Division factor */ + +#define BOARD_GCLK7_ENABLE FALSE /* Don't enable GCLK7 */ +#define BOARD_GCLK7_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK7_OE FALSE /* No generator output of GCLK_IO */ +#define BOARD_GCLK7_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK7_SOURCE 1 /* Select XOSC1 as GCLK7 source */ +#define BOARD_GCLK7_DIV 1 /* Division factor */ + +#define BOARD_GCLK8_ENABLE FALSE /* Don't enable GCLK8 */ +#define BOARD_GCLK8_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK8_OE FALSE /* No generator output of GCLK_IO */ +#define BOARD_GCLK8_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK8_SOURCE 1 /* Select XOSC1 as GCLK8 source */ +#define BOARD_GCLK8_DIV 1 /* Division factor */ + +#define BOARD_GCLK9_ENABLE FALSE /* Don't enable GCLK9 */ +#define BOARD_GCLK9_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK9_OE FALSE /* No generator output of GCLK_IO */ +#define BOARD_GCLK9_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK9_SOURCE 1 /* Select XOSC1 as GCLK9 source */ +#define BOARD_GCLK9_DIV 1 /* Division factor */ + +#define BOARD_GCLK10_ENABLE FALSE /* Don't enable GCLK10 */ +#define BOARD_GCLK10_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK10_OE FALSE /* No generator output of GCLK_IO */ +#define BOARD_GCLK10_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK10_SOURCE 1 /* Select XOSC1 as GCLK10 source */ +#define BOARD_GCLK10_DIV 1 /* Division factor */ + +#define BOARD_GCLK11_ENABLE FALSE /* Don't enable GCLK11 */ +#define BOARD_GCLK11_OOV FALSE /* Clock output will be LOW */ +#define BOARD_GCLK11_OE FALSE /* No generator output of GCLK_IO */ +#define BOARD_GCLK11_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_GCLK11_SOURCE 1 /* Select XOSC1 as GCLK11 source */ +#define BOARD_GCLK11_DIV 1 /* Division factor */ +#define BOARD_GCLK11_FREQUENCY BOARD_XOSC1_FREQUENCY + +/* FDLL */ + +#define BOARD_DFLL_ENABLE TRUE /* DFLL enable */ +#define BOARD_DFLL_RUNSTDBY FALSE /* Don't run in standby */ +#define BOARD_DFLL_ONDEMAND FALSE /* No n-demand control */ +#define BOARD_DFLL_MODE FALSE /* Open loop mode */ +#define BOARD_DFLL_STABLE FALSE /* No stable DFLL frequency */ +#define BOARD_DFLL_LLAW FALSE /* Don't ose lock after wake */ +#define BOARD_DFLL_USBCRM TRUE /* Use USB clock recovery mode */ +#define BOARD_DFLL_CCDIS TRUE /* Chill cycle disable */ +#define BOARD_DFLL_QLDIS FALSE /* No Quick Lock Disable */ +#define BOARD_DFLL_BPLCKC FALSE /* No ypass coarse clock */ +#define BOARD_DFLL_WAITLOCK TRUE /* Wait lock */ +#define BOARD_DFLL_CALIBEN FALSE /* Don't verwrite factory calibration */ +#define BOARD_DFLL_GCLKLOCK FALSE /* Don't lock the GCLK source */ +#define BOARD_DFLL_FCALIB 128 /* Coarse calibration value (if caliben) */ +#define BOARD_DFLL_CCALIB (31 / 4) /* Fine calibration value (if caliben) */ +#define BOARD_DFLL_FSTEP 1 /* Fine maximum step */ +#define BOARD_DFLL_CSTEP 1 /* Coarse maximum step */ +#define BOARD_DFLL_GCLK 3 /* GCLK source (if !usbcrm && !mode) */ +#define BOARD_DFLL_MUL 0 /* DFLL multiply factor */ + +/* DPLL0/1 + * + * Fckr is the frequency of the selected reference clock reference: + * + * BOARD_XOSC32K_FREQENCY, + * BOARD_XOSCn_FREQUENCY / DIV, or + * BOARD_GCLKn_FREQUENCY + * + * The DPLL output frequency is then given by: + * + * Fdpll = Fckr * (LDR + 1 + LDRFRAC / 32) + * + * DPLL0: + * Fckr = BOARD_GCLK5_FREQUENCY = BOARD_DFLL_FREQUENCY / 24 = 2MHz + * Fdpll = 2Mhz * (59 + 1 + 0 / 32) = 120MHz + * + * DPLL1: (not enabled) + * Fckr = BOARD_XOSCK32_FREQUENCY = 32.768KHz + * Fdpll = 32768 * (1463 + 1 + 13/32) = 47.986 MHz + */ + +#define BOARD_DPLL0_ENABLE TRUE /* DPLL enable */ +#define BOARD_DPLL0_DCOEN FALSE /* DCO filter enable */ +#define BOARD_DPLL0_LBYPASS FALSE /* Lock bypass */ +#define BOARD_DPLL0_WUF FALSE /* Wake up fast */ +#define BOARD_DPLL0_RUNSTDBY FALSE /* Run in standby */ +#define BOARD_DPLL0_ONDEMAND FALSE /* On demand clock activation */ +#define BOARD_DPLL0_REFLOCK FALSE /* Do not lock reference clock section */ +#define BOARD_DPLL0_REFCLK 0 /* Reference clock selection */ +#define BOARD_DPLL0_LTIME 0 /* Lock time */ +#define BOARD_DPLL0_FILTER 0 /* Proportional integer filter selection */ +#define BOARD_DPLL0_DCOFILTER 0 /* Sigma-delta DCO filter selection */ +#define BOARD_DPLL0_GCLK 5 /* GCLK source (if refclock == 0) */ +#define BOARD_DPLL0_GCLKLOCK 0 /* Don't lock GCLK source clock configuration */ +#define BOARD_DPLL0_LDRFRAC 0 /* Loop divider fractional part */ +#define BOARD_DPLL0_LDRINT 59 /* Loop divider ratio */ +#define BOARD_DPLL0_DIV 0 /* Clock divider */ + +#define BOARD_DPLL1_ENABLE FALSE /* DPLL enable */ +#define BOARD_DPLL1_DCOEN FALSE /* DCO filter enable */ +#define BOARD_DPLL1_LBYPASS FALSE /* Lock bypass */ +#define BOARD_DPLL1_WUF FALSE /* Wake up fast */ +#define BOARD_DPLL1_RUNSTDBY FALSE /* Run in standby */ +#define BOARD_DPLL1_ONDEMAND FALSE /* On demand clock activation */ +#define BOARD_DPLL1_REFLOCK FALSE /* Do not lock reference clock section */ +#define BOARD_DPLL1_REFCLK 1 /* Reference clock = XOSCK32 */ +#define BOARD_DPLL1_LTIME 0 /* Lock time */ +#define BOARD_DPLL1_FILTER 0 /* Sigma-delta DCO filter selection */ +#define BOARD_DPLL1_DCOFILTER 0 /* Sigma-delta DCO filter selection */ +#define BOARD_DPLL1_GCLK 0 /* GCLK source (if refclock == 0) */ +#define BOARD_DPLL1_GCLKLOCK 0 /* Don't lock GCLK source clock configuration */ +#define BOARD_DPLL1_LDRFRAC 13 /* Loop divider fractional part */ +#define BOARD_DPLL1_LDRINT 1463 /* Loop divider ratio */ +#define BOARD_DPLL1_DIV 0 /* Clock divider */ + +/* Master Clock (MCLK) + * + * GCLK0 is always the direct source the GCLK_MAIN. + * CPU frequency = 120MHz / 1 = 120MHz + */ + +#define BOARD_MCLK_CPUDIV 1 /* MCLK divder to get CPU frequency */ + +#define BOARD_MCK_FREQUENCY BOARD_GCLK0_FREQUENCY + +/* Peripheral clocking */ + +#define BOARD_GCLK_EIC 4 /* EIC GCLK index */ + +/* FLASH wait states + * + * Vdd Range Wait states Maximum Operating Frequency + * --------- ----------- --------------------------- + * > 2.7V 0 24 MHz + * 1 51 MHz + * 2 77 MHz + * 3 101 MHz + * 4 119 MHz + * 5 120 MHz + * >1.71V 0 22 MHz + * 1 44 MHz + * 2 67 MHz + * 3 89 MHz + * 4 111 MHz + * 5 120 MHz + */ + +#define BOARD_FLASH_WAITSTATES 6 + +/* LED definitions **********************************************************/ + +/* LEDs + * + * The SAME54 Xplained Pro has three LEDs, but only one is controllable by software: + * + * 1. LED0 near the edge of the board + * + * + * ----------------- ----------- + * SAMD5E5 FUNCTION + * ----------------- ----------- + * PC18 GPIO output + * + */ + +/* LED index values for use with board_userled() */ + +#define BOARD_LED0 0 +#define BOARD_NLEDS 1 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED0_BIT (1 << BOARD_LED0) + +/* This LED is not used by the board port unless CONFIG_ARCH_LEDS is + * defined. In that case, the usage by the board port is defined in + * include/board.h and src/sam_autoleds.c. The LEDs are used to encode + * OS-related events as follows: + * + * ------------------- ---------------------------- ------ + * SYMBOL Meaning LED + * ------------------- ---------------------------- ------ + */ + +#define LED_STARTED 0 /* NuttX has been started OFF */ +#define LED_HEAPALLOCATE 0 /* Heap has been allocated OFF */ +#define LED_IRQSENABLED 0 /* Interrupts enabled OFF */ +#define LED_STACKCREATED 1 /* Idle stack created ON */ +#define LED_INIRQ 2 /* In an interrupt N/C */ +#define LED_SIGNAL 2 /* In a signal handler N/C */ +#define LED_ASSERTION 2 /* An assertion failed N/C */ +#define LED_PANIC 3 /* The system has crashed FLASH */ +#undef LED_IDLE /* MCU is is sleep mode Not used */ + +/* Thus is LED is statically on, NuttX has successfully booted and is, + * apparently, running normally. If LED is flashing at approximately + * 2Hz, then a fatal error has been detected and the system has halted. + */ + +/* Alternate function pin selections ****************************************/ + +/* SERCOM definitions *******************************************************/ + +/* The SERCOM bus clock (CLK_SERCOMx_APB) can be enabled and disabled in the + * Main Clock Controller. + * The SERCOM uses two generic clocks: GCLK_SERCOMn_CORE and GCLK_SERCOM_SLOW. + * The core clock (GCLK_SERCOMx_CORE) is required to clock the SERCOM while + * working as a master. The slow clock (GCLK_SERCOM_SLOW) is only required + * for certain functions and is common to all SERCOM modules. + * + * These clocks must be configured and enabled in the Generic Clock + * Controller (GCLK) before using the SERCOM. + */ + +#define BOARD_SERCOM_SLOWGEN 3 /* 32.768KHz, common to all SERCOMS */ +#define BOARD_SERCOM_SLOWLOCK FALSE /* Don't lock the SLOWCLOCK */ +#define BOARD_SLOWCLOCK_FREQUENCY BOARD_GCLK3_FREQUENCY + +/* SERCOM2 + * + * Built-in virtual COM port using the EDBG chip on the board. + * DTR must be asserted by your console software in order to enable this port. + * + * ----------------- --------- + * SAMD5E5 FUNCTION + * ----------------- --------- + * PB24 SERCOM2 PAD1 RXD + * PB25 SERCOM2 PAD0 TXD + * + * NOTES: + * USART_CTRLA_TXPAD0_2: TxD=PAD0 XCK=N/A RTS/TE=PAD2 CTS=PAD3 + * USART_CTRLA_RXPAD1: RxD=PAD1 + */ + +#define BOARD_SERCOM2_MUXCONFIG (USART_CTRLA_TXPAD0_2 | USART_CTRLA_RXPAD1) +#define BOARD_SERCOM2_PINMAP_PAD0 PORT_SERCOM2_PAD0_4 /* PAD0: USART TX */ +#define BOARD_SERCOM2_PINMAP_PAD1 PORT_SERCOM2_PAD1_4 /* PAD1: USART RX */ +#define BOARD_SERCOM2_PINMAP_PAD2 0 /* PAD2: (not used) */ +#define BOARD_SERCOM2_PINMAP_PAD3 0 /* PAD3: (not used) */ + +#define BOARD_TXIRQ_SERCOM2 SAM_IRQ_SERCOM2_0 /* INTFLAG[0] DRE */ +#define BOARD_RXIRQ_SERCOM2 SAM_IRQ_SERCOM2_2 /* INTFLAG[2] RXC */ + +#define BOARD_SERCOM2_COREGEN 1 /* 48MHz Core clock */ +#define BOARD_SERCOM2_CORELOCK FALSE /* Don't lock the CORECLOCK */ +#define BOARD_SERCOM2_FREQUENCY BOARD_GCLK1_FREQUENCY + +/* SERCOM3 + * + * An external RS-232 or serial-to-USB adapter can be connected on pins PA22 + * and PA23: + * + * ----------------- --------- + * SAMD5E5 FUNCTION + * ----------------- --------- + * PA23 SERCOM3 PAD1 RXD + * PA22 SERCOM3 PAD0 TXD + * + * NOTES: + * USART_CTRLA_TXPAD0_2: TxD=PAD0 XCK=N/A RTS/TE=PAD2 CTS=PAD3 + * USART_CTRLA_RXPAD1: RxD=PAD1 + */ + +#define BOARD_SERCOM3_MUXCONFIG (USART_CTRLA_TXPAD0_2 | USART_CTRLA_RXPAD1) +#define BOARD_SERCOM3_PINMAP_PAD0 PORT_SERCOM3_PAD0_1 /* PAD0: USART TX */ +#define BOARD_SERCOM3_PINMAP_PAD1 PORT_SERCOM3_PAD1_1 /* PAD1: USART RX */ +#define BOARD_SERCOM3_PINMAP_PAD2 0 /* PAD2: (not used) */ +#define BOARD_SERCOM3_PINMAP_PAD3 0 /* PAD3: (not used) */ + +#define BOARD_TXIRQ_SERCOM3 SAM_IRQ_SERCOM3_0 /* INTFLAG[0] DRE */ +#define BOARD_RXIRQ_SERCOM3 SAM_IRQ_SERCOM3_2 /* INTFLAG[2] RXC */ + +#define BOARD_SERCOM3_COREGEN 1 /* 48MHz Core clock */ +#define BOARD_SERCOM3_CORELOCK FALSE /* Don't lock the CORECLOCK */ +#define BOARD_SERCOM3_FREQUENCY BOARD_GCLK1_FREQUENCY + +/* USB */ + +#define BOARD_USB_GCLKGEN 1 /* GCLK1, 48MHz */ + +/* Ethernet */ + +#define BOARD_GMAC_GMDC PORT_GMAC_GMDC_3 +#define BOARD_GMAC_GMDIO PORT_GMAC_GMDIO_3 + +#endif /* __BOARDS_ARM_SAMD5E5_SAME54_XPLAINED_PRO_INCLUDE_BOARD_H */ diff --git a/boards/arm/samd5e5/same54-xplained-pro/scripts/Make.defs b/boards/arm/samd5e5/same54-xplained-pro/scripts/Make.defs new file mode 100644 index 0000000000..f9ecb17264 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/scripts/Make.defs @@ -0,0 +1,128 @@ +############################################################################ +# boards/arm/samd5e5/same54-xplained-pro/scripts/Make.defs +# +# Copyright (C) 2018 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS 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. +# +############################################################################ + +include ${TOPDIR}/.config +include ${TOPDIR}/tools/Config.mk +include ${TOPDIR}/arch/arm/src/armv7-m/Toolchain.defs + +ifeq ($(CONFIG_SAME54_XPLAINED_PRO_RUNFROMFLASH),y) + LDSCRIPT = flash.ld +else ifeq ($(CONFIG_SAME54_XPLAINED_PRO_RUNFROMSRAM),y) + LDSCRIPT = sram.ld +endif + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + DIRLINK = $(TOPDIR)/tools/copydir.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mkwindeps.sh + ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" + ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" -isystem "${shell cygpath -w $(TOPDIR)/include/cxx}" + ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT)}" +else + # Linux/Cygwin-native toolchain + MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT) + ARCHINCLUDES = -I. -isystem $(TOPDIR)/include + ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx + ARCHSCRIPT = -T$(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT) +endif + +CC = $(CROSSDEV)gcc +CXX = $(CROSSDEV)g++ +CPP = $(CROSSDEV)gcc -E +LD = $(CROSSDEV)ld +STRIP = $(CROSSDEV)strip --strip-unneeded +AR = $(ARCROSSDEV)ar rcs +NM = $(ARCROSSDEV)nm +OBJCOPY = $(CROSSDEV)objcopy +OBJDUMP = $(CROSSDEV)objdump + +ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'} +ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1} + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + ARCHOPTIMIZATION = -g +endif + +ifneq ($(CONFIG_DEBUG_NOOPT),y) + ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer +endif + +ARCHCFLAGS = -fno-builtin +ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fno-rtti +ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef +ARCHWARNINGSXX = -Wall -Wshadow -Wundef +ARCHDEFINES = +ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 + +CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) +AFLAGS = $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +# Loadable module definitions + +CMODULEFLAGS = $(CFLAGS) -mlong-calls # --target1-abs + +LDMODULEFLAGS = -r -e module_initialize +ifeq ($(WINTOOL),y) + LDMODULEFLAGS += -T "${shell cygpath -w $(TOPDIR)/libs/libc/modlib/gnu-elf.ld}" +else + LDMODULEFLAGS += -T $(TOPDIR)/libs/libc/modlib/gnu-elf.ld +endif + +ASMEXT = .S +OBJEXT = .o +LIBEXT = .a +EXEEXT = + +ifneq ($(CROSSDEV),arm-nuttx-elf-) + LDFLAGS += -nostartfiles -nodefaultlibs +endif +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + LDFLAGS += -g +endif + + +HOSTCC = gcc +HOSTINCLUDES = -I. +HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe +HOSTLDFLAGS = diff --git a/boards/arm/samd5e5/same54-xplained-pro/scripts/flash.ld b/boards/arm/samd5e5/same54-xplained-pro/scripts/flash.ld new file mode 100644 index 0000000000..4a4c9e2bb7 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/scripts/flash.ld @@ -0,0 +1,123 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/scripts/flash.ld + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/* The ATSAME54P20A has 1024Kb of FLASH beginning at address 0x0000:0000 and + * 256Kb of SRAM at address 0x2000:0000. + */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x00000000, LENGTH = 1024K + sram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K +} + +OUTPUT_ARCH(arm) +ENTRY(_stext) +EXTERN(_vectors) +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : + { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : + { + *(.ARM.extab*) + } > flash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : + { + *(.ARM.exidx*) + } > flash + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/samd5e5/same54-xplained-pro/scripts/nvm.c b/boards/arm/samd5e5/same54-xplained-pro/scripts/nvm.c new file mode 100644 index 0000000000..c30c14c2a3 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/scripts/nvm.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/scripts/nvm.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt 9 + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t nvm[20] = +{ + 0x14, /* Count 20 bytes */ + 0x80, 0x40, 0x00, /* 24-address : 804000 */ + 0x39, 0x92, 0x9a, 0xfe, 0x80, 0xff, 0xec, 0xae, /* 16-bytes of NVM data */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv) +{ + unsigned int csum; + int i; + + printf("S2"); + + for (i = 0, csum = 0; i < 20; i++) + { + csum += nvm[i]; + printf("%02X", (unsigned int)nvm[i]); + } + + printf("%02X\r\n", ~csum & 0xff); + printf("S9030000FC\r\n"); + return 0; +} diff --git a/boards/arm/samd5e5/same54-xplained-pro/scripts/nvm.srec b/boards/arm/samd5e5/same54-xplained-pro/scripts/nvm.srec new file mode 100644 index 0000000000..dbe95235e5 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/scripts/nvm.srec @@ -0,0 +1,2 @@ +S21480400039929AFE80FFECAEFFFFFFFFFFFFFFFFB7 +S9030000FC diff --git a/boards/arm/samd5e5/same54-xplained-pro/scripts/sram.ld b/boards/arm/samd5e5/same54-xplained-pro/scripts/sram.ld new file mode 100644 index 0000000000..f7b19a4bd7 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/scripts/sram.ld @@ -0,0 +1,122 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/scripts/sram.ld + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/* The ATSAME54P20A has 1024Kb of FLASH beginning at address 0x0000:0000 and + * 256Kb of SRAM at address 0x2000:0000. Only sram is used by this linker + * script. + */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x00000000, LENGTH = 1024K + sram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K +} + +OUTPUT_ARCH(arm) +ENTRY(_stext) +EXTERN(_vectors) +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > sram + + .init_section : + { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > sram + + .ARM.extab : + { + *(.ARM.extab*) + } > sram + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : + { + *(.ARM.exidx*) + } > sram + __exidx_end = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/samd5e5/same54-xplained-pro/src/Makefile b/boards/arm/samd5e5/same54-xplained-pro/src/Makefile new file mode 100644 index 0000000000..f53cae73c0 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/src/Makefile @@ -0,0 +1,55 @@ +############################################################################ +# boards/arm/samd5e5/same54-xplained-pro/src/Makefile +# +# Copyright (C) 2018 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS 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. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +CSRCS = sam_boot.c sam_bringup.c + +ifeq ($(CONFIG_LIB_BOARDCTL),y) +CSRCS += sam_appinit.c +endif + +ifeq ($(CONFIG_ARCH_LEDS),y) +CSRCS += sam_autoleds.c +else +CSRCS += sam_userleds.c +endif + +ifeq ($(CONFIG_SAMD5E5_GMAC_PHYINIT), y) +CSRCS += sam_phyinit.c +endif + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/samd5e5/same54-xplained-pro/src/sam_appinit.c b/boards/arm/samd5e5/same54-xplained-pro/src/sam_appinit.c new file mode 100644 index 0000000000..261a846b85 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/src/sam_appinit.c @@ -0,0 +1,94 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/src/sam_appinit.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "same54-xplained-pro.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef OK +# define OK 0 +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value cold be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ +#ifdef CONFIG_BOARD_LATE_INITIALIZE + /* Board initialization already performed by board_late_initialize() */ + + return OK; +#else + /* Perform board-specific initialization */ + + return sam_bringup(); +#endif +} diff --git a/boards/arm/samd5e5/same54-xplained-pro/src/sam_autoleds.c b/boards/arm/samd5e5/same54-xplained-pro/src/sam_autoleds.c new file mode 100644 index 0000000000..5ebec70d68 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/src/sam_autoleds.c @@ -0,0 +1,295 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/src/sam_autoleds.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/* The SAME54 Xplained Pro has three LEDs, but only one is controllable by software: + * + * 1. LED0 near the edge of the board + * + * ----------------- ----------- + * SAMD5E5 FUNCTION + * ----------------- ----------- + * PC18 GPIO output + * + * This LED is not used by the board port unless CONFIG_ARCH_LEDS is + * defined. In that case, the usage by the board port is defined in + * include/board.h and src/sam_autoleds.c. The LEDs are used to encode + * OS-related events as follows: + * + * ------------------- ---------------------------- ------ + * SYMBOL Meaning LED + * ------------------- ---------------------------- ------ + * + * LED_STARTED NuttX has been started OFF + * LED_HEAPALLOCATE Heap has been allocated OFF + * LED_IRQSENABLED Interrupts enabled OFF + * LED_STACKCREATED Idle stack created ON + * LED_INIRQ In an interrupt N/C + * LED_SIGNAL In a signal handler N/C + * LED_ASSERTION An assertion failed N/C + * LED_PANIC The system has crashed FLASH + * LED_IDLE MCU is is sleep mode Not used + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "sam_port.h" +#include "same54-xplained-pro.h" + +#include + +#ifdef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* LED Power Management */ + +#ifdef CONFIG_PM +static void led_pm_notify(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +static int led_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_PM +static struct pm_callback_s g_ledscb = +{ + .notify = led_pm_notify, + .prepare = led_pm_prepare, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: led_pm_notify + * + * Description: + * Notify the driver of new power state. This callback is called after + * all drivers have had the opportunity to prepare for the new power state. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void led_pm_notify(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + switch (pmstate) + { + case(PM_NORMAL): + { + /* Restore normal LEDs operation */ + } + break; + + case(PM_IDLE): + { + /* Entering IDLE mode - Turn leds off */ + } + break; + + case(PM_STANDBY): + { + /* Entering STANDBY mode - Logic for PM_STANDBY goes here */ + } + break; + + case(PM_SLEEP): + { + /* Entering SLEEP mode - Logic for PM_SLEEP goes here */ + } + break; + + default: + { + /* Should not get here */ + } + break; + } +} +#endif + +/**************************************************************************** + * Name: led_pm_prepare + * + * Description: + * Request the driver to prepare for a new power state. This is a warning + * that the system is about to enter into a new power state. The driver + * should begin whatever operations that may be required to enter power + * state. The driver may abort the state change mode by returning a + * non-zero value from the callback function. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static int led_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + /* No preparation to change power modes is required by the LEDs driver. + * We always accept the state change by returning OK. + */ + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_autoled_initialize + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + (void)sam_portconfig(PORT_LED0); +} + +/**************************************************************************** + * Name: board_autoled_on + ****************************************************************************/ + +void board_autoled_on(int led) +{ + bool ledstate = true; + + switch (led) + { + case 0: /* LED_STARTED: NuttX has been started STATUS LED=OFF + * LED_HEAPALLOCATE: Heap has been allocated STATUS LED=OFF + * LED_IRQSENABLED: Interrupts enabled STATUS LED=OFF + */ + + break; /* Leave ledstate == true to turn OFF */ + + default: + case 2: /* LED_INIRQ: In an interrupt STATUS LED=N/C + * LED_SIGNAL: In a signal handler STATUS LED=N/C + * LED_ASSERTION: An assertion failed STATUS LED=N/C + */ + + return; /* Return to leave STATUS LED unchanged */ + + case 3: /* LED_PANIC: The system has crashed STATUS LED=FLASH */ + case 1: /* LED_STACKCREATED: Idle stack created STATUS LED=ON */ + ledstate = false; /* Set ledstate == false to turn ON */ + break; + } + + sam_portwrite(PORT_LED0, ledstate); +} + +/**************************************************************************** + * Name: board_autoled_off + ****************************************************************************/ + +void board_autoled_off(int led) +{ + switch (led) + { + /* These should not happen and are ignored */ + + default: + case 0: /* LED_STARTED: NuttX has been started STATUS LED=OFF + * LED_HEAPALLOCATE: Heap has been allocated STATUS LED=OFF + * LED_IRQSENABLED: Interrupts enabled STATUS LED=OFF + */ + + case 1: /* LED_STACKCREATED: Idle stack created STATUS LED=ON */ + + /* These result in no-change */ + + case 2: /* LED_INIRQ: In an interrupt STATUS LED=N/C + * LED_SIGNAL: In a signal handler STATUS LED=N/C + * LED_ASSERTION: An assertion failed STATUS LED=N/C + */ + + return; /* Return to leave STATUS LED unchanged */ + + /* Turn STATUS LED off set driving the output high */ + + case 3: /* LED_PANIC: The system has crashed STATUS LED=FLASH */ + sam_portwrite(PORT_LED0, true); + break; + } +} + +/**************************************************************************** + * Name: sam_led_pminitialize + * + * Description: + * Register LED power management features. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +void sam_led_pminitialize(void) +{ + /* Register to receive power management callbacks */ + + int ret = pm_register(&g_ledscb); + if (ret != OK) + { + board_autoled_on(LED_ASSERTION); + } +} +#endif /* CONFIG_PM */ + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/arm/samd5e5/same54-xplained-pro/src/sam_boot.c b/boards/arm/samd5e5/same54-xplained-pro/src/sam_boot.c new file mode 100644 index 0000000000..8e713a6765 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/src/sam_boot.c @@ -0,0 +1,94 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/src/sam_boot.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "same54-xplained-pro.h" + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sam_board_initialize + * + * Description: + * All SAMD5/E5 architectures must provide the following entry point. + * This entry point is called early in the initialization -- after all + * memory has been configured and mapped but before any devices have been + * initialized. + * + ****************************************************************************/ + +void sam_board_initialize(void) +{ +#ifdef CONFIG_ARCH_LEDS + /* Configure on-board LEDs if LED support has been selected. */ + + board_autoled_initialize(); +#endif +} + +/**************************************************************************** + * Name: board_late_initialize + * + * Description: + * If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional + * initialization call will be performed in the boot-up sequence to a + * function called board_late_initialize(). board_late_initialize() will be + * called immediately after up_initialize() is called and just before the + * initial application is started. This additional initialization phase + * may be used, for example, to initialize board-specific device drivers. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ + /* Perform board-specific initialization */ + + (void)sam_bringup(); +} +#endif diff --git a/boards/arm/samd5e5/same54-xplained-pro/src/sam_bringup.c b/boards/arm/samd5e5/same54-xplained-pro/src/sam_bringup.c new file mode 100644 index 0000000000..b2ea8a3864 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/src/sam_bringup.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/src/sam_bringup.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "same54-xplained-pro.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PROCFS_MOUNTPOINT "/proc" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sam_bringup + * + * Description: + * Perform architecture-specific initialization + * + * CONFIG_BOARD_LATE_INITIALIZE=y : + * Called from board_late_initialize(). + * + * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_LIB_BOARDCTL=y : + * Called from the NSH library + * + ****************************************************************************/ + +int sam_bringup(void) +{ + int ret = OK; + +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = mount(NULL, PROCFS_MOUNTPOINT, "procfs", 0, NULL); + if (ret < 0) + { + syslot(LOG_ERR, "ERROR: Failed to mount procfs at %s: %d\n", + PROCFS_MOUNTPOINT, ret); + } +#endif + + UNUSED(ret); + return OK; +} diff --git a/boards/arm/samd5e5/same54-xplained-pro/src/sam_phyinit.c b/boards/arm/samd5e5/same54-xplained-pro/src/sam_phyinit.c new file mode 100644 index 0000000000..cd42075da2 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/src/sam_phyinit.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/src/sam_phyinit.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Darcy Gong + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "sam_port.h" +#include "sam_ethernet.h" + +#include "same54-xplained-pro.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#if defined(CONFIG_ETH0_PHY_KSZ8081) && defined(CONFIG_SAMD5E5_GMAC_PHYINIT) +int sam_phy_boardinitialize(int intf) +{ + /* Configure the KSZ8081 PHY reset pin and take it out of reset */ + + sam_portconfig(PORT_PHY_RESET); + return 0; +} +#endif + diff --git a/boards/arm/samd5e5/same54-xplained-pro/src/sam_userleds.c b/boards/arm/samd5e5/same54-xplained-pro/src/sam_userleds.c new file mode 100644 index 0000000000..36d3c20950 --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/src/sam_userleds.c @@ -0,0 +1,229 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/src/sam_userleds.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/* The SAME54 Xplained Pro has three LEDs, but only one is controllable by software: + * + * 1. LED0 near the edge of the board + * + * ----------------- ----------- + * SAMD5E5 FUNCTION + * ----------------- ----------- + * PC18 GPIO output + * + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "up_arch.h" +#include "sam_port.h" + +#include "same54-xplained-pro.h" + +#include + +#ifndef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* LED Power Management */ + +#ifdef CONFIG_PM +static void led_pm_notify(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +static int led_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_PM +static struct pm_callback_s g_ledscb = +{ + .notify = led_pm_notify, + .prepare = led_pm_prepare, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: led_pm_notify + * + * Description: + * Notify the driver of new power state. This callback is called after + * all drivers have had the opportunity to prepare for the new power state. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void led_pm_notify(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + switch (pmstate) + { + case(PM_NORMAL): + { + /* Restore normal LEDs operation */ + } + break; + + case(PM_IDLE): + { + /* Entering IDLE mode - Turn leds off */ + } + break; + + case(PM_STANDBY): + { + /* Entering STANDBY mode - Logic for PM_STANDBY goes here */ + } + break; + + case(PM_SLEEP): + { + /* Entering SLEEP mode - Logic for PM_SLEEP goes here */ + } + break; + + default: + { + /* Should not get here */ + } + break; + } +} +#endif + +/**************************************************************************** + * Name: led_pm_prepare + * + * Description: + * Request the driver to prepare for a new power state. This is a warning + * that the system is about to enter into a new power state. The driver + * should begin whatever operations that may be required to enter power + * state. The driver may abort the state change mode by returning a + * non-zero value from the callback function. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static int led_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + /* No preparation to change power modes is required by the LEDs driver. + * We always accept the state change by returning OK. + */ + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_userled_initialize + ****************************************************************************/ + +void board_userled_initialize(void) +{ + (void)sam_portconfig(PORT_STATUS_LED); +} + +/**************************************************************************** + * Name: board_userled + ****************************************************************************/ + +void board_userled(int led, bool ledon) +{ + if (led == BOARD_STATUS_LED) + { + sam_portwrite(PORT_STATUS_LED, !ledon); + } +} + +/**************************************************************************** + * Name: board_userled_all + ****************************************************************************/ + +void board_userled_all(uint8_t ledset) +{ + board_userled(BOARD_STATUS_LED, (ledset & BOARD_STATUS_LED_BIT) != 0); +} + +/**************************************************************************** + * Name: sam_led_pminitialize + * + * Description: + * Register LED power management features. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +void sam_led_pminitialize(void) +{ + /* Register to receive power management callbacks */ + + int ret = pm_register(&g_ledscb); + if (ret != OK) + { + board_autoled_on(LED_ASSERTION); + } +} +#endif /* CONFIG_PM */ + +#endif /* !CONFIG_ARCH_LEDS */ diff --git a/boards/arm/samd5e5/same54-xplained-pro/src/same54-xplained-pro.h b/boards/arm/samd5e5/same54-xplained-pro/src/same54-xplained-pro.h new file mode 100644 index 0000000000..e467c660fd --- /dev/null +++ b/boards/arm/samd5e5/same54-xplained-pro/src/same54-xplained-pro.h @@ -0,0 +1,128 @@ +/**************************************************************************** + * boards/arm/samd5e5/same54-xplained-pro/src/same54-xplained-pro.h + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_SAMD5E5_SAME54_XPLAINED_PRO_SRC_SAME54_XPLAINED_PRO_H +#define __BOARDS_ARM_SAMD5E5_SAME54_XPLAINED_PRO_SRC_SAME54_XPLAINED_PRO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Metro-M4 GPIOs ***********************************************************/ + +/* LEDs + * + * The SAME54 Xplained Pro has three LEDs, but only one is controllable by software: + * + * 1. LED0 near the edge of the board + * + * + * ----------------- ----------- + * SAMD5E5 FUNCTION + * ----------------- ----------- + * PC18 GPIO output + * + */ + +#define PORT_LED0 (PORT_OUTPUT | PORT_PULL_NONE | PORT_OUTPUT_SET | \ + PORTC | PORT_PIN18) +/* Ethernet *****************************************************************/ + +/* PHY pins: + * + * -------- ----------------- ----------- + * PHY SAMD5E5 FUNCTION + * -------- ----------------- ----------- + * Reset PD12 GPIO output + * IRQ PC21 GPIO input + */ + +#define PORT_PHY_RESET (PORT_OUTPUT | PORT_PULL_NONE | PORT_OUTPUT_SET | \ + PORTD | PORT_PIN12) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sam_bringup + * + * Description: + * Perform architecture-specific initialization + * + * CONFIG_BOARD_LATE_INITIALIZE=y : + * Called from board_late_initialize(). + * + * CONFIG_BOARD_LATE_INITIALIZE=y && CONFIG_LIB_BOARDCTL=y : + * Called from the NSH library + * + ****************************************************************************/ + +int sam_bringup(void); + +/**************************************************************************** + * Name: sam_led_pminitialize + * + * Description: + * Register LED power management features. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +void sam_led_pminitialize(void); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM_SAMD5E5_SAME54_XPLAINED_PRO_SRC_SAME54_XPLAINED_PRO_H */