diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0b44c79f2b2..2ba434667da 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -227,6 +227,7 @@ config ARCH_CHIP_MOXART bool "MoxART" select ARCH_ARM7TDMI select ARCH_HAVE_RESET + select ARCH_HAVE_SERIAL_TERMIOS ---help--- MoxART family diff --git a/arch/arm/include/lpc43xx/chip.h b/arch/arm/include/lpc43xx/chip.h index 6168672ea89..390f96bd6c9 100644 --- a/arch/arm/include/lpc43xx/chip.h +++ b/arch/arm/include/lpc43xx/chip.h @@ -566,7 +566,7 @@ #define NVIC_SYSH_PRIORITY_MIN LPC43M4_SYSH_PRIORITY_MIN #define NVIC_SYSH_PRIORITY_DEFAULT LPC43M4_SYSH_PRIORITY_DEFAULT #define NVIC_SYSH_PRIORITY_MAX LPC43M4_SYSH_PRIORITY_MAX -#define NVIC_SYSH_PRIORITY_STEP LPC43M4_SYSH_PRIORITY_INCR +#define NVIC_SYSH_PRIORITY_STEP LPC43M4_SYSH_PRIORITY_STEP /* If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled * by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so that most diff --git a/arch/arm/include/moxart/irq.h b/arch/arm/include/moxart/irq.h index 31c92ed5d3b..238d47761ef 100644 --- a/arch/arm/include/moxart/irq.h +++ b/arch/arm/include/moxart/irq.h @@ -81,7 +81,8 @@ extern "C" #define IRQ_SYSTIMER 19 -#define NR_IRQS 32 +#define VIRQ_START 32 + +#define NR_IRQS (VIRQ_START+2) #endif /* __ARCH_ARM_INCLUDE_MOXART_IRQ_H */ - diff --git a/arch/arm/include/sama5/chip.h b/arch/arm/include/sama5/chip.h index 3e0d016d934..359086831c4 100644 --- a/arch/arm/include/sama5/chip.h +++ b/arch/arm/include/sama5/chip.h @@ -1,7 +1,7 @@ /**************************************************************************************************** * arch/arm/include/sama5/chip.h * - * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -45,6 +45,49 @@ /**************************************************************************************************** * Pre-processor Definitions ****************************************************************************************************/ +/* SAMA5D2 Family + * + * SAMA5D21 SAMA5D22 SAMA5D23 SAMA5D24 SAMA5D26 SAMA5D27 SAMA5D28 + * ------------------------- --------- --------- --------- --------- --------- --------- --------- + * Pin Count 196 196 196 256 289 289 289 + * Max. Operating Frequency 500 MHz 500 MHz 500 MHz 500 MHz 500 MHz 500 MHz 500 MHz + * CPU Cortex-A5 Cortex-A5 Cortex-A5 Cortex-A5 Cortex-A5 Cortex-A5 Cortex-A5 + * Max I/O Pins 72 72 72 105 128 128 128 + * USB Transceiver 1 1 1 1 1 1 1 + * USB Speed Hi-Speed Hi-Speed Hi-Speed Hi-Speed Hi-Speed Hi-Speed Hi-Speed + * USB Interface 2 2 2 3 3 3 3 + * SPI 6 6 6 7 7 7 7 + * QuadSPI 2 2 2 2 2 2 2 + * TWIHS (I2C) 6 6 6 7 7 7 7 + * UART 9 9 9 10 10 10 10 + * CAN - 1 1 - - 2 2 + * SDIO/SD/MMC 1 1 1 2 2 2 2 + * I2SC 2 2 2 2 2 2 2 + * SSC 2 2 2 2 2 2 2 + * Class D 1 1 1 2 2 2 2 + * PDMIC 1 1 1 2 2 2 2 + * Camera Interface 1 1 1 1 1 1 1 + * ADC Inputs 5 5 5 12 12 12 12 + * AESB - 1 1 1 - 1 1 + * SRAM (Kbytes) 128 128 128 128 128 128 128 + * DDR Bus 16-bit 16-bit 16-bit 16/32-bit 16/32-bit 16/32-bit 16/32-bit + * Timers 6 6 6 6 6 6 6 + * Tamper pins 6 6 6 2 8 8 8 + * Packages BGA196 BGA196 BGA196 BGA256 BGA289 BGA289 BGA289 + */ + +#if defined(CONFIG_ARCH_CHIP_ATSAMA5D21) || defined(CONFIG_ARCH_CHIP_ATSAMA5D22) || \ + defined(CONFIG_ARCH_CHIP_ATSAMA5D22) || defined(CONFIG_ARCH_CHIP_ATSAMA5D23) || \ + defined(CONFIG_ARCH_CHIP_ATSAMA5D24) || defined(CONFIG_ARCH_CHIP_ATSAMA5D26) || \ + defined(CONFIG_ARCH_CHIP_ATSAMA5D27) || defined(CONFIG_ARCH_CHIP_ATSAMA5D28) +# define ATSAMA5D2 1 /* SAMA5D2 family */ +# undef ATSAMA5D3 /* Not SAMA5D3 family */ +# undef ATSAMA5D4 /* Not SAMA5D4 family */ +# define SAM_ISRAM0_SIZE (64*1024) /* 128KB of SRAM in two banks */ +# define SAM_ISRAM1_SIZE (64*1024) +# define SAM_NDMAC 2 /* (2) XDMA controllers */ +# define SAM_NDMACHAN 16 /* (16) DMA channels per XDMA controller */ + /* SAMA5D3 Family * * ATSAMA5D31 ATSAMA5D33 ATSAMA5D34 ATSAMA5D35 ATSAMA5D36 @@ -91,7 +134,8 @@ * Packages LFBGA324_A LFBGA324_A LFBGA324_A LFBGA324_A LFBGA324_A */ -#if defined(CONFIG_ARCH_CHIP_ATSAMA5D31) +#elif defined(CONFIG_ARCH_CHIP_ATSAMA5D31) +# undef ATSAMA5D2 /* Not SAMA5D2 family */ # define ATSAMA5D3 1 /* SAMA5D3 family */ # undef ATSAMA5D4 /* Not SAMA5D4 family */ # define SAM_ISRAM0_SIZE (64*1024) /* 128KB of SRAM in two banks */ @@ -99,6 +143,7 @@ # define SAM_NDMAC 2 /* (2) DMA controllers */ # define SAM_NDMACHAN 8 /* (8) DMA channels per DMA controller */ #elif defined(CONFIG_ARCH_CHIP_ATSAMA5D33) +# undef ATSAMA5D2 /* Not SAMA5D2 family */ # define ATSAMA5D3 1 /* SAMA5D3 family */ # undef ATSAMA5D4 /* Not SAMA5D4 family */ # define SAM_ISRAM0_SIZE (64*1024) /* 128KB of SRAM in two banks */ @@ -106,6 +151,7 @@ # define SAM_NDMAC 2 /* (2) DMA controllers */ # define SAM_NDMACHAN 8 /* (8) DMA channels per DMA controller */ #elif defined(CONFIG_ARCH_CHIP_ATSAMA5D34) +# undef ATSAMA5D2 /* Not SAMA5D2 family */ # define ATSAMA5D3 1 /* SAMA5D3 family */ # undef ATSAMA5D4 /* Not SAMA5D4 family */ # define SAM_ISRAM0_SIZE (64*1024) /* 128KB of SRAM in two banks */ @@ -113,6 +159,7 @@ # define SAM_NDMAC 2 /* (2) DMA controllers */ # define SAM_NDMACHAN 8 /* (8) DMA channels per DMA controller */ #elif defined(CONFIG_ARCH_CHIP_ATSAMA5D35) +# undef ATSAMA5D2 /* Not SAMA5D2 family */ # define ATSAMA5D3 1 /* SAMA5D3 family */ # undef ATSAMA5D4 /* Not SAMA5D4 family */ # define SAM_ISRAM0_SIZE (64*1024) /* 128KB of SRAM in two banks */ @@ -120,6 +167,7 @@ # define SAM_NDMAC 2 /* (2) DMA controllers */ # define SAM_NDMACHAN 8 /* (8) DMA channels per DMA controller */ #elif defined(CONFIG_ARCH_CHIP_ATSAMA5D36) +# undef ATSAMA5D2 /* Not SAMA5D2 family */ # define ATSAMA5D3 1 /* SAMA5D3 family */ # undef ATSAMA5D4 /* Not SAMA5D4 family */ # define SAM_ISRAM0_SIZE (64*1024) /* 128KB of SRAM in two banks */ @@ -141,6 +189,7 @@ #elif defined(CONFIG_ARCH_CHIP_ATSAMA5D41) || defined(CONFIG_ARCH_CHIP_ATSAMA5D42) || \ defined(CONFIG_ARCH_CHIP_ATSAMA5D43) || defined(CONFIG_ARCH_CHIP_ATSAMA5D44) +# undef ATSAMA5D2 /* Not SAMA5D2 family */ # undef ATSAMA5D3 /* Not SAMA5D3 family */ # define ATSAMA5D4 1 /* SAMA5D4 family */ # define SAM_ISRAM0_SIZE (64*1024) /* 128KB of SRAM in two banks */ diff --git a/arch/arm/include/sama5/irq.h b/arch/arm/include/sama5/irq.h index 1cf5d453e4a..864f802d950 100644 --- a/arch/arm/include/sama5/irq.h +++ b/arch/arm/include/sama5/irq.h @@ -53,7 +53,9 @@ /* Chip-Specific External interrupts */ -#if defined(ATSAMA5D3) +#if defined(ATSAMA5D2) +# include +#elif defined(ATSAMA5D3) # include #elif defined(ATSAMA5D4) # include diff --git a/arch/arm/include/sama5/sama5d2_irq.h b/arch/arm/include/sama5/sama5d2_irq.h new file mode 100644 index 00000000000..fa378304d4e --- /dev/null +++ b/arch/arm/include/sama5/sama5d2_irq.h @@ -0,0 +1,424 @@ +/**************************************************************************************** + * arch/arm/include/sama5/sama5d2_irq.h + * + * Copyright (C) 2015 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. + * + ****************************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly through + * nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_SAMA5_SAMA5D2_IRQ_H +#define __ARCH_ARM_INCLUDE_SAMA5_SAMA5D2_IRQ_H + +/**************************************************************************************** + * Included Files + ****************************************************************************************/ + +/**************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************/ + +/* SAMA5D3 Peripheral Identifiers */ + +#define SAM_PID_FIQ (0) /* Advanced Interrupt Controller FIQ */ + /* 2 Reserved */ +#define SAM_PID_ARM (2) /* Performance Monitor Unit */ +#define SAM_PID_PIT (3) /* Periodic Interval Timer Interrupt */ +#define SAM_PID_WDT (4) /* Watchdog timer Interrupt */ +#define SAM_PID_EMAC0 (5) /* Ethernet MAC 0 */ +#define SAM_PID_XDMAC0 (6) /* DMA Controller 0 */ +#define SAM_PID_XDMAC1 (7) /* DMA Controller 1 */ +#define SAM_PID_ICM (8) /* Integrity Check Monitor */ +#define SAM_PID_AES (9) /* Advanced Encryption Standard */ + +#define SAM_PID_AESB (10) /* AES bridge */ +#define SAM_PID_TDES (11) /* Triple Data Encryption Standard */ +#define SAM_PID_SHA (12) /* Secure Hash Algorithm */ +#define SAM_PID_MPDDRC (13) /* MPDDR controller */ +#define SAM_PID_MATRIX1 (14) /* H32MX, 32-bit AHB Matrix */ +#define SAM_PID_MATRIX0 (15) /* H64MX, 64-bit AHB Matrix */ +#define SAM_PID_SECUMOD (16) /* Secure Module */ +#define SAM_PID_HSMC (17) /* Multi-bit ECC Interrupt */ +#define SAM_PID_PIOA (18) /* Parallel I/O Controller A */ +#define SAM_PID_FLEXCOM0 (19) /* FLEXCOM 0 */ + +#define SAM_PID_FLEXCOM1 (20) /* FLEXCOM 1 */ +#define SAM_PID_FLEXCOM2 (21) /* FLEXCOM 2 */ +#define SAM_PID_FLEXCOM3 (22) /* FLEXCOM 3 */ +#define SAM_PID_FLEXCOM4 (23) /* FLEXCOM 4 */ +#define SAM_PID_UART0 (24) /* UART 0 */ +#define SAM_PID_UART1 (25) /* UART 1 */ +#define SAM_PID_UART2 (26) /* UART 2 */ +#define SAM_PID_UART3 (27) /* UART 3 */ +#define SAM_PID_UART4 (28) /* UART 4 */ +#define SAM_PID_TWI0 (29) /* Two-Wire Interface 0 */ + +#define SAM_PID_TWI1 (30) /* Two-Wire Interface 1 */ +#define SAM_PID_SDMMC0 (31) /* Secure Data Memory Card Controller 0 */ +#define SAM_PID_SDMMC1 (32) /* Secure Data Memory Card Controller 1 */ +#define SAM_PID_SPI0 (33) /* Serial Peripheral Interface 0 */ +#define SAM_PID_SPI1 (34) /* Serial Peripheral Interface 1 */ +#define SAM_PID_TC0 (35) /* Timer Counter 0 (ch. 0, 1, 2) */ +#define SAM_PID_TC1 (36) /* Timer Counter 1 (ch. 3, 4, 5) */ + /* 37 Reserved */ +#define SAM_PID_PWM (38) /* Pulse Width Modulation Controller */ + /* 39 Reserved */ + +#define SAM_PID_ADC (40) /* Touch Screen ADC Controller */ +#define SAM_PID_UHPHS (41) /* USB Host High Speed */ +#define SAM_PID_UDPHS (42) /* USB Device High Speed */ +#define SAM_PID_SSC0 (43) /* Synchronous Serial Controller 0 */ +#define SAM_PID_SSC1 (44) /* Synchronous Serial Controller 1 */ +#define SAM_PID_LCDC (45) /* LCD Controller */ +#define SAM_PID_ISC (46) /* Image Sensor Controller */ +#define SAM_PID_TRNG (47) /* True Random Number Generator */ +#define SAM_PID_PDMIC (48) /* Pulse Density Modulation Interface Controller */ +#define SAM_PID_IRQID (49) /* IRQ Interrupt ID */ + +#define SAM_PID_SFC (50) /* Fuse Controller */ +#define SAM_PID_SECURAM (51) /* Secured RAM */ +#define SAM_PID_QSPI0 (52) /* QuadSPI 0 */ +#define SAM_PID_QSPI1 (53) /* QuadSPI 1 */ +#define SAM_PID_I2SC0 (54) /* Inter-IC Sound Controller 0 */ +#define SAM_PID_I2SC1 (55) /* Inter-IC Sound Controller 1 */ +#define SAM_PID_MCAN00 (56) /* MCAN controller 0, Interrupt 0 */ +#define SAM_PID_MCAN10 (57) /* MCAN controller 1, Interrupt 0 */ + /* 58 Reserved */ +#define SAM_PID_CLASSD (59) /* Audio Class D Amplifier */ + +#define SAM_PID_SFR (60) /* Special Function Register */ +#define SAM_PID_SAIC (61) /* Secured Advanced Interrupt Controller */ +#define SAM_PID_AIC (62) /* Advanced Interrupt Controller */ +#define SAM_PID_L2CC (63) /* L2 Cache Controller */ +#define SAM_PID_MCAN01 (64) /* MCAN controller 0, Interrupt 1 */ +#define SAM_PID_MCAN11 (65) /* MCAN controller 1, Interrupt 1 */ +#define SAM_PID_EMACQ1 (66) /* EMAC Queue 1 Interrupt */ +#define SAM_PID_EMACQ2 (67) /* EMAC Queue 2 Interrupt */ +#define SAM_PID_PIOB (68) /* Parallel I/O Controller B */ +#define SAM_PID_PIOC (69) /* Parallel I/O Controller C */ + +#define SAM_PID_PIOD (70) /* Parallel I/O Controller D */ +#define SAM_PID_SDMMC0T (71) /* Secure Data Memory Card Controller 0 */ +#define SAM_PID_SDMMC1T (72) /* Secure Data Memory Card Controller 1 */ + /* 73 Reserved */ +#define SAM_PID_SYS (74) /* System Controller Interrupt PMC, RTC, RSTC */ +#define SAM_PID_ACC (75) /* Analog Comparator */ +#define SAM_PID_RXLP (76) /* UART Low-Power */ +#define SAM_PID_SFRBU (77) /* Special Function Register BackUp */ +#define SAM_PID_CHIPID (78) /* Chip ID */ + +#define SAM_NPIDS (79) + +/* External interrupts vectors numbers (same as peripheral ID) */ + +#define SAM_IRQ_FIQ SAM_PID_FIQ /* Advanced Interrupt Controller FIQ */ +#define SAM_IRQ_ARM SAM_PID_ARM /* Performance Monitor Unit */ +#define SAM_IRQ_PIT SAM_PID_PIT /* Periodic Interval Timer Interrupt */ +#define SAM_IRQ_WDT SAM_PID_WDT /* Watchdog timer Interrupt */ +#define SAM_IRQ_EMAC0 SAM_PID_EMAC0 /* Ethernet MAC 0 */ +#define SAM_IRQ_XDMAC0 SAM_PID_XDMAC0 /* DMA Controller 0 */ +#define SAM_IRQ_XDMAC1 SAM_PID_XDMAC1 /* DMA Controller 1 */ +#define SAM_IRQ_ICM SAM_PID_ICM /* Integrity Check Monitor */ +#define SAM_IRQ_AES SAM_PID_AES /* Advanced Encryption Standard */ + +#define SAM_IRQ_AESB SAM_PID_AESB /* AES bridge */ +#define SAM_IRQ_TDES SAM_PID_TDES /* Triple Data Encryption Standard */ +#define SAM_IRQ_SHA SAM_PID_SHA /* Secure Hash Algorithm */ +#define SAM_IRQ_MPDDRC SAM_PID_MPDDRC /* MPDDR controller */ +#define SAM_IRQ_MATRIX1 SAM_PID_MATRIX1 /* H32MX, 32-bit AHB Matrix */ +#define SAM_IRQ_MATRIX0 SAM_PID_MATRIX0 /* H64MX, 64-bit AHB Matrix */ +#define SAM_IRQ_SECUMOD SAM_PID_SECUMOD /* Secure Module */ +#define SAM_IRQ_HSMC SAM_PID_HSMC /* Multi-bit ECC Interrupt */ +#define SAM_IRQ_PIOA SAM_PID_PIOA /* Parallel I/O Controller A */ +#define SAM_IRQ_FLEXCOM0 SAM_PID_FLEXCOM0 /* FLEXCOM 0 */ + +#define SAM_IRQ_FLEXCOM1 SAM_PID_FLEXCOM1 /* FLEXCOM 1 */ +#define SAM_IRQ_FLEXCOM2 SAM_PID_FLEXCOM2 /* FLEXCOM 2 */ +#define SAM_IRQ_FLEXCOM3 SAM_PID_FLEXCOM3 /* FLEXCOM 3 */ +#define SAM_IRQ_FLEXCOM4 SAM_PID_FLEXCOM4 /* FLEXCOM 4 */ +#define SAM_IRQ_UART0 SAM_PID_UART0 /* UART 0 */ +#define SAM_IRQ_UART1 SAM_PID_UART1 /* UART 1 */ +#define SAM_IRQ_UART2 SAM_PID_UART2 /* UART 2 */ +#define SAM_IRQ_UART3 SAM_PID_UART3 /* UART 3 */ +#define SAM_IRQ_UART4 SAM_PID_UART4 /* UART 4 */ +#define SAM_IRQ_TWI0 SAM_PID_TWI0 /* Two-Wire Interface 0 */ + +#define SAM_IRQ_TWI1 SAM_PID_TWI1 /* Two-Wire Interface 1 */ +#define SAM_IRQ_SDMMC0 SAM_PID_SDMMC0 /* Secure Data Memory Card Controller 0 */ +#define SAM_IRQ_SDMMC1 SAM_PID_SDMMC1 /* Secure Data Memory Card Controller 1 */ +#define SAM_IRQ_SPI0 SAM_PID_SPI0 /* Serial Peripheral Interface 0 */ +#define SAM_IRQ_SPI1 SAM_PID_SPI1 /* Serial Peripheral Interface 1 */ +#define SAM_IRQ_TC0 SAM_PID_TC0 /* Timer Counter 0 (ch. 0, 1, 2) */ +#define SAM_IRQ_TC1 SAM_PID_TC1 /* Timer Counter 1 (ch. 3, 4, 5) */ +#define SAM_IRQ_PWM SAM_PID_PWM /* Pulse Width Modulation Controller */ + +#define SAM_IRQ_ADC SAM_PID_ADC /* Touch Screen ADC Controller */ +#define SAM_IRQ_UHPHS SAM_PID_UHPHS /* USB Host High Speed */ +#define SAM_IRQ_UDPHS SAM_PID_UDPHS /* USB Device High Speed */ +#define SAM_IRQ_SSC0 SAM_PID_SSC0 /* Synchronous Serial Controller 0 */ +#define SAM_IRQ_SSC1 SAM_PID_SSC1 /* Synchronous Serial Controller 1 */ +#define SAM_IRQ_LCDC SAM_PID_LCDC /* LCD Controller */ +#define SAM_IRQ_ISC SAM_PID_ISC /* Image Sensor Controller */ +#define SAM_IRQ_TRNG SAM_PID_TRNG /* True Random Number Generator */ +#define SAM_IRQ_PDMIC SAM_PID_PDMIC /* Pulse Density Modulation Interface Controller */ +#define SAM_IRQ_IRQID SAM_PID_IRQID /* IRQ Interrupt ID */ + +#define SAM_IRQ_SFC SAM_PID_SFC /* Fuse Controller */ +#define SAM_IRQ_SECURAM SAM_PID_SECURAM /* Secured RAM */ +#define SAM_IRQ_QSPI0 SAM_PID_QSPI0 /* QuadSPI 0 */ +#define SAM_IRQ_QSPI1 SAM_PID_QSPI1 /* QuadSPI 1 */ +#define SAM_IRQ_I2SC0 SAM_PID_I2SC0 /* Inter-IC Sound Controller 0 */ +#define SAM_IRQ_I2SC1 SAM_PID_I2SC1 /* Inter-IC Sound Controller 1 */ +#define SAM_IRQ_MCAN00 SAM_PID_MCAN00 /* MCAN controller 0, Interrupt 0 */ +#define SAM_IRQ_MCAN10 SAM_PID_MCAN10 /* MCAN controller 1, Interrupt 0 */ +#define SAM_IRQ_CLASSD SAM_PID_CLASSD /* Audio Class D Amplifier */ + + /* Special Function Register (no interrupt) */ + /* Secured Advanced Interrupt Controller (no interrupt) */ + /* Advanced Interrupt Controller (no interrupt) */ +#define SAM_IRQ_L2CC SAM_PID_L2CC /* L2 Cache Controller */ +#define SAM_IRQ_MCAN01 SAM_PID_MCAN01 /* MCAN controller 0, Interrupt 1 */ +#define SAM_IRQ_MCAN11 SAM_PID_MCAN11 /* MCAN controller 1, Interrupt 1 */ +#define SAM_IRQ_EMACQ1 SAM_PID_EMACQ1 /* EMAC Queue 1 Interrupt */ +#define SAM_IRQ_EMACQ2 SAM_PID_EMACQ2 /* EMAC Queue 2 Interrupt */ +#define SAM_IRQ_PIOB SAM_PID_PIOB /* Parallel I/O Controller B */ +#define SAM_IRQ_PIOC SAM_PID_PIOC /* Parallel I/O Controller C */ + +#define SAM_IRQ_PIOD SAM_PID_PIOD /* Parallel I/O Controller D */ +#define SAM_IRQ_SDMMC0T SAM_PID_SDMMC0T /* Secure Data Memory Card Controller 0 */ +#define SAM_IRQ_SDMMC1T SAM_PID_SDMMC1T /* Secure Data Memory Card Controller 1 */ +#define SAM_IRQ_SYS SAM_PID_SYS /* System Controller Interrupt PMC, RTC, RSTC */ +#define SAM_IRQ_ACC SAM_PID_ACC /* Analog Comparator */ +#define SAM_IRQ_RXLP SAM_PID_RXLP /* UART Low-Power */ + /* Special Function Register BackUp (no interrupt) */ + /* Chip ID (no interrupt) */ + +#define SAM_IRQ_NINT (SAM_PID_RXLP + 1) + +/* PIO interrupts (derived from SAM_IRQ_PIOA/B/C/D/E/F) */ + +#ifdef CONFIG_SAMA5_PIOA_IRQ +# define SAM_IRQ_PIOA_PINS (SAM_IRQ_NINT) +# define SAM_IRQ_PA0 (SAM_IRQ_PIOA_PINS+0) /* PIOA, PIN 0 */ +# define SAM_IRQ_PA1 (SAM_IRQ_PIOA_PINS+1) /* PIOA, PIN 1 */ +# define SAM_IRQ_PA2 (SAM_IRQ_PIOA_PINS+2) /* PIOA, PIN 2 */ +# define SAM_IRQ_PA3 (SAM_IRQ_PIOA_PINS+3) /* PIOA, PIN 3 */ +# define SAM_IRQ_PA4 (SAM_IRQ_PIOA_PINS+4) /* PIOA, PIN 4 */ +# define SAM_IRQ_PA5 (SAM_IRQ_PIOA_PINS+5) /* PIOA, PIN 5 */ +# define SAM_IRQ_PA6 (SAM_IRQ_PIOA_PINS+6) /* PIOA, PIN 6 */ +# define SAM_IRQ_PA7 (SAM_IRQ_PIOA_PINS+7) /* PIOA, PIN 7 */ +# define SAM_IRQ_PA8 (SAM_IRQ_PIOA_PINS+8) /* PIOA, PIN 8 */ +# define SAM_IRQ_PA9 (SAM_IRQ_PIOA_PINS+9) /* PIOA, PIN 9 */ +# define SAM_IRQ_PA10 (SAM_IRQ_PIOA_PINS+10) /* PIOA, PIN 10 */ +# define SAM_IRQ_PA11 (SAM_IRQ_PIOA_PINS+11) /* PIOA, PIN 11 */ +# define SAM_IRQ_PA12 (SAM_IRQ_PIOA_PINS+12) /* PIOA, PIN 12 */ +# define SAM_IRQ_PA13 (SAM_IRQ_PIOA_PINS+13) /* PIOA, PIN 13 */ +# define SAM_IRQ_PA14 (SAM_IRQ_PIOA_PINS+14) /* PIOA, PIN 14 */ +# define SAM_IRQ_PA15 (SAM_IRQ_PIOA_PINS+15) /* PIOA, PIN 15 */ +# define SAM_IRQ_PA16 (SAM_IRQ_PIOA_PINS+16) /* PIOA, PIN 16 */ +# define SAM_IRQ_PA17 (SAM_IRQ_PIOA_PINS+17) /* PIOA, PIN 17 */ +# define SAM_IRQ_PA18 (SAM_IRQ_PIOA_PINS+18) /* PIOA, PIN 18 */ +# define SAM_IRQ_PA19 (SAM_IRQ_PIOA_PINS+19) /* PIOA, PIN 19 */ +# define SAM_IRQ_PA20 (SAM_IRQ_PIOA_PINS+20) /* PIOA, PIN 20 */ +# define SAM_IRQ_PA21 (SAM_IRQ_PIOA_PINS+21) /* PIOA, PIN 21 */ +# define SAM_IRQ_PA22 (SAM_IRQ_PIOA_PINS+22) /* PIOA, PIN 22 */ +# define SAM_IRQ_PA23 (SAM_IRQ_PIOA_PINS+23) /* PIOA, PIN 23 */ +# define SAM_IRQ_PA24 (SAM_IRQ_PIOA_PINS+24) /* PIOA, PIN 24 */ +# define SAM_IRQ_PA25 (SAM_IRQ_PIOA_PINS+25) /* PIOA, PIN 25 */ +# define SAM_IRQ_PA26 (SAM_IRQ_PIOA_PINS+26) /* PIOA, PIN 26 */ +# define SAM_IRQ_PA27 (SAM_IRQ_PIOA_PINS+27) /* PIOA, PIN 27 */ +# define SAM_IRQ_PA28 (SAM_IRQ_PIOA_PINS+28) /* PIOA, PIN 28 */ +# define SAM_IRQ_PA29 (SAM_IRQ_PIOA_PINS+29) /* PIOA, PIN 29 */ +# define SAM_IRQ_PA30 (SAM_IRQ_PIOA_PINS+30) /* PIOA, PIN 30 */ +# define SAM_IRQ_PA31 (SAM_IRQ_PIOA_PINS+31) /* PIOA, PIN 31 */ +# define SAM_NPIOAIRQS 32 +#else +# define SAM_NPIOAIRQS 0 +#endif + +#ifdef CONFIG_SAMA5_PIOB_IRQ +# define SAM_IRQ_PIOB_PINS (SAM_IRQ_NINT + SAM_NPIOAIRQS) +# define SAM_IRQ_PB0 (SAM_IRQ_PIOB_PINS+0) /* PIOB, PIN 0 */ +# define SAM_IRQ_PB1 (SAM_IRQ_PIOB_PINS+1) /* PIOB, PIN 1 */ +# define SAM_IRQ_PB2 (SAM_IRQ_PIOB_PINS+2) /* PIOB, PIN 2 */ +# define SAM_IRQ_PB3 (SAM_IRQ_PIOB_PINS+3) /* PIOB, PIN 3 */ +# define SAM_IRQ_PB4 (SAM_IRQ_PIOB_PINS+4) /* PIOB, PIN 4 */ +# define SAM_IRQ_PB5 (SAM_IRQ_PIOB_PINS+5) /* PIOB, PIN 5 */ +# define SAM_IRQ_PB6 (SAM_IRQ_PIOB_PINS+6) /* PIOB, PIN 6 */ +# define SAM_IRQ_PB7 (SAM_IRQ_PIOB_PINS+7) /* PIOB, PIN 7 */ +# define SAM_IRQ_PB8 (SAM_IRQ_PIOB_PINS+8) /* PIOB, PIN 8 */ +# define SAM_IRQ_PB9 (SAM_IRQ_PIOB_PINS+9) /* PIOB, PIN 9 */ +# define SAM_IRQ_PB10 (SAM_IRQ_PIOB_PINS+10) /* PIOB, PIN 10 */ +# define SAM_IRQ_PB11 (SAM_IRQ_PIOB_PINS+11) /* PIOB, PIN 11 */ +# define SAM_IRQ_PB12 (SAM_IRQ_PIOB_PINS+12) /* PIOB, PIN 12 */ +# define SAM_IRQ_PB13 (SAM_IRQ_PIOB_PINS+13) /* PIOB, PIN 13 */ +# define SAM_IRQ_PB14 (SAM_IRQ_PIOB_PINS+14) /* PIOB, PIN 14 */ +# define SAM_IRQ_PB15 (SAM_IRQ_PIOB_PINS+15) /* PIOB, PIN 15 */ +# define SAM_IRQ_PB16 (SAM_IRQ_PIOB_PINS+16) /* PIOB, PIN 16 */ +# define SAM_IRQ_PB17 (SAM_IRQ_PIOB_PINS+17) /* PIOB, PIN 17 */ +# define SAM_IRQ_PB18 (SAM_IRQ_PIOB_PINS+18) /* PIOB, PIN 18 */ +# define SAM_IRQ_PB19 (SAM_IRQ_PIOB_PINS+19) /* PIOB, PIN 19 */ +# define SAM_IRQ_PB20 (SAM_IRQ_PIOB_PINS+20) /* PIOB, PIN 20 */ +# define SAM_IRQ_PB21 (SAM_IRQ_PIOB_PINS+21) /* PIOB, PIN 21 */ +# define SAM_IRQ_PB22 (SAM_IRQ_PIOB_PINS+22) /* PIOB, PIN 22 */ +# define SAM_IRQ_PB23 (SAM_IRQ_PIOB_PINS+23) /* PIOB, PIN 23 */ +# define SAM_IRQ_PB24 (SAM_IRQ_PIOB_PINS+24) /* PIOB, PIN 24 */ +# define SAM_IRQ_PB25 (SAM_IRQ_PIOB_PINS+25) /* PIOB, PIN 25 */ +# define SAM_IRQ_PB26 (SAM_IRQ_PIOB_PINS+26) /* PIOB, PIN 26 */ +# define SAM_IRQ_PB27 (SAM_IRQ_PIOB_PINS+27) /* PIOB, PIN 27 */ +# define SAM_IRQ_PB28 (SAM_IRQ_PIOB_PINS+28) /* PIOB, PIN 28 */ +# define SAM_IRQ_PB29 (SAM_IRQ_PIOB_PINS+29) /* PIOB, PIN 29 */ +# define SAM_IRQ_PB30 (SAM_IRQ_PIOB_PINS+30) /* PIOB, PIN 30 */ +# define SAM_IRQ_PB31 (SAM_IRQ_PIOB_PINS+31) /* PIOB, PIN 31 */ +# define SAM_NPIOBIRQS 32 +#else +# define SAM_NPIOBIRQS 0 +#endif + +#ifdef CONFIG_SAMA5_PIOC_IRQ +# define SAM_IRQ_PIOC_PINS (SAM_IRQ_NINT + SAM_NPIOAIRQS + SAM_NPIOBIRQS) +# define SAM_IRQ_PC0 (SAM_IRQ_PIOC_PINS+0) /* PIOC, PIN 0 */ +# define SAM_IRQ_PC1 (SAM_IRQ_PIOC_PINS+1) /* PIOC, PIN 1 */ +# define SAM_IRQ_PC2 (SAM_IRQ_PIOC_PINS+2) /* PIOC, PIN 2 */ +# define SAM_IRQ_PC3 (SAM_IRQ_PIOC_PINS+3) /* PIOC, PIN 3 */ +# define SAM_IRQ_PC4 (SAM_IRQ_PIOC_PINS+4) /* PIOC, PIN 4 */ +# define SAM_IRQ_PC5 (SAM_IRQ_PIOC_PINS+5) /* PIOC, PIN 5 */ +# define SAM_IRQ_PC6 (SAM_IRQ_PIOC_PINS+6) /* PIOC, PIN 6 */ +# define SAM_IRQ_PC7 (SAM_IRQ_PIOC_PINS+7) /* PIOC, PIN 7 */ +# define SAM_IRQ_PC8 (SAM_IRQ_PIOC_PINS+8) /* PIOC, PIN 8 */ +# define SAM_IRQ_PC9 (SAM_IRQ_PIOC_PINS+9) /* PIOC, PIN 9 */ +# define SAM_IRQ_PC10 (SAM_IRQ_PIOC_PINS+10) /* PIOC, PIN 10 */ +# define SAM_IRQ_PC11 (SAM_IRQ_PIOC_PINS+11) /* PIOC, PIN 11 */ +# define SAM_IRQ_PC12 (SAM_IRQ_PIOC_PINS+12) /* PIOC, PIN 12 */ +# define SAM_IRQ_PC13 (SAM_IRQ_PIOC_PINS+13) /* PIOC, PIN 13 */ +# define SAM_IRQ_PC14 (SAM_IRQ_PIOC_PINS+14) /* PIOC, PIN 14 */ +# define SAM_IRQ_PC15 (SAM_IRQ_PIOC_PINS+15) /* PIOC, PIN 15 */ +# define SAM_IRQ_PC16 (SAM_IRQ_PIOC_PINS+16) /* PIOC, PIN 16 */ +# define SAM_IRQ_PC17 (SAM_IRQ_PIOC_PINS+17) /* PIOC, PIN 17 */ +# define SAM_IRQ_PC18 (SAM_IRQ_PIOC_PINS+18) /* PIOC, PIN 18 */ +# define SAM_IRQ_PC19 (SAM_IRQ_PIOC_PINS+19) /* PIOC, PIN 19 */ +# define SAM_IRQ_PC20 (SAM_IRQ_PIOC_PINS+20) /* PIOC, PIN 20 */ +# define SAM_IRQ_PC21 (SAM_IRQ_PIOC_PINS+21) /* PIOC, PIN 21 */ +# define SAM_IRQ_PC22 (SAM_IRQ_PIOC_PINS+22) /* PIOC, PIN 22 */ +# define SAM_IRQ_PC23 (SAM_IRQ_PIOC_PINS+23) /* PIOC, PIN 23 */ +# define SAM_IRQ_PC24 (SAM_IRQ_PIOC_PINS+24) /* PIOC, PIN 24 */ +# define SAM_IRQ_PC25 (SAM_IRQ_PIOC_PINS+25) /* PIOC, PIN 25 */ +# define SAM_IRQ_PC26 (SAM_IRQ_PIOC_PINS+26) /* PIOC, PIN 26 */ +# define SAM_IRQ_PC27 (SAM_IRQ_PIOC_PINS+27) /* PIOC, PIN 27 */ +# define SAM_IRQ_PC28 (SAM_IRQ_PIOC_PINS+28) /* PIOC, PIN 28 */ +# define SAM_IRQ_PC29 (SAM_IRQ_PIOC_PINS+29) /* PIOC, PIN 29 */ +# define SAM_IRQ_PC30 (SAM_IRQ_PIOC_PINS+30) /* PIOC, PIN 30 */ +# define SAM_IRQ_PC31 (SAM_IRQ_PIOC_PINS+31) /* PIOC, PIN 31 */ +# define SAM_NPIOCIRQS 32 +#else +# define SAM_NPIOCIRQS 0 +#endif + +#ifdef CONFIG_SAMA5_PIOD_IRQ +# define SAM_IRQ_PIOD_PINS (SAM_IRQ_NINT + SAM_NPIOAIRQS + SAM_NPIOBIRQS + \ + SAM_NPIOCIRQS) +# define SAM_IRQ_PD0 (SAM_IRQ_PIOD_PINS+0) /* PIOD, PIN 0 */ +# define SAM_IRQ_PD1 (SAM_IRQ_PIOD_PINS+1) /* PIOD, PIN 1 */ +# define SAM_IRQ_PD2 (SAM_IRQ_PIOD_PINS+2) /* PIOD, PIN 2 */ +# define SAM_IRQ_PD3 (SAM_IRQ_PIOD_PINS+3) /* PIOD, PIN 3 */ +# define SAM_IRQ_PD4 (SAM_IRQ_PIOD_PINS+4) /* PIOD, PIN 4 */ +# define SAM_IRQ_PD5 (SAM_IRQ_PIOD_PINS+5) /* PIOD, PIN 5 */ +# define SAM_IRQ_PD6 (SAM_IRQ_PIOD_PINS+6) /* PIOD, PIN 6 */ +# define SAM_IRQ_PD7 (SAM_IRQ_PIOD_PINS+7) /* PIOD, PIN 7 */ +# define SAM_IRQ_PD8 (SAM_IRQ_PIOD_PINS+8) /* PIOD, PIN 8 */ +# define SAM_IRQ_PD9 (SAM_IRQ_PIOD_PINS+9) /* PIOD, PIN 9 */ +# define SAM_IRQ_PD10 (SAM_IRQ_PIOD_PINS+10) /* PIOD, PIN 10 */ +# define SAM_IRQ_PD11 (SAM_IRQ_PIOD_PINS+11) /* PIOD, PIN 11 */ +# define SAM_IRQ_PD12 (SAM_IRQ_PIOD_PINS+12) /* PIOD, PIN 12 */ +# define SAM_IRQ_PD13 (SAM_IRQ_PIOD_PINS+13) /* PIOD, PIN 13 */ +# define SAM_IRQ_PD14 (SAM_IRQ_PIOD_PINS+14) /* PIOD, PIN 14 */ +# define SAM_IRQ_PD15 (SAM_IRQ_PIOD_PINS+15) /* PIOD, PIN 15 */ +# define SAM_IRQ_PD16 (SAM_IRQ_PIOD_PINS+16) /* PIOD, PIN 16 */ +# define SAM_IRQ_PD17 (SAM_IRQ_PIOD_PINS+17) /* PIOD, PIN 17 */ +# define SAM_IRQ_PD18 (SAM_IRQ_PIOD_PINS+18) /* PIOD, PIN 18 */ +# define SAM_IRQ_PD19 (SAM_IRQ_PIOD_PINS+19) /* PIOD, PIN 19 */ +# define SAM_IRQ_PD20 (SAM_IRQ_PIOD_PINS+20) /* PIOD, PIN 20 */ +# define SAM_IRQ_PD21 (SAM_IRQ_PIOD_PINS+21) /* PIOD, PIN 21 */ +# define SAM_IRQ_PD22 (SAM_IRQ_PIOD_PINS+22) /* PIOD, PIN 22 */ +# define SAM_IRQ_PD23 (SAM_IRQ_PIOD_PINS+23) /* PIOD, PIN 23 */ +# define SAM_IRQ_PD24 (SAM_IRQ_PIOD_PINS+24) /* PIOD, PIN 24 */ +# define SAM_IRQ_PD25 (SAM_IRQ_PIOD_PINS+25) /* PIOD, PIN 25 */ +# define SAM_IRQ_PD26 (SAM_IRQ_PIOD_PINS+26) /* PIOD, PIN 26 */ +# define SAM_IRQ_PD27 (SAM_IRQ_PIOD_PINS+27) /* PIOD, PIN 27 */ +# define SAM_IRQ_PD28 (SAM_IRQ_PIOD_PINS+28) /* PIOD, PIN 28 */ +# define SAM_IRQ_PD29 (SAM_IRQ_PIOD_PINS+29) /* PIOD, PIN 29 */ +# define SAM_IRQ_PD30 (SAM_IRQ_PIOD_PINS+30) /* PIOD, PIN 30 */ +# define SAM_IRQ_PD31 (SAM_IRQ_PIOD_PINS+31) /* PIOD, PIN 31 */ +# define SAM_NPIODIRQS 32 +#else +# define SAM_NPIODIRQS 0 +#endif + +/* Total number of IRQ numbers */ + +#define NR_IRQS (SAM_IRQ_NINT + \ + SAM_NPIOAIRQS + SAM_NPIOBIRQS + SAM_NPIOCIRQS + \ + SAM_NPIODIRQS) + +/**************************************************************************************** + * Public Types + ****************************************************************************************/ + +/**************************************************************************************** + * Inline functions + ****************************************************************************************/ + +/**************************************************************************************** + * Public Variables + ****************************************************************************************/ + +/**************************************************************************************** + * Public Function Prototypes + ****************************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_SAMA5_SAMA5D2_IRQ_H */ diff --git a/arch/arm/include/sama5/sama5d4_irq.h b/arch/arm/include/sama5/sama5d4_irq.h index 282fae32616..c49c7d9333e 100644 --- a/arch/arm/include/sama5/sama5d4_irq.h +++ b/arch/arm/include/sama5/sama5d4_irq.h @@ -1,5 +1,5 @@ /**************************************************************************************** - * arch/arm/include/sama5/sama5d4x_irq.h + * arch/arm/include/sama5/sama5d4_irq.h * * Copyright (C) 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -37,8 +37,8 @@ * nuttx/irq.h */ -#ifndef __ARCH_ARM_INCLUDE_SAMA5_SAMA5D4X_IRQ_H -#define __ARCH_ARM_INCLUDE_SAMA5_SAMA5D4X_IRQ_H +#ifndef __ARCH_ARM_INCLUDE_SAMA5_SAMA5D4_IRQ_H +#define __ARCH_ARM_INCLUDE_SAMA5_SAMA5D4_IRQ_H /**************************************************************************************** * Included Files @@ -436,4 +436,4 @@ extern "C" #endif #endif -#endif /* __ARCH_ARM_INCLUDE_SAMA5_SAMA5D4X_IRQ_H */ +#endif /* __ARCH_ARM_INCLUDE_SAMA5_SAMA5D4_IRQ_H */ diff --git a/arch/arm/include/samv7/chip.h b/arch/arm/include/samv7/chip.h index 29ed62afa36..eff9fe1ea4f 100644 --- a/arch/arm/include/samv7/chip.h +++ b/arch/arm/include/samv7/chip.h @@ -86,7 +86,7 @@ # define SAMV7_NTCCHIO 36 /* 12 Timer/counter channels I/O */ # define SAMV7_NUSART 3 /* 3 USARTs */ # define SAMV7_NUART 5 /* 5 UARTs */ -# define SAMV7_NQSPI 5 /* 1 Quad SPI */ +# define SAMV7_NQSPI 1 /* 1 Quad SPI */ # define SAMV7_NSPI 2 /* 2 SPI, SPI0-1 */ # define SAMV7_NTWIHS 3 /* 3 TWIHS */ # define SAMV7_NHSMCI4 1 /* 1 4-bit HSMCI port */ @@ -142,7 +142,7 @@ # define SAMV7_NTCCHIO 9 /* 12 Timer/counter channels I/O */ # define SAMV7_NUSART 3 /* 3 USARTs */ # define SAMV7_NUART 5 /* 5 UARTs */ -# define SAMV7_NQSPI 5 /* 1 Quad SPI */ +# define SAMV7_NQSPI 1 /* 1 Quad SPI */ # define SAMV7_NSPI 1 /* 1 SPI, SPI0 */ # define SAMV7_NTWIHS 3 /* 3 TWIHS */ # define SAMV7_NHSMCI4 1 /* 1 4-bit HSMCI port */ diff --git a/arch/arm/include/stm32/chip.h b/arch/arm/include/stm32/chip.h index d52a9aec29c..8635da36dc9 100644 --- a/arch/arm/include/stm32/chip.h +++ b/arch/arm/include/stm32/chip.h @@ -1212,6 +1212,86 @@ # define STM32_NRNG 0 /* (0) No random number generator (RNG) */ # define STM32_NDCMI 0 /* (0) No digital camera interface (DCMI) */ +#elif defined(CONFIG_ARCH_CHIP_STM32F303K6) || defined(CONFIG_ARCH_CHIP_STM32F303K8) +# undef CONFIG_STM32_STM32L15XX /* STM32L151xx and STM32L152xx family */ +# undef CONFIG_STM32_ENERGYLITE /* STM32L EnergyLite family */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_MEDIUMPLUSDENSITY /* STM32L15xxC w/ 32/256 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F100x, STM32F101x, and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F30XX 1 /* STM32F30xxx family */ +# undef CONFIG_STM32_STM32F37XX /* STM32F37xxx family */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 0 /* No FSMC */ + +# define STM32_NATIM 1 /* (1) Advanced 16-bit timers with DMA: TIM1 */ +# define STM32_NGTIM 5 /* (1) 16-bit general timers with DMA: TIM3 + * (1) 32-bit general timers with DMA: TIM2 + * (3) 16-bit general timers count-up timers with DMA: TIM15-17 */ +# define STM32_NGTIMNDMA 0 /* All timers have DMA */ +# define STM32_NBTIM 2 /* (2) Basic timers: TIM6 and TIM7 */ +# define STM32_NDMA 1 /* (1) DMA1 (7 channels) */ +# define STM32_NSPI 1 /* (1) SPI1 */ +# define STM32_NI2S 0 /* (0) No I2S */ +# define STM32_NUSART 2 /* (2) USART1-2, no UARTs */ +# define STM32_NI2C 1 /* (1) I2C1 */ +# define STM32_NCAN 1 /* (1) CAN1 */ +# define STM32_NSDIO 0 /* (0) No SDIO */ +# define STM32_NLCD 0 /* (0) No LCD */ +# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */ +# define STM32_NGPIO 25 /* GPIOA-F */ +# define STM32_NADC 2 /* (2) 12-bit ADC1-2 */ +# define STM32_NDAC 3 /* (2) 12-bit DAC1-3 */ +# define STM32_NCAPSENSE 0 /* (0) No capacitive sensing channels */ +# define STM32_NCRC 1 /* (1) CRC calculation unit */ +# define STM32_NETHERNET 0 /* (0) No Ethernet MAC */ +# define STM32_NRNG 0 /* (0) No random number generator (RNG) */ +# define STM32_NDCMI 0 /* (0) No digital camera interface (DCMI) */ + +#elif defined(CONFIG_ARCH_CHIP_STM32F303C6) || defined(CONFIG_ARCH_CHIP_STM32F303C8) +# undef CONFIG_STM32_STM32L15XX /* STM32L151xx and STM32L152xx family */ +# undef CONFIG_STM32_ENERGYLITE /* STM32L EnergyLite family */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_MEDIUMPLUSDENSITY /* STM32L15xxC w/ 32/256 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F100x, STM32F101x, and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F30XX 1 /* STM32F30xxx family */ +# undef CONFIG_STM32_STM32F37XX /* STM32F37xxx family */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 0 /* No FSMC */ + +# define STM32_NATIM 1 /* (1) Advanced 16-bit timers with DMA: TIM1 */ +# define STM32_NGTIM 5 /* (1) 16-bit general timers with DMA: TIM3 + * (1) 32-bit general timers with DMA: TIM2 + * (3) 16-bit general timers count-up timers with DMA: TIM15-17 */ +# define STM32_NGTIMNDMA 0 /* All timers have DMA */ +# define STM32_NBTIM 2 /* (2) Basic timers: TIM6 and TIM7 */ +# define STM32_NDMA 1 /* (1) DMA1 (7 channels) */ +# define STM32_NSPI 1 /* (1) SPI1 */ +# define STM32_NI2S 0 /* (0) No I2S */ +# define STM32_NUSART 3 /* (3) USART1-3, no UARTs */ +# define STM32_NI2C 1 /* (1) I2C1 */ +# define STM32_NCAN 1 /* (1) CAN1 */ +# define STM32_NSDIO 0 /* (0) No SDIO */ +# define STM32_NLCD 0 /* (0) No LCD */ +# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */ +# define STM32_NGPIO 37 /* GPIOA-F */ +# define STM32_NADC 2 /* (2) 12-bit ADC1-2 */ +# define STM32_NDAC 3 /* (2) 12-bit DAC1-3 */ +# define STM32_NCAPSENSE 0 /* (0) No capacitive sensing channels */ +# define STM32_NCRC 1 /* (1) CRC calculation unit */ +# define STM32_NETHERNET 0 /* (0) No Ethernet MAC */ +# define STM32_NRNG 0 /* (0) No random number generator (RNG) */ +# define STM32_NDCMI 0 /* (0) No digital camera interface (DCMI) */ + #elif defined(CONFIG_ARCH_CHIP_STM32F303CB) || defined(CONFIG_ARCH_CHIP_STM32F303CC) # undef CONFIG_STM32_STM32L15XX /* STM32L151xx and STM32L152xx family */ # undef CONFIG_STM32_ENERGYLITE /* STM32L EnergyLite family */ @@ -1292,6 +1372,46 @@ # define STM32_NRNG 0 /* (0) No random number generator (RNG) */ # define STM32_NDCMI 0 /* (0) No digital camera interface (DCMI) */ +#elif defined(CONFIG_ARCH_CHIP_STM32F303RD) || defined(CONFIG_ARCH_CHIP_STM32F303RE) +# undef CONFIG_STM32_STM32L15XX /* STM32L151xx and STM32L152xx family */ +# undef CONFIG_STM32_ENERGYLITE /* STM32L EnergyLite family */ +# undef CONFIG_STM32_STM32F10XX /* STM32F10xxx family */ +# undef CONFIG_STM32_LOWDENSITY /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */ +# undef CONFIG_STM32_MEDIUMDENSITY /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */ +# undef CONFIG_STM32_MEDIUMPLUSDENSITY /* STM32L15xxC w/ 32/256 Kbytes */ +# undef CONFIG_STM32_HIGHDENSITY /* STM32F100x, STM32F101x, and STM32F103x w/ 256/512 Kbytes */ +# undef CONFIG_STM32_VALUELINE /* STM32F100x */ +# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */ +# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */ +# define CONFIG_STM32_STM32F30XX 1 /* STM32F30xxx family */ +# undef CONFIG_STM32_STM32F37XX /* STM32F37xxx family */ +# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx */ +# define STM32_NFSMC 0 /* No FSMC */ + +# define STM32_NATIM 2 /* (2) Advanced 16-bit timers with DMA: TIM1 and TIM8 */ +# define STM32_NGTIM 6 /* (2) 16-bit general timers with DMA: TIM3 and TIM4 + * (1) 32-bit general timers with DMA: TIM2 + * (3) 16-bit general timers count-up timers with DMA: TIM15-17 */ +# define STM32_NGTIMNDMA 0 /* All timers have DMA */ +# define STM32_NBTIM 2 /* (2) Basic timers: TIM6 and TIM7 */ +# define STM32_NDMA 2 /* (2) DMA1 (7 channels) and DMA2 (5 channels) */ +# define STM32_NSPI 4 /* (4) SPI1-4 */ +# define STM32_NI2S 2 /* (2) I2S1-2 (multiplexed with SPI2-3) */ +# define STM32_NUSART 5 /* (5) USART1-3, UART4-5 */ +# define STM32_NI2C 3 /* (2) I2C1-3 */ +# define STM32_NCAN 1 /* (1) CAN1 */ +# define STM32_NSDIO 0 /* (0) No SDIO */ +# define STM32_NLCD 0 /* (0) No LCD */ +# define STM32_NUSBOTG 0 /* USB FS device, but no USB OTG FS/HS */ +# define STM32_NGPIO 51 /* GPIOA-F */ +# define STM32_NADC 4 /* (4) 12-bit ADC1-4 */ +# define STM32_NDAC 2 /* (2) 12-bit DAC1-2 */ +# define STM32_NCAPSENSE 0 /* (0) No capacitive sensing channels */ +# define STM32_NCRC 1 /* (1) CRC calculation unit */ +# define STM32_NETHERNET 0 /* (0) No Ethernet MAC */ +# define STM32_NRNG 0 /* (0) No random number generator (RNG) */ +# define STM32_NDCMI 0 /* (0) No digital camera interface (DCMI) */ + #elif defined(CONFIG_ARCH_CHIP_STM32F303VB) || defined(CONFIG_ARCH_CHIP_STM32F303VC) # undef CONFIG_STM32_STM32L15XX /* STM32L151xx and STM32L152xx family */ # undef CONFIG_STM32_ENERGYLITE /* STM32L EnergyLite family */ diff --git a/arch/arm/src/armv7-a/arm_copyarmstate.c b/arch/arm/src/armv7-a/arm_copyarmstate.c index 20f1934efff..9c8a7797afa 100644 --- a/arch/arm/src/armv7-a/arm_copyarmstate.c +++ b/arch/arm/src/armv7-a/arm_copyarmstate.c @@ -76,7 +76,7 @@ void up_copyarmstate(uint32_t *dest, uint32_t *src) { int i; - /* In the Cortex-M3 model, the state is copied from the stack to the TCB, + /* In the Cortex-M model, the state is copied from the stack to the TCB, * but only a reference is passed to get the state from the TCB. So the * following check avoids copying the TCB save area onto itself: */ diff --git a/arch/arm/src/armv7-m/up_ramvec_initialize.c b/arch/arm/src/armv7-m/up_ramvec_initialize.c index b8bf2057214..37332776850 100644 --- a/arch/arm/src/armv7-m/up_ramvec_initialize.c +++ b/arch/arm/src/armv7-m/up_ramvec_initialize.c @@ -56,6 +56,21 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Alignment ****************************************************************/ +/* Per the ARMv7M Architecture reference manual, the NVIC vector table + * requires 7-bit address alignment (i.e, bits 0-6 of the address of the + * vector table must be zero). In this case alignment to a 128 byte address + * boundary is sufficient. + * + * Some parts, such as the LPC17xx family, require alignment to a 256 byte + * address boundary. Any other unusual alignment requirements for the vector + * can be specified for a given architecture be redefining + * NVIC_VECTAB_TBLOFF_MASK in the chip-specific chip.h header file for the + * appropriate mask. + */ + +#define RAMVEC_ALIGN ((~NVIC_VECTAB_TBLOFF_MASK & 0xffff) + 1) + /* Debug ********************************************************************/ /* Non-standard debug that may be enabled just for testing the interrupt * config. NOTE: that only lldbg types are used so that the output is @@ -91,7 +106,7 @@ */ up_vector_t g_ram_vectors[ARMV7M_VECTAB_SIZE] - __attribute__ ((section (".ram_vectors"), aligned (128))); + __attribute__ ((section (".ram_vectors"), aligned (RAMVEC_ALIGN))); /**************************************************************************** * Private Variables diff --git a/arch/arm/src/calypso/calypso_serial.c b/arch/arm/src/calypso/calypso_serial.c index c19ac2858c4..fa5587a2e87 100644 --- a/arch/arm/src/calypso/calypso_serial.c +++ b/arch/arm/src/calypso/calypso_serial.c @@ -377,7 +377,7 @@ static inline void up_setrate(struct up_dev_s *priv, unsigned int rate) break; } -#if UART_DIV_BIT_RATE_OFFS +#ifdef UART_DIV_BIT_RATE_OFFS up_serialout(priv, UART_DIV_BIT_RATE_OFFS, div_bit_rate); #else up_serialout(priv, UART_DIV_LOW_OFFS, div_bit_rate); diff --git a/arch/arm/src/common/up_initialize.c b/arch/arm/src/common/up_initialize.c index cad12d23077..71c33313453 100644 --- a/arch/arm/src/common/up_initialize.c +++ b/arch/arm/src/common/up_initialize.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -254,6 +255,12 @@ void up_initialize(void) up_netinitialize(); #endif +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + /* Initialize USB -- device and/or host */ up_usbinitialize(); diff --git a/arch/arm/src/common/up_internal.h b/arch/arm/src/common/up_internal.h index 2f20524b5d5..6523f57d30d 100644 --- a/arch/arm/src/common/up_internal.h +++ b/arch/arm/src/common/up_internal.h @@ -124,10 +124,11 @@ /* If the floating point unit is present and enabled, then save the * floating point registers as well as normal ARM registers. This only * applies if "lazy" floating point register save/restore is used - * (i.e., not CONFIG_ARMV7M_CMNVECTOR). + * (i.e., not CONFIG_ARMV7M_CMNVECTOR=y with CONFIG_ARMV7M_LAZYFPU=n). */ -# if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_ARMV7M_CMNVECTOR) +# if defined(CONFIG_ARCH_FPU) && (!defined(CONFIG_ARMV7M_CMNVECTOR) || \ + defined(CONFIG_ARMV7M_LAZYFPU)) # define up_savestate(regs) up_copyarmstate(regs, (uint32_t*)current_regs) # else # define up_savestate(regs) up_copyfullstate(regs, (uint32_t*)current_regs) diff --git a/arch/arm/src/efm32/Make.defs b/arch/arm/src/efm32/Make.defs index bdac6fc2343..e40e240d79c 100644 --- a/arch/arm/src/efm32/Make.defs +++ b/arch/arm/src/efm32/Make.defs @@ -87,6 +87,8 @@ ifeq ($(CONFIG_ARCH_FPU),y) CMN_ASRCS += up_fpu.S ifneq ($(CONFIG_ARMV7M_CMNVECTOR),y) CMN_CSRCS += up_copyarmstate.c +else ifeq ($(CONFIG_ARMV7M_LAZYFPU),y) +CMN_CSRCS += up_copyarmstate.c endif endif diff --git a/arch/arm/src/efm32/efm32_irq.c b/arch/arm/src/efm32/efm32_irq.c index 3b7c386ef65..9923bcdf259 100644 --- a/arch/arm/src/efm32/efm32_irq.c +++ b/arch/arm/src/efm32/efm32_irq.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/efm32/efm32_irq.c * - * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -79,8 +79,18 @@ * Public Data ****************************************************************************/ +/* This is the address of current interrupt saved state data. Used for + * context switching. Only value during interrupt handling. + */ + volatile uint32_t *current_regs; +/* This is the address of the exception vector table (determined by the + * linker script). + */ + +extern uint32_t _vectors[]; + /**************************************************************************** * Private Data ****************************************************************************/ @@ -363,6 +373,15 @@ void up_irqinitialize(void) } #endif + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + #ifdef CONFIG_ARCH_RAMVECTORS /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. diff --git a/arch/arm/src/efm32/efm32_usbdev.c b/arch/arm/src/efm32/efm32_usbdev.c index 6816d50b708..9ce5b6a1387 100644 --- a/arch/arm/src/efm32/efm32_usbdev.c +++ b/arch/arm/src/efm32/efm32_usbdev.c @@ -683,7 +683,7 @@ static const struct usbdev_ops_s g_devops = .pullup = efm32_pullup, }; -/* Device error strings that may be enabled for more desciptive USB trace +/* Device error strings that may be enabled for more descriptive USB trace * output. */ @@ -725,7 +725,7 @@ const struct trace_msg_t g_usb_trace_strings_deverror[] = }; #endif -/* Interrupt event strings that may be enabled for more desciptive USB trace +/* Interrupt event strings that may be enabled for more descriptive USB trace * output. */ diff --git a/arch/arm/src/efm32/efm32_usbhost.c b/arch/arm/src/efm32/efm32_usbhost.c index 97b75f75d5d..35c0bc65b91 100644 --- a/arch/arm/src/efm32/efm32_usbhost.c +++ b/arch/arm/src/efm32/efm32_usbhost.c @@ -1171,7 +1171,7 @@ static int efm32_chan_wait(FAR struct efm32_usbhost_s *priv, /* Loop, testing for an end of transfer condition. The channel 'result' * was set to EBUSY and 'waiter' was set to true before the transfer; 'waiter' * will be set to false and 'result' will be set appropriately when the - * tranfer is completed. + * transfer is completed. */ do diff --git a/arch/arm/src/kinetis/kinetis_enet.c b/arch/arm/src/kinetis/kinetis_enet.c index 8cf87932da2..628263e7102 100644 --- a/arch/arm/src/kinetis/kinetis_enet.c +++ b/arch/arm/src/kinetis/kinetis_enet.c @@ -191,14 +191,14 @@ struct kinetis_driver_s #endif /* The DMA descriptors. A unaligned uint8_t is used to allocate the - * memory; 16 is added to assure that we can meet the desciptor alignment + * memory; 16 is added to assure that we can meet the descriptor alignment * requirements. */ uint8_t desc[NENET_NBUFFERS * sizeof(struct enet_desc_s) + 16]; /* The DMA buffers. Again, A unaligned uint8_t is used to allocate the - * memory; 16 is added to assure that we can meet the desciptor alignment + * memory; 16 is added to assure that we can meet the descriptor alignment * requirements. */ @@ -1338,7 +1338,7 @@ static inline void kinetis_initphy(struct kinetis_driver_s *priv) * configuration and the auto negotiation results. */ -#if CONFIG_ENET_USEMII +#ifdef CONFIG_ENET_USEMII rcr = ENET_RCR_MII_MODE | ENET_RCR_CRCFWD | CONFIG_NET_ETH_MTU << ENET_RCR_MAX_FL_SHIFT; #else @@ -1527,7 +1527,7 @@ int kinetis_netinitialize(int intf) /* Configure all ENET/MII pins */ -#if CONFIG_ENET_USEMII +#ifdef CONFIG_ENET_USEMII kinetis_pinconfig(PIN_MII0_MDIO); kinetis_pinconfig(PIN_MII0_MDC); kinetis_pinconfig(PIN_MII0_RXDV); diff --git a/arch/arm/src/kinetis/kinetis_irq.c b/arch/arm/src/kinetis/kinetis_irq.c index 452c4b45b6a..cded69a62a7 100644 --- a/arch/arm/src/kinetis/kinetis_irq.c +++ b/arch/arm/src/kinetis/kinetis_irq.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/lpc17/kinetis_irq.c * - * Copyright (C) 2011, 2013-14 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -75,8 +75,18 @@ * Public Data ****************************************************************************/ +/* This is the address of current interrupt saved state data. Used for + * context switching. Only value during interrupt handling. + */ + volatile uint32_t *current_regs; +/* This is the address of the exception vector table (determined by the + * linker script). + */ + +extern uint32_t _vectors[]; + /**************************************************************************** * Private Data ****************************************************************************/ @@ -341,11 +351,20 @@ void up_irqinitialize(void) putreg32(0, regaddr); } + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ -#ifdef CONFIG_ARCH_RAMVECTORS up_ramvec_initialize(); #endif diff --git a/arch/arm/src/kinetis/kinetis_sdhc.c b/arch/arm/src/kinetis/kinetis_sdhc.c index bbc2e1edf64..8dc394a4008 100644 --- a/arch/arm/src/kinetis/kinetis_sdhc.c +++ b/arch/arm/src/kinetis/kinetis_sdhc.c @@ -65,7 +65,7 @@ #include "kinetis_sim.h" #include "kinetis_sdhc.h" -#if CONFIG_KINETIS_SDHC +#ifdef CONFIG_KINETIS_SDHC /**************************************************************************** * Pre-processor Definitions @@ -102,7 +102,7 @@ * and divider values. */ -#if CONFIG_KINETIS_SDHC_ABSFREQ +#ifdef CONFIG_KINETIS_SDHC_ABSFREQ # ifndef CONFIG_KINETIS_IDMODE_FREQ # define CONFIG_KINETIS_IDMODE_FREQ 400000 /* 400 KHz, ID mode */ # endif @@ -287,7 +287,7 @@ static int kinetis_lock(FAR struct sdio_dev_s *dev, bool lock); static void kinetis_reset(FAR struct sdio_dev_s *dev); static uint8_t kinetis_status(FAR struct sdio_dev_s *dev); static void kinetis_widebus(FAR struct sdio_dev_s *dev, bool enable); -#if CONFIG_KINETIS_SDHC_ABSFREQ +#ifdef CONFIG_KINETIS_SDHC_ABSFREQ static void kinetis_frequency(FAR struct sdio_dev_s *dev, uint32_t frequency); #endif static void kinetis_clock(FAR struct sdio_dev_s *dev, @@ -1387,7 +1387,7 @@ static void kinetis_widebus(FAR struct sdio_dev_s *dev, bool wide) * ****************************************************************************/ -#if CONFIG_KINETIS_SDHC_ABSFREQ +#ifdef CONFIG_KINETIS_SDHC_ABSFREQ static void kinetis_frequency(FAR struct sdio_dev_s *dev, uint32_t frequency) { uint32_t sdclkfs; @@ -1523,7 +1523,7 @@ static void kinetis_frequency(FAR struct sdio_dev_s *dev, uint32_t frequency) * ****************************************************************************/ -#if CONFIG_KINETIS_SDHC_ABSFREQ +#ifdef CONFIG_KINETIS_SDHC_ABSFREQ static void kinetis_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) { uint32_t frequency; diff --git a/arch/arm/src/lpc17xx/Make.defs b/arch/arm/src/lpc17xx/Make.defs index 3157b846bac..daf388a1172 100644 --- a/arch/arm/src/lpc17xx/Make.defs +++ b/arch/arm/src/lpc17xx/Make.defs @@ -100,6 +100,8 @@ ifeq ($(CONFIG_ARCH_FPU),y) CMN_ASRCS += up_fpu.S ifneq ($(CONFIG_ARMV7M_CMNVECTOR),y) CMN_CSRCS += up_copyarmstate.c +else ifeq ($(CONFIG_ARMV7M_LAZYFPU),y) +CMN_CSRCS += up_copyarmstate.c endif endif diff --git a/arch/arm/src/lpc17xx/lpc176x_rtc.c b/arch/arm/src/lpc17xx/lpc176x_rtc.c index 0aaf6eb33d8..b25095dda46 100644 --- a/arch/arm/src/lpc17xx/lpc176x_rtc.c +++ b/arch/arm/src/lpc17xx/lpc176x_rtc.c @@ -250,7 +250,7 @@ static int rtc_resume(void) * ************************************************************************************/ -#if CONFIG_RTC_ALARM +#ifdef CONFIG_RTC_ALARM static int rtc_interrupt(int irq, void *context) { #warning "Missing logic" @@ -285,7 +285,7 @@ int up_rtcinitialize(void) /* Attach the RTC interrupt handler */ -#if CONFIG_RTC_ALARM +#ifdef CONFIG_RTC_ALARM ret = irq_attach(LPC17_IRQ_RTC, rtc_interrupt); if (ret == OK) { diff --git a/arch/arm/src/lpc17xx/lpc17_allocateheap.c b/arch/arm/src/lpc17xx/lpc17_allocateheap.c index 577de74053f..491a3445af5 100644 --- a/arch/arm/src/lpc17xx/lpc17_allocateheap.c +++ b/arch/arm/src/lpc17xx/lpc17_allocateheap.c @@ -155,15 +155,23 @@ /* Sanity checking */ +#if !defined(CONFIG_LPC17_EXTDRAMHEAP) && !defined(CONFIG_LPC17_EXTSRAM0HEAP) +# define LPC17_EXT_MM_REGIONS 0 +#elif defined(CONFIG_LPC17_EXTDRAMHEAP) && defined(CONFIG_LPC17_EXTSRAM0HEAP) +# define LPC17_EXT_MM_REGIONS 2 +#else +# define LPC17_EXT_MM_REGIONS 1 +#endif + #ifdef LPC17_AHB_HEAPBASE -# if CONFIG_MM_REGIONS < 2 +# if CONFIG_MM_REGIONS < 2 + LPC17_EXT_MM_REGIONS # warning "CONFIG_MM_REGIONS < 2: Available AHB SRAM Bank(s) not included in HEAP" # endif -# if CONFIG_MM_REGIONS > 2 +# if (CONFIG_MM_REGIONS > 2 + LPC17_EXT_MM_REGIONS) # warning "CONFIG_MM_REGIONS > 2: Are additional regions handled by application?" # endif #else -# if CONFIG_MM_REGIONS > 1 +# if CONFIG_MM_REGIONS > 1 + LPC17_EXT_MM_REGIONS # warning "CONFIG_MM_REGIONS > 1: This configuration has no available AHB SRAM Bank0/1" # warning "CONFIG_MM_REGIONS > 1: Are additional regions handled by application?" # endif @@ -340,5 +348,16 @@ void up_addregion(void) kumm_addregion((FAR void*)LPC17_AHB_HEAPBASE, LPC17_AHB_HEAPSIZE); #endif + +#if CONFIG_MM_REGIONS >= 3 +#if defined(CONFIG_LPC17_EXTDRAM) && defined(CONFIG_LPC17_EXTDRAMHEAP) + kmm_addregion((FAR void*)LPC17_EXTDRAM_CS0, CONFIG_LPC17_EXTDRAMSIZE); +#endif +#if !defined(CONFIG_LPC17_EXTDRAMHEAP) || (CONFIG_MM_REGIONS >= 4) +#if defined(CONFIG_LPC17_EXTSRAM0) && defined(CONFIG_LPC17_EXTSRAM0HEAP) + kmm_addregion((FAR void*)LPC17_EXTSRAM_CS0, CONFIG_LPC17_EXTSRAM0SIZE); +#endif +#endif +#endif } #endif diff --git a/arch/arm/src/lpc17xx/lpc17_can.c b/arch/arm/src/lpc17xx/lpc17_can.c index 8334e01ab1f..310330dc4ed 100644 --- a/arch/arm/src/lpc17xx/lpc17_can.c +++ b/arch/arm/src/lpc17xx/lpc17_can.c @@ -750,7 +750,8 @@ static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg) irqstate_t flags; int ret = OK; - canvdbg("CAN%d ID: %d DLC: %d\n", priv->port, msg->cm_hdr.ch_id, msg->cm_hdr.ch_dlc); + canvdbg("CAN%d ID: %d DLC: %d\n", + priv->port, msg->cm_hdr.ch_id, msg->cm_hdr.ch_dlc); if (msg->cm_hdr.ch_rtr) { @@ -971,12 +972,15 @@ static void can_interrupt(FAR struct can_dev_s *dev) /* Construct the CAN header */ - hdr.ch_id = rid; - hdr.ch_rtr = ((rfs & CAN_RFS_RTR) != 0); - hdr.ch_dlc = (rfs & CAN_RFS_DLC_MASK) >> CAN_RFS_DLC_SHIFT; + hdr.ch_id = rid; + hdr.ch_rtr = ((rfs & CAN_RFS_RTR) != 0); + hdr.ch_dlc = (rfs & CAN_RFS_DLC_MASK) >> CAN_RFS_DLC_SHIFT; + hdr.ch_error = 0; #ifdef CONFIG_CAN_EXTID - hdr.ch_extid = ((rfs & CAN_RFS_FF) != 0); + hdr.ch_extid = ((rfs & CAN_RFS_FF) != 0); #else + hdr.ch_unused = 0; + if ((rfs & CAN_RFS_FF) != 0) { canlldbg("ERROR: Received message with extended identifier. Dropped\n"); diff --git a/arch/arm/src/lpc17xx/lpc17_ethernet.c b/arch/arm/src/lpc17xx/lpc17_ethernet.c index 3fa7028a788..02fcc2a3353 100644 --- a/arch/arm/src/lpc17xx/lpc17_ethernet.c +++ b/arch/arm/src/lpc17xx/lpc17_ethernet.c @@ -1564,7 +1564,7 @@ static void lpc17_poll_process(FAR struct lpc17_driver_s *priv) if (considx != prodidx) { -#if CONFIG_NET_NOINTS +#ifdef CONFIG_NET_NOINTS work_queue(HPWORK, &priv->lp_rxwork, (worker_t)lpc17_rxdone_work, priv, 0); diff --git a/arch/arm/src/lpc17xx/lpc17_gpdma.h b/arch/arm/src/lpc17xx/lpc17_gpdma.h index 0136ac105f8..4e1e499eb1c 100644 --- a/arch/arm/src/lpc17xx/lpc17_gpdma.h +++ b/arch/arm/src/lpc17xx/lpc17_gpdma.h @@ -60,7 +60,7 @@ typedef FAR void *DMA_HANDLE; * function is called at the completion of the DMA transfer. 'arg' is the * same 'arg' value that was provided when lpc17_dmastart() was called and * result indicates the result of the transfer: Zero indicates a successful - * tranfers. On failure, a negated errno is returned indicating the general + * transfers. On failure, a negated errno is returned indicating the general * nature of the DMA faiure. */ diff --git a/arch/arm/src/lpc17xx/lpc17_irq.c b/arch/arm/src/lpc17xx/lpc17_irq.c index 29f398c8e3e..7a6005c71fb 100644 --- a/arch/arm/src/lpc17xx/lpc17_irq.c +++ b/arch/arm/src/lpc17xx/lpc17_irq.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/lpc17/lpc17_irq.c * - * Copyright (C) 2010-2011, 2013-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2010-2011, 2013-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -76,11 +76,17 @@ * Public Data ****************************************************************************/ +/* This is the address of current interrupt saved state data. Used for + * context switching. Only value during interrupt handling. + */ + volatile uint32_t *current_regs; -/**************************************************************************** - * Private Data - ****************************************************************************/ +/* This is the address of the exception vector table (determined by the + * linker script). + */ + +extern uint32_t _vectors[]; /**************************************************************************** * Private Functions @@ -313,8 +319,21 @@ void up_irqinitialize(void) putreg32(0, regaddr); } + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. + * + * But even in this case NVIC_VECTAB has to point to the initial table + * because up_ramvec_initialize() initializes RAM table from table + * pointed by NVIC_VECTAB register. */ #ifdef CONFIG_ARCH_RAMVECTORS diff --git a/arch/arm/src/lpc17xx/lpc17_lcd.c b/arch/arm/src/lpc17xx/lpc17_lcd.c index ebc43759688..001364a386b 100644 --- a/arch/arm/src/lpc17xx/lpc17_lcd.c +++ b/arch/arm/src/lpc17xx/lpc17_lcd.c @@ -565,7 +565,7 @@ int up_fbinitialize(void) /* TFT panel */ -#if CONFIG_LPC17_LCD_TFTPANEL +#ifdef CONFIG_LPC17_LCD_TFTPANEL regval |= LCD_CTRL_LCDTFT; #endif diff --git a/arch/arm/src/lpc17xx/lpc17_sdcard.c b/arch/arm/src/lpc17xx/lpc17_sdcard.c index 74208f7c7d5..543318fe72a 100644 --- a/arch/arm/src/lpc17xx/lpc17_sdcard.c +++ b/arch/arm/src/lpc17xx/lpc17_sdcard.c @@ -67,7 +67,7 @@ #include "chip/lpc17_syscon.h" #include "chip/lpc17_pinconfig.h" -#if CONFIG_LPC17_SDCARD +#ifdef CONFIG_LPC17_SDCARD /**************************************************************************** * Pre-processor Definitions diff --git a/arch/arm/src/lpc17xx/lpc17_usbdev.c b/arch/arm/src/lpc17xx/lpc17_usbdev.c index 876584ba337..a7a914f0aef 100644 --- a/arch/arm/src/lpc17xx/lpc17_usbdev.c +++ b/arch/arm/src/lpc17xx/lpc17_usbdev.c @@ -2088,7 +2088,7 @@ static int lpc17_usbinterrupt(int irq, FAR void *context) #endif -#if CONFIG_DEBUG +#ifdef CONFIG_DEBUG /* USB engine error interrupt */ if ((devintstatus & USBDEV_INT_ERRINT) != 0) @@ -2457,7 +2457,7 @@ static int lpc17_dmasetup(struct lpc17_usbdev_s *priv, uint8_t epphy, dmadesc->size = (uint32_t)packet; #endif - /* Enable DMA tranfer for this endpoint */ + /* Enable DMA transfer for this endpoint */ putreq32(1 << epphy, LPC17_USBDEV_EPDMAEN); diff --git a/arch/arm/src/lpc214x/lpc214x_usbdev.c b/arch/arm/src/lpc214x/lpc214x_usbdev.c index f1d21bab434..5fb688c034c 100644 --- a/arch/arm/src/lpc214x/lpc214x_usbdev.c +++ b/arch/arm/src/lpc214x/lpc214x_usbdev.c @@ -212,7 +212,7 @@ /* USB RAM ******************************************************************** * - * UBS_UDCA is is list of 32 pointers to DMA desciptors located at the + * UBS_UDCA is is list of 32 pointers to DMA descriptors located at the * beginning of USB RAM. Each pointer points to a DMA descriptor with * assocated DMA buffer. */ @@ -2052,7 +2052,7 @@ static int lpc214x_usbinterrupt(int irq, FAR void *context) #endif -#if CONFIG_DEBUG +#ifdef CONFIG_DEBUG /* USB engine error interrupt */ if ((devintstatus & USBDEV_DEVINT_EPRINT)) @@ -2422,7 +2422,7 @@ static int lpc214x_dmasetup(struct lpc214x_usbdev_s *priv, uint8_t epphy, dmadesc->size = (uint32_t)packet; #endif - /* Enable DMA tranfer for this endpoint */ + /* Enable DMA transfer for this endpoint */ putreq32(1 << epphy, LPC214X_USBDEV_EPDMAEN); diff --git a/arch/arm/src/lpc43xx/Kconfig b/arch/arm/src/lpc43xx/Kconfig index 1491120fbed..808c8955440 100644 --- a/arch/arm/src/lpc43xx/Kconfig +++ b/arch/arm/src/lpc43xx/Kconfig @@ -163,6 +163,151 @@ config LPC43_ETHERNET bool "Ethernet" default n +if LPC43_ETHERNET +menu "Ethernet MAC configuration" + +config LPC43_PHYADDR + int "PHY address" + default 1 + ---help--- + The 5-bit address of the PHY on the board. Default: 1 + +config LPC43_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 + LPC43_PHYINIT is defined in the configuration then the board specific logic must + provide lpc43_phyinitialize(); The LPC43 Ethernet driver will call this function + one time before it first uses the PHY. + +config LPC43_MII + bool "Use MII interface" + default n + ---help--- + Support Ethernet MII interface. + +config LPC43_AUTONEG + bool "Use autonegotiation" + default y + ---help--- + Use PHY autonegotiation to determine speed and mode + +config LPC43_ETHFD + bool "Full duplex" + default n + depends on !LPC43_AUTONEG + ---help--- + If LPC43_AUTONEG is not defined, then this may be defined to select full duplex + mode. Default: half-duplex + +config LPC43_ETH100MBPS + bool "100 Mbps" + default n + depends on !LPC43_AUTONEG + ---help--- + If LPC43_AUTONEG is not defined, then this may be defined to select 100 MBps + speed. Default: 10 Mbps + +config LPC43_PHYSR + int "PHY Status Register Address (decimal)" + depends on LPC43_AUTONEG + ---help--- + This must be provided if LPC43_AUTONEG is defined. The PHY status register + address may diff from PHY to PHY. This configuration sets the address of + the PHY status register. + +config LPC43_PHYSR_ALTCONFIG + bool "PHY Status Alternate Bit Layout" + default n + depends on LPC43_AUTONEG + ---help--- + Different PHYs present speed and mode information in different ways. Some + will present separate information for speed and mode (this is the default). + Those PHYs, for example, may provide a 10/100 Mbps indication and a separate + full/half duplex indication. This options selects an alternative representation + where speed and mode information are combined. This might mean, for example, + separate bits for 10HD, 100HD, 10FD and 100FD. + +config LPC43_PHYSR_SPEED + hex "PHY Speed Mask" + depends on LPC43_AUTONEG && !LPC43_PHYSR_ALTCONFIG + ---help--- + This must be provided if LPC43_AUTONEG is defined. This provides bit mask + for isolating the 10 or 100MBps speed indication. + +config LPC43_PHYSR_100MBPS + hex "PHY 100Mbps Speed Value" + depends on LPC43_AUTONEG && !LPC43_PHYSR_ALTCONFIG + ---help--- + This must be provided if LPC43_AUTONEG is defined. This provides the value + of the speed bit(s) indicating 100MBps speed. + +config LPC43_PHYSR_MODE + hex "PHY Mode Mask" + depends on LPC43_AUTONEG && !LPC43_PHYSR_ALTCONFIG + ---help--- + This must be provided if LPC43_AUTONEG is defined. This provide bit mask + for isolating the full or half duplex mode bits. + +config LPC43_PHYSR_FULLDUPLEX + hex "PHY Full Duplex Mode Value" + depends on LPC43_AUTONEG && !LPC43_PHYSR_ALTCONFIG + ---help--- + This must be provided if LPC43_AUTONEG is defined. This provides the + value of the mode bits indicating full duplex mode. + +config LPC43_PHYSR_ALTMODE + hex "PHY Mode Mask" + depends on LPC43_AUTONEG && LPC43_PHYSR_ALTCONFIG + ---help--- + This must be provided if LPC43_AUTONEG is defined. This provide bit mask + for isolating the speed and full/half duplex mode bits. + +config LPC43_PHYSR_10HD + hex "10MBase-T Half Duplex Value" + depends on LPC43_AUTONEG && LPC43_PHYSR_ALTCONFIG + ---help--- + This must be provided if LPC43_AUTONEG is defined. This is the value + under the bit mask that represents the 10Mbps, half duplex setting. + +config LPC43_PHYSR_100HD + hex "100Base-T Half Duplex Value" + depends on LPC43_AUTONEG && LPC43_PHYSR_ALTCONFIG + ---help--- + This must be provided if LPC43_AUTONEG is defined. This is the value + under the bit mask that represents the 100Mbps, half duplex setting. + +config LPC43_PHYSR_10FD + hex "10Base-T Full Duplex Value" + depends on LPC43_AUTONEG && LPC43_PHYSR_ALTCONFIG + ---help--- + This must be provided if LPC43_AUTONEG is defined. This is the value + under the bit mask that represents the 10Mbps, full duplex setting. + +config LPC43_PHYSR_100FD + hex "100Base-T Full Duplex Value" + depends on LPC43_AUTONEG && LPC43_PHYSR_ALTCONFIG + ---help--- + This must be provided if LPC43_AUTONEG is defined. This is the value + under the bit mask that represents the 100Mbps, full duplex setting. + +config LPC43_RMII + bool + default y if !LPC43_MII + + +config LPC43_ETHERNET_REGDEBUG + bool "Register-Level Debug" + default n + depends on DEBUG + ---help--- + Enable very low-level register access debug. Depends on DEBUG. + +endmenu +endif + config LPC43_EVNTMNTR bool "Event Monitor" default n diff --git a/arch/arm/src/lpc43xx/Make.defs b/arch/arm/src/lpc43xx/Make.defs index dda686e7397..b15004c54d0 100644 --- a/arch/arm/src/lpc43xx/Make.defs +++ b/arch/arm/src/lpc43xx/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # arch/arm/src/lpc43xx/Make.defs # -# Copyright (C) 2012-2014 Gregory Nutt. All rights reserved. +# Copyright (C) 2012-2015 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -84,6 +84,8 @@ ifeq ($(CONFIG_ARCH_FPU),y) CMN_ASRCS += up_fpu.S ifneq ($(CONFIG_ARMV7M_CMNVECTOR),y) CMN_CSRCS += up_copyarmstate.c +else ifeq ($(CONFIG_ARMV7M_LAZYFPU),y) +CMN_CSRCS += up_copyarmstate.c endif endif @@ -116,6 +118,10 @@ ifeq ($(CONFIG_GPIO_IRQ),y) CHIP_CSRCS += lpc43_gpioint.c endif +ifeq ($(CONFIG_LPC43_ETHERNET),y) +CHIP_CSRCS += lpc43_ethernet.c +endif + ifeq ($(CONFIG_LPC43_SPI),y) CHIP_CSRCS += lpc43_spi.c endif diff --git a/arch/arm/src/lpc43xx/chip/lpc43_eeprom.h b/arch/arm/src/lpc43xx/chip/lpc43_eeprom.h index 19391d479b4..8b0398447ea 100644 --- a/arch/arm/src/lpc43xx/chip/lpc43_eeprom.h +++ b/arch/arm/src/lpc43xx/chip/lpc43_eeprom.h @@ -73,7 +73,7 @@ #define LPC43_EEPROM_RWSTATE (LPC43_EEPROMC_BASE+LPC43_EEPROM_RWSTATE_OFFSET) #define LPC43_EEPROM_AUTOPROG (LPC43_EEPROMC_BASE+LPC43_EEPROM_AUTOPROG_OFFSET) #define LPC43_EEPROM_WSTATE (LPC43_EEPROMC_BASE+LPC43_EEPROM_WSTATE_OFFSET) -# LPC43_EEPROM_CLKDIV (LPC43_EEPROMC_BASE+LPC43_EEPROM_CLKDIV_OFFSET) +#define LPC43_EEPROM_CLKDIV (LPC43_EEPROMC_BASE+LPC43_EEPROM_CLKDIV_OFFSET) #define LPC43_EEPROM_PWRDWN (LPC43_EEPROMC_BASE+LPC43_EEPROM_PWRDWN_OFFSET) /* EEPROM interrupt registers */ diff --git a/arch/arm/src/lpc43xx/chip/lpc43_ethernet.h b/arch/arm/src/lpc43xx/chip/lpc43_ethernet.h index c2db11db88b..6da125a6fee 100644 --- a/arch/arm/src/lpc43xx/chip/lpc43_ethernet.h +++ b/arch/arm/src/lpc43xx/chip/lpc43_ethernet.h @@ -181,7 +181,8 @@ /* MAC frame filter register */ #define ETH_MACFFLT_PR (1 << 0) /* Bit 0: Promiscuous mode */ - /* Bits 1-2: Reserved */ +#define ETH_MACFFLT_HUC (1 << 1) /* Bit 1: Hash Unicast */ +#define ETH_MACFFLT_HMC (1 << 2) /* Bit 2: Hash Multicast */ #define ETH_MACFFLT_DAIF (1 << 3) /* Bit 3: Destination address inverse filtering */ #define ETH_MACFFLT_PM (1 << 4) /* Bit 4: Pass all multicast */ #define ETH_MACFFLT_DBF (1 << 5) /* Bit 5: Disable Broadcast Frames */ @@ -191,9 +192,9 @@ # define ETH_MACFFLT_PCF_PAUSE (1 << ETH_MACFFLT_PCF_SHIFT) /* Prevents all except Pause control frames */ # define ETH_MACFFLT_PCF_ALL (2 << ETH_MACFFLT_PCF_SHIFT) /* Forwards all control frames */ # define ETH_MACFFLT_PCF_FILTER (3 << ETH_MACFFLT_PCF_SHIFT) /* Forwards all that pass address filter */ -#define ETH_MACFFLT_SAIF (1 << 8) /* Bit 8: Source address inverse filtering */ -#define ETH_MACFFLT_SAF (1 << 9) /* Bit 9: Source address filter */ - /* Bits 10-30: Reserved */ + /* Bit 8-9: Reserved */ +#define ETH_MACFFLT_HPF (1 << 10) /* Bit 10: Hash or perfect filter */ + /* Bits 11-30: Reserved */ #define ETH_MACFFLT_RA (1 << 31) /* Bit 31: Receive all */ /* MAC hash table high/low register (32-bit values) */ @@ -208,7 +209,7 @@ # define ETH_MACMIIA_CR_100_150 (1 << ETH_MACMIIA_CR_SHIFT) /* 100-150 MHz CLK_M4_ETHERNET/62 */ # define ETH_MACMIIA_CR_20_35 (2 << ETH_MACMIIA_CR_SHIFT) /* 20-35 MHz CLK_M4_ETHERNET/16 */ # define ETH_MACMIIA_CR_35_60 (3 << ETH_MACMIIA_CR_SHIFT) /* 35-60 MHz CLK_M4_ETHERNET/26 */ -# define ETH_MACMIIA_CR_150_168 (4 << ETH_MACMIIA_CR_SHIFT) /* 150-168 MHz CLK_M4_ETHERNET/102 */ +# define ETH_MACMIIA_CR_150_250 (4 << ETH_MACMIIA_CR_SHIFT) /* 150-250 MHz CLK_M4_ETHERNET/102 */ # define ETH_MACMIIA_CR_250_300 (5 << ETH_MACMIIA_CR_SHIFT) /* 250-300 MHz CLK_M4_ETHERNET/124 */ # define ETH_MACMIIA_CR_DIV42 (8 << ETH_MACMIIA_CR_SHIFT) /* 60-100 MHz CLK_M4_ETHERNET/42 */ # define ETH_MACMIIA_CR_DIV62 (9 << ETH_MACMIIA_CR_SHIFT) /* 100-150 MHz CLK_M4_ETHERNET/62 */ @@ -314,7 +315,7 @@ /* Bits 4-8: Reserved */ #define ETH_MACIM_TSIM (1 << 9) /* Bit 9: Time stamp interrupt mask */ /* Bits 10-31: Reserved */ -#define ETH_MACIM_ALLINTS (ETH_MACIM_PMTIM|ETH_MACIM_TSTIM) +#define ETH_MACIM_ALLINTS (ETH_MACIM_PMTIM|ETH_MACIM_TSIM) /* MAC address 0 high register */ @@ -499,9 +500,9 @@ #define ETH_TDES0_CC_MASK (15 << ETH_TDES0_CC_SHIFT) #define ETH_TDES0_VF (1 << 7) /* Bit 7: VLAN frame */ #define ETH_TDES0_EC (1 << 8) /* Bit 8: Excessive collision */ -#define ETH_TDES0_LC (1 << 9) /* Bit 9: Late collision */ +#define ETH_TDES0_LCL (1 << 9) /* Bit 9: Late collision */ #define ETH_TDES0_NC (1 << 10) /* Bit 10: No carrier */ -#define ETH_TDES0_LC (1 << 11) /* Bit 11: Loss of carrier */ +#define ETH_TDES0_LCR (1 << 11) /* Bit 11: Loss of carrier */ #define ETH_TDES0_IPE (1 << 12) /* Bit 12: IP payload error */ #define ETH_TDES0_FF (1 << 13) /* Bit 13: Frame flushed */ #define ETH_TDES0_JT (1 << 14) /* Bit 14: Jabber timeout */ @@ -536,7 +537,7 @@ #define ETH_RDES0_ESA (1 << 0) /* Bit 0: Extended status available */ #define ETH_RDES0_CE (1 << 1) /* Bit 1: CRC error */ -#define ETH_RDES0_DE (1 << 2) /* Bit 2: Dribble bit error */ +#define ETH_RDES0_DRE (1 << 2) /* Bit 2: Dribble bit error */ #define ETH_RDES0_RE (1 << 3) /* Bit 3: Receive error */ #define ETH_RDES0_RWT (1 << 4) /* Bit 4: Receive watchdog timeout */ #define ETH_RDES0_FT (1 << 5) /* Bit 5: Frame type */ @@ -548,7 +549,7 @@ #define ETH_RDES0_OE (1 << 11) /* Bit 11: Overflow error */ #define ETH_RDES0_LE (1 << 12) /* Bit 12: Length error */ #define ETH_RDES0_SAF (1 << 13) /* Bit 13: Source address filter fail */ -#define ETH_RDES0_DE (1 << 14) /* Bit 14: Descriptor error */ +#define ETH_RDES0_DS (1 << 14) /* Bit 14: Descriptor error */ #define ETH_RDES0_ES (1 << 15) /* Bit 15: Error summary */ #define ETH_RDES0_FL_SHIFT (16) /* Bits 16-29: Frame length */ #define ETH_RDES0_FL_MASK (0x3fff << ETH_RDES0_FL_SHIFT) @@ -584,12 +585,12 @@ * transparent clock) */ # define ETH_RDES4_MT_PDELREQMM (6 << ETH_RDES4_MT_SHIFT) /* Pdelay_Resp (in peer-to-peer * transparent clock) */ -# define ETH_RDES4_MT_PDELREQFUS (7 << ETH_RDES4_MT_SHIFT) /* Pdelay_Resp_Follow_Up (in +# define ETH_RDES4_MT_PDELRESFUS (7 << ETH_RDES4_MT_SHIFT) /* Pdelay_Resp_Follow_Up (in * peer-to-peer transparent clock) */ -# define ETH_RDES4_MT_PDELREQFUS (8 << ETH_RDES4_MT_SHIFT) /* Announce */ -# define ETH_RDES4_MT_PDELREQFUS (9 << ETH_RDES4_MT_SHIFT) /* Management */ -# define ETH_RDES4_MT_PDELREQFUS (10 << ETH_RDES4_MT_SHIFT) /* Signaling */ -# define ETH_RDES4_MT_PDELREQFUS (15 << ETH_RDES4_MT_SHIFT) /* PTP packet with Reserved message type */ +# define ETH_RDES4_MT_ANNOUNCE (8 << ETH_RDES4_MT_SHIFT) /* Announce */ +# define ETH_RDES4_MT_MANAGEMENT (9 << ETH_RDES4_MT_SHIFT) /* Management */ +# define ETH_RDES4_MT_SIGNALING (10 << ETH_RDES4_MT_SHIFT) /* Signaling */ +# define ETH_RDES4_MT_PTP (15 << ETH_RDES4_MT_SHIFT) /* PTP packet with Reserved message type */ #define ETH_RDES4_PTPTYPE (1 << 12) /* Bit 12: PTP frame type */ #define ETH_RDES4_PTPVERSION (1 << 13) /* Bit 13: PTP version */ /* Bits 14-31: Reserved */ @@ -662,6 +663,5 @@ extern "C" #endif #endif /* __ASSEMBLY__ */ -#endif /* LPC43_NETHERNET > 0 */ #endif /* __ARCH_ARM_SRC_LPC43XX_CHIP_LPC43_ETHERNET_H */ diff --git a/arch/arm/src/lpc43xx/lpc43_ethernet.c b/arch/arm/src/lpc43xx/lpc43_ethernet.c new file mode 100644 index 00000000000..8b0b2b6c243 --- /dev/null +++ b/arch/arm/src/lpc43xx/lpc43_ethernet.c @@ -0,0 +1,4008 @@ +/**************************************************************************** + * arch/arm/src/lpc43/lpc43_eth.c + * + * Copyright (C) 2011-2015 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 +#if defined(CONFIG_NET) && defined(CONFIG_LPC43_ETHERNET) + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#ifdef CONFIG_NET_NOINTS +# include +#endif + +#include +#include +#include +#if defined(CONFIG_NET_PKT) +# include +#endif + +#include "up_internal.h" + +#include "chip.h" +#include "lpc43_pinconfig.h" +#include "lpc43_ethernet.h" +#include "chip/lpc43_creg.h" +#include "chip/lpc43_cgu.h" +#include "lpc43_rgu.h" +#include "up_arch.h" +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +/* If processing is not done at the interrupt level, then high priority + * work queue support is required. + */ + +#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_HPWORK) +# error High priority work queue support is required +#endif + +#ifndef CONFIG_LPC43_PHYADDR +# error "CONFIG_LPC43_PHYADDR must be defined in the NuttX configuration" +#endif + +#if !defined(CONFIG_LPC43_MII) && !defined(CONFIG_LPC43_RMII) +# warning "Neither CONFIG_LPC43_MII nor CONFIG_LPC43_RMII defined" +#endif + +#if defined(CONFIG_LPC43_MII) && defined(CONFIG_LPC43_RMII) +# error "Both CONFIG_LPC43_MII and CONFIG_LPC43_RMII defined" +#endif + +#ifdef CONFIG_LPC43_AUTONEG +# ifndef CONFIG_LPC43_PHYSR +# error "CONFIG_LPC43_PHYSR must be defined in the NuttX configuration" +# endif +# ifdef CONFIG_LPC43_PHYSR_ALTCONFIG +# ifndef CONFIG_LPC43_PHYSR_ALTMODE +# error "CONFIG_LPC43_PHYSR_ALTMODE must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_LPC43_PHYSR_10HD +# error "CONFIG_LPC43_PHYSR_10HD must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_LPC43_PHYSR_100HD +# error "CONFIG_LPC43_PHYSR_100HD must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_LPC43_PHYSR_10FD +# error "CONFIG_LPC43_PHYSR_10FD must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_LPC43_PHYSR_100FD +# error "CONFIG_LPC43_PHYSR_100FD must be defined in the NuttX configuration" +# endif +# else +# ifndef CONFIG_LPC43_PHYSR_SPEED +# error "CONFIG_LPC43_PHYSR_SPEED must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_LPC43_PHYSR_100MBPS +# error "CONFIG_LPC43_PHYSR_100MBPS must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_LPC43_PHYSR_MODE +# error "CONFIG_LPC43_PHYSR_MODE must be defined in the NuttX configuration" +# endif +# ifndef CONFIG_LPC43_PHYSR_FULLDUPLEX +# error "CONFIG_LPC43_PHYSR_FULLDUPLEX must be defined in the NuttX configuration" +# endif +# endif +#endif + +#ifdef CONFIG_LPC43_ETH_PTP +# warning "CONFIG_LPC43_ETH_PTP is not yet supported" +#endif + +/* This driver does not use enhanced descriptors. Enhanced descriptors must + * be used, however, if time stamping or and/or IPv4 checksum offload is + * supported. + */ + +#undef CONFIG_LPC43_ETH_ENHANCEDDESC +#undef CONFIG_LPC43_ETH_HWCHECKSUM + +/* Ethernet buffer sizes, number of buffers, and number of descriptors */ + +#ifndef CONFIG_NET_MULTIBUFFER +# error "CONFIG_NET_MULTIBUFFER is required" +#endif + +/* Add 4 to the configured buffer size to account for the 2 byte checksum + * memory needed at the end of the maximum size packet. Buffer sizes must + * be an even multiple of 4, 8, or 16 bytes (depending on buswidth). We + * will use the 16-byte alignment in all cases. + */ + +#define OPTIMAL_ETH_BUFSIZE ((CONFIG_NET_ETH_MTU + 4 + 15) & ~15) + +#ifndef CONFIG_LPC43_ETH_BUFSIZE +# define CONFIG_LPC43_ETH_BUFSIZE OPTIMAL_ETH_BUFSIZE +#endif + +#if CONFIG_LPC43_ETH_BUFSIZE > ETH_TDES1_TBS1_MASK +# error "CONFIG_LPC43_ETH_BUFSIZE is too large" +#endif + +#if (CONFIG_LPC43_ETH_BUFSIZE & 15) != 0 +# error "CONFIG_LPC43_ETH_BUFSIZE must be aligned" +#endif + +#if CONFIG_LPC43_ETH_BUFSIZE != OPTIMAL_ETH_BUFSIZE +# warning "You using an incomplete/untested configuration" +#endif + +#ifndef CONFIG_LPC43_ETH_NRXDESC +# define CONFIG_LPC43_ETH_NRXDESC 8 +#endif +#ifndef CONFIG_LPC43_ETH_NTXDESC +# define CONFIG_LPC43_ETH_NTXDESC 4 +#endif + +/* We need at least one more free buffer than transmit buffers */ + +#define LPC43_ETH_NFREEBUFFERS (CONFIG_LPC43_ETH_NTXDESC+1) + +/* Extremely detailed register debug that you would normally never want + * enabled. + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_LPC43_ETHMAC_REGDEBUG +#endif + +/* Clocking *****************************************************************/ +/* Set MACMIIAR CR bits depending on HCLK setting */ + +#if BOARD_FCLKOUT_FREQUENCY >= 20000000 && BOARD_FCLKOUT_FREQUENCY < 35000000 +# define ETH_MACMIIA_CR ETH_MACMIIA_CR_20_35 +#elif BOARD_FCLKOUT_FREQUENCY >= 35000000 && BOARD_FCLKOUT_FREQUENCY < 60000000 +# define ETH_MACMIIA_CR ETH_MACMIIA_CR_35_60 +#elif BOARD_FCLKOUT_FREQUENCY >= 60000000 && BOARD_FCLKOUT_FREQUENCY < 100000000 +# define ETH_MACMIIA_CR ETH_MACMIIA_CR_60_100 +#elif BOARD_FCLKOUT_FREQUENCY >= 100000000 && BOARD_FCLKOUT_FREQUENCY < 150000000 +# define ETH_MACMIIA_CR ETH_MACMIIA_CR_100_150 +#elif BOARD_FCLKOUT_FREQUENCY >= 150000000 && BOARD_FCLKOUT_FREQUENCY <= 250000000 +# define ETH_MACMIIA_CR ETH_MACMIIA_CR_150_250 +#elif BOARD_FCLKOUT_FREQUENCY >= 250000000 && BOARD_FCLKOUT_FREQUENCY <= 350000000 +# define ETH_MACMIIA_CR ETH_MACMIIA_CR_250_300 +#else +# error "BOARD_FCLKOUT_FREQUENCY not supportable" +#endif + +/* Timing *******************************************************************/ +/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per + * second + */ + +#define LPC43_WDDELAY (1*CLK_TCK) +#define LPC43_POLLHSEC (1*2) + +/* TX timeout = 1 minute */ + +#define LPC43_TXTIMEOUT (60*CLK_TCK) + +/* PHY reset/configuration delays in milliseconds */ + +#define PHY_RESET_DELAY (65) +#define PHY_CONFIG_DELAY (1000) + +/* PHY read/write delays in loop counts */ + +#define PHY_READ_TIMEOUT (0x0004ffff) +#define PHY_WRITE_TIMEOUT (0x0004ffff) +#define PHY_RETRY_TIMEOUT (0x0004ffff) + +/* Register values **********************************************************/ + +/* Clear the MACCR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_MACCFG_RE Bit 2: Receiver enable + * ETH_MACCFG_TE Bit 3: Transmitter enable + * ETH_MACCFG_DC Bit 4: Deferral check + * ETH_MACCFG_BL Bits 5-6: Back-off limit + * ETH_MACCFG_APCS Bit 7: Automatic pad/CRC stripping + * ETH_MACCFG_RD Bit 9: Retry disable + * ETH_MACCFG_DM Bit 11: Duplex mode + * ETH_MACCFG_LM Bit 12: Loopback mode + * ETH_MACCFG_DO Bit 13: Receive own disable + * ETH_MACCFG_FES Bit 14: Fast Ethernet speed + * ETH_MACCFG_CSD Bit 16: Carrier sense disable + * ETH_MACCFG_IFG Bits 17-19: Interframe gap + * ETH_MACCFG_JD Bit 22: Jabber disable + * ETH_MACCFG_WD Bit 23: Watchdog disable + * ETH_MACCFG_CSTF Bits 25: CRC stripping for Type frames (F2/F4 only) + */ + +#define MACCR_CLEAR_BITS \ + (ETH_MACCFG_RE | ETH_MACCFG_TE | ETH_MACCFG_DF | ETH_MACCFG_BL_MASK | \ + ETH_MACCFG_ACS | ETH_MACCFG_RD | ETH_MACCFG_DM | \ + ETH_MACCFG_LM | ETH_MACCFG_DO | ETH_MACCFG_FES | ETH_MACCFG_DCRS | \ + ETH_MACCFG_JE | ETH_MACCFG_IFG_MASK | ETH_MACCFG_JD | ETH_MACCFG_WD) + + +/* The following bits are set or left zero unconditionally in all modes. + * + * ETH_MACCFG_RE Receiver enable 0 (disabled) + * ETH_MACCFG_TE Transmitter enable 0 (disabled) + * ETH_MACCFG_DC Deferral check 0 (disabled) + * ETH_MACCFG_BL Back-off limit 0 (10) + * ETH_MACCFG_APCS Automatic pad/CRC stripping 0 (disabled) + * ETH_MACCFG_RD Retry disable 1 (disabled) + * ETH_MACCFG_LM Loopback mode 0 (disabled) + * ETH_MACCFG_ROD Receive own disable 0 (enabled) + * ETH_MACCFG_CSD Carrier sense disable 0 (enabled) + * ETH_MACCFG_IFG Interframe gap 0 (96 bits) + * ETH_MACCFG_JD Jabber disable 0 (enabled) + * ETH_MACCFG_WD Watchdog disable 0 (enabled) + * ETH_MACCFG_CSTF CRC stripping for Type frames 0 (disabled, F2/F4 only) + * + * The following are set conditioinally based on mode and speed. + * + * ETH_MACCFG_DM Duplex mode Depends on priv->fduplex + * ETH_MACCFG_FES Fast Ethernet speed Depends on priv->mbps100 + */ + +# define MACCR_SET_BITS \ + (ETH_MACCFG_BL_10 | ETH_MACCFG_RD | ETH_MACCFG_IFG(96)) + + +/* Clear the MACCR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_MACFFR_PM Bit 0: Promiscuous mode + * ETH_MACFFR_HU Bit 1: Hash unicast + * ETH_MACFFR_HM Bit 2: Hash multicast + * ETH_MACFFR_DAIF Bit 3: Destination address inverse filtering + * ETH_MACFFR_PAM Bit 4: Pass all multicast + * ETH_MACFFR_BFD Bit 5: Broadcast frames disable + * ETH_MACFFR_PCF Bits 6-7: Pass control frames + * ETH_MACFFR_SAIF Bit 8: Source address inverse filtering + * ETH_MACFFR_SAF Bit 9: Source address filter + * ETH_MACFFR_HPF Bit 10: Hash or perfect filter + * ETH_MACFFR_RA Bit 31: Receive all + */ + +#define MACFFR_CLEAR_BITS \ + (ETH_MACFFLT_PR | ETH_MACFFLT_HUC | ETH_MACFFLT_HMC | ETH_MACFFLT_DAIF | \ + ETH_MACFFLT_PM | ETH_MACFFLT_DBF | ETH_MACFFLT_PCF_MASK | ETH_MACFFLT_HPF | \ + ETH_MACFFLT_RA) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ETH_MACFFLT_PM Promiscuous mode 0 (disabled) + * ETH_MACFFLT_HU Hash unicast 0 (perfect dest filtering) + * ETH_MACFFLT_HM Hash multicast 0 (perfect dest filtering) + * ETH_MACFFLT_DAIF Destination address inverse filtering 0 (normal) + * ETH_MACFFLT_PAM Pass all multicast 0 (Depends on HM bit) + * ETH_MACFFLT_BFD Broadcast frames disable 0 (enabled) + * ETH_MACFFLT_PCF Pass control frames 1 (block all but PAUSE) + * ETH_MACFFLT_HPF Hash or perfect filter 0 (Only matching frames passed) + * ETH_MACFFLT_RA Receive all 0 (disabled) + */ + +#define MACFFR_SET_BITS (ETH_MACFFLT_PCF_PAUSE) + +/* Clear the MACFCR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_MACFCR_FCB_BPA Bit 0: Flow control busy/back pressure activate + * ETH_MACFCR_TFCE Bit 1: Transmit flow control enable + * ETH_MACFCR_RFCE Bit 2: Receive flow control enable + * ETH_MACFCR_UPFD Bit 3: Unicast pause frame detect + * ETH_MACFCR_PLT Bits 4-5: Pause low threshold + * ETH_MACFCR_ZQPD Bit 7: Zero-quanta pause disable + * ETH_MACFCR_PT Bits 16-31: Pause time + */ + +#define MACFCR_CLEAR_MASK \ + (ETH_MACFC_FCB | ETH_MACFC_TFE | ETH_MACFC_RFE | ETH_MACFC_UP | \ + ETH_MACFC_PLT_MASK | ETH_MACFC_DZPQ | ETH_MACFC_PT_MASK) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ETH_MACFCR_FCB_BPA Flow control busy/back pressure activate 0 (no pause control frame) + * ETH_MACFCR_TFCE Transmit flow control enable 0 (disabled) + * ETH_MACFCR_RFCE Receive flow control enable 0 (disabled) + * ETH_MACFCR_UPFD Unicast pause frame detect 0 (disabled) + * ETH_MACFCR_PLT Pause low threshold 0 (pause time - 4) + * ETH_MACFCR_ZQPD Zero-quanta pause disable 1 (disabled) + * ETH_MACFCR_PT Pause time 0 + */ + +#define MACFCR_SET_MASK (ETH_MACFC_PLT(4) | ETH_MACFC_DZPQ) + +/* Clear the DMAOMR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_DMAOPMODE_SR Bit 1: Start/stop receive + * TH_DMAOMR_OSF Bit 2: Operate on second frame + * ETH_DMAOPMODE_RTC Bits 3-4: Receive threshold control + * ETH_DMAOPMODE_FUGF Bit 6: Forward undersized good frames + * ETH_DMAOPMODE_FEF Bit 7: Forward error frames + * ETH_DMAOPMODE_ST Bit 13: Start/stop transmission + * ETH_DMAOPMODE_TTC Bits 14-16: Transmit threshold control + * ETH_DMAOPMODE_FTF Bit 20: Flush transmit FIFO + * ETH_DMAOPMODE_TSF Bit 21: Transmit store and forward + * ETH_DMAOPMODE_DFRF Bit 24: Disable flushing of received frames + * ETH_DMAOPMODE_RSF Bit 25: Receive store and forward + * TH_DMAOMR_DTCEFD Bit 26: Dropping of TCP/IP checksum error frames disable + */ + +#define DMAOMR_CLEAR_MASK \ + (ETH_DMAOPMODE_SR | ETH_DMAOPMODE_OSF | ETH_DMAOPMODE_RTC_MASK | ETH_DMAOPMODE_FUF | \ + ETH_DMAOPMODE_FEF | ETH_DMAOPMODE_ST | ETH_DMAOPMODE_TTC_MASK | ETH_DMAOPMODE_FTF | \ + ETH_DMAOPMODE_DFF) + +/* The following bits are set or left zero unconditionally in all modes. + * + * ETH_DMAOPMODE_SR Start/stop receive 0 (not running) + * TH_DMAOMR_OSF Operate on second frame 1 (enabled) + * ETH_DMAOPMODE_RTC Receive threshold control 0 (64 bytes) + * ETH_DMAOPMODE_FUGF Forward undersized good frames 0 (disabled) + * ETH_DMAOPMODE_FEF Forward error frames 0 (disabled) + * ETH_DMAOPMODE_ST Start/stop transmission 0 (not running) + * ETH_DMAOPMODE_TTC Transmit threshold control 0 (64 bytes) + * ETH_DMAOPMODE_FTF Flush transmit FIFO 0 (no flush) + * ETH_DMAOPMODE_TSF Transmit store and forward Depends on CONFIG_LPC43_ETH_HWCHECKSUM + * ETH_DMAOPMODE_DFRF Disable flushing of received frames 0 (enabled) + * ETH_DMAOPMODE_RSF Receive store and forward Depends on CONFIG_LPC43_ETH_HWCHECKSUM + * TH_DMAOMR_DTCEFD Dropping of TCP/IP checksum error Depends on CONFIG_LPC43_ETH_HWCHECKSUM + * frames disable + * + * When the checksum offload feature is enabled, we need to enable the Store + * and Forward mode: the store and forward guarantee that a whole frame is + * stored in the FIFO, so the MAC can insert/verify the checksum, if the + * checksum is OK the DMA can handle the frame otherwise the frame is dropped + */ + +#if CONFIG_LPC43_ETH_HWCHECKSUM +# define DMAOMR_SET_MASK \ + (ETH_DMAOPMODE_OSF | ETH_DMAOPMODE_RTC_64 | ETH_DMAOPMODE_TTC_64 | \ + ETH_DMAOPMODE_TSF | ETH_DMAOPMODE_RSF) +#else +# define DMAOMR_SET_MASK \ + (ETH_DMAOPMODE_OSF | ETH_DMAOPMODE_RTC_64 | ETH_DMAOPMODE_TTC_64) +#endif + +/* Clear the DMABMR bits that will be setup during MAC initialization (or that + * are cleared unconditionally). Per the reference manual, all reserved bits + * must be retained at their reset value. + * + * ETH_DMABMODE_SR Bit 0: Software reset + * ETH_DMABMODE_DA Bit 1: DMA Arbitration + * ETH_DMABMODE_DSL Bits 2-6: Descriptor skip length + * ETH_DMABMODE_ATDS Bit 7: Enhanced descriptor format enable + * ETH_DMABMODE_PBL Bits 8-13: Programmable burst length + * ETH_DMABMODE_RTPR Bits 14-15: RX TX priority ratio + * ETH_DMABMODE_FB Bit 16: Fixed burst + * ETH_DMABMODE_RDP Bits 17-22: RX DMA PBL + * ETH_DMABMODE_USP Bit 23: Use separate PBL + * ETH_DMABMODE_FPM Bit 24: 4xPBL mode + * ETH_DMABMODE_AAB Bit 25: Address-aligned beats + * ETH_DMABMODE_MB Bit 26: Mixed burst (F2/F4 only) + */ + +#define DMABMR_CLEAR_MASK \ + (ETH_DMABMODE_SWR | ETH_DMABMODE_DA | ETH_DMABMODE_DSL_MASK | ETH_DMABMODE_ATDS | \ + ETH_DMABMODE_PBL_MASK | ETH_DMABMODE_PR_MASK | ETH_DMABMODE_FB | ETH_DMABMODE_RPBL_MASK | \ + ETH_DMABMODE_USP | ETH_DMABMODE_PBL8X | ETH_DMABMODE_AAL | ETH_DMABMODE_MB | ETH_DMABMODE_TXPR ) + + +/* The following bits are set or left zero unconditionally in all modes. + * + * + * ETH_DMABMODE_SR Software reset 0 (no reset) + * ETH_DMABMODE_DA DMA Arbitration 0 (round robin) + * ETH_DMABMODE_DSL Descriptor skip length 0 + * ETH_DMABMODE_ATDS Enhanced descriptor format enable Depends on CONFIG_LPC43_ETH_ENHANCEDDESC + * ETH_DMABMODE_PBL Programmable burst length 32 beats + * ETH_DMABMODE_RTPR RX TX priority ratio 2:1 + * ETH_DMABMODE_FB Fixed burst 1 (enabled) + * ETH_DMABMODE_RDP RX DMA PBL 32 beats + * ETH_DMABMODE_USP Use separate PBL 1 (enabled) + * ETH_DMABMODE_FPM 4xPBL mode 0 (disabled) + * ETH_DMABMODE_AAB Address-aligned beats 1 (enabled) + * ETH_DMABMODE_MB Mixed burst 0 (disabled, F2/F4 only) + */ + +#ifdef CONFIG_LPC43_ETH_ENHANCEDDESC +# define DMABMR_SET_MASK \ + (ETH_DMABMODE_DSL(0) | ETH_DMABMODE_PBL(32) | ETH_DMABMODE_ATDS | ETH_DMABMODE_RTPR_2TO1 | \ + ETH_DMABMODE_FB | ETH_DMABMODE_RPBL(32) | ETH_DMABMODE_USP | ETH_DMABMODE_AAB) +#else +# define DMABMR_SET_MASK \ + (ETH_DMABMODE_DSL(0) | ETH_DMABMODE_PBL(32) | ETH_DMABMODE_PR_2TO1 | ETH_DMABMODE_FB | \ + ETH_DMABMODE_RPBL(32) | ETH_DMABMODE_USP | ETH_DMABMODE_AAL) +#endif + +/* Interrupt bit sets *******************************************************/ +/* All interrupts in the normal and abnormal interrupt summary. Early transmit + * interrupt (ETI) is excluded from the abnormal set because it causes too + * many interrupts and is not interesting. + */ + +#define ETH_DMAINT_NORMAL \ + (ETH_DMAINT_TI | ETH_DMAINT_TU |ETH_DMAINT_RI | ETH_DMAINT_ERI) + +#define ETH_DMAINT_ABNORMAL \ + (ETH_DMAINT_TPS | ETH_DMAINT_TJT | ETH_DMAINT_OVF | ETH_DMAINT_UNF | \ + ETH_DMAINT_RU | ETH_DMAINT_RPS | ETH_DMAINT_RWT | /* ETH_DMAINT_ETI | */ \ + ETH_DMAINT_FBI) + +/* Normal receive, transmit, error interrupt enable bit sets */ + +#define ETH_DMAINT_RECV_ENABLE (ETH_DMAINT_NIS | ETH_DMAINT_RI) +#define ETH_DMAINT_XMIT_ENABLE (ETH_DMAINT_NIS | ETH_DMAINT_TI) +#define ETH_DMAINT_XMIT_DISABLE (ETH_DMAINT_TI) + +#ifdef CONFIG_DEBUG_NET +# define ETH_DMAINT_ERROR_ENABLE (ETH_DMAINT_AIS | ETH_DMAINT_ABNORMAL) +#else +# define ETH_DMAINT_ERROR_ENABLE (0) +#endif + +/* Helpers ******************************************************************/ +/* This is a helper pointer for accessing the contents of the Ethernet + * header + */ + +#define BUF ((struct eth_hdr_s *)priv->dev.d_buf) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The lpc43_ethmac_s encapsulates all state information for a single hardware + * interface + */ + +struct lpc43_ethmac_s +{ + uint8_t ifup : 1; /* true:ifup false:ifdown */ + uint8_t mbps100 : 1; /* 100MBps operation (vs 10 MBps) */ + uint8_t fduplex : 1; /* Full (vs. half) duplex */ + WDOG_ID txpoll; /* TX poll timer */ + WDOG_ID txtimeout; /* TX timeout timer */ +#ifdef CONFIG_NET_NOINTS + struct work_s work; /* For deferring work to the work queue */ +#endif + + /* This holds the information visible to uIP/NuttX */ + + struct net_driver_s dev; /* Interface understood by uIP */ + + /* Used to track transmit and receive descriptors */ + + struct eth_txdesc_s *txhead; /* Next available TX descriptor */ + struct eth_rxdesc_s *rxhead; /* Next available RX descriptor */ + + struct eth_txdesc_s *txtail; /* First "in_flight" TX descriptor */ + struct eth_rxdesc_s *rxcurr; /* First RX descriptor of the segment */ + uint16_t segments; /* RX segment count */ + uint16_t inflight; /* Number of TX transfers "in_flight" */ + sq_queue_t freeb; /* The free buffer list */ + + /* Descriptor allocations */ + + struct eth_rxdesc_s rxtable[CONFIG_LPC43_ETH_NRXDESC]; + struct eth_txdesc_s txtable[CONFIG_LPC43_ETH_NTXDESC]; + + /* Buffer allocations */ + + uint8_t rxbuffer[CONFIG_LPC43_ETH_NRXDESC*CONFIG_LPC43_ETH_BUFSIZE]; + uint8_t alloc[LPC43_ETH_NFREEBUFFERS*CONFIG_LPC43_ETH_BUFSIZE]; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct lpc43_ethmac_s g_lpc43ethmac; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* Register operations ******************************************************/ + +#if defined(CONFIG_LPC43_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG) +static uint32_t lpc43_getreg(uint32_t addr); +static void lpc43_putreg(uint32_t val, uint32_t addr); +static void lpc43_checksetup(void); +#else +# define lpc43_getreg(addr) getreg32(addr) +# define lpc43_putreg(val,addr) putreg32(val,addr) +# define lpc43_checksetup() +#endif + +/* Free buffer management */ + +static void lpc43_initbuffer(FAR struct lpc43_ethmac_s *priv); +static inline uint8_t *lpc43_allocbuffer(FAR struct lpc43_ethmac_s *priv); +static inline void lpc43_freebuffer(FAR struct lpc43_ethmac_s *priv, uint8_t *buffer); +static inline bool lpc43_isfreebuffer(FAR struct lpc43_ethmac_s *priv); + +/* Common TX logic */ + +static int lpc43_transmit(FAR struct lpc43_ethmac_s *priv); +static int lpc43_txpoll(struct net_driver_s *dev); +static void lpc43_dopoll(FAR struct lpc43_ethmac_s *priv); + +/* Interrupt handling */ + +static void lpc43_enableint(FAR struct lpc43_ethmac_s *priv, uint32_t ierbit); +static void lpc43_disableint(FAR struct lpc43_ethmac_s *priv, uint32_t ierbit); + +static void lpc43_freesegment(FAR struct lpc43_ethmac_s *priv, + FAR struct eth_rxdesc_s *rxfirst, int segments); +static int lpc43_recvframe(FAR struct lpc43_ethmac_s *priv); +static void lpc43_receive(FAR struct lpc43_ethmac_s *priv); +static void lpc43_freeframe(FAR struct lpc43_ethmac_s *priv); +static void lpc43_txdone(FAR struct lpc43_ethmac_s *priv); +#ifdef CONFIG_NET_NOINTS +static void lpc43_interrupt_work(FAR void *arg); +#endif +static int lpc43_interrupt(int irq, FAR void *context); + +/* Watchdog timer expirations */ + +static inline void lpc43_txtimeout_process(FAR struct lpc43_ethmac_s *priv); +#ifdef CONFIG_NET_NOINTS +static void lpc43_txtimeout_work(FAR void *arg); +#endif +static void lpc43_txtimeout_expiry(int argc, uint32_t arg, ...); + +static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv); +#ifdef CONFIG_NET_NOINTS +static void lpc43_poll_work(FAR void *arg); +#endif +static void lpc43_poll_expiry(int argc, uint32_t arg, ...); + +/* NuttX callback functions */ + +static int lpc43_ifup(struct net_driver_s *dev); +static int lpc43_ifdown(struct net_driver_s *dev); +static inline void lpc43_txavail_process(FAR struct lpc43_ethmac_s *priv); +#ifdef CONFIG_NET_NOINTS +static void lpc43_txavail_work(FAR void *arg); +#endif +static int lpc43_txavail(struct net_driver_s *dev); +#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6) +static int lpc43_addmac(struct net_driver_s *dev, FAR const uint8_t *mac); +#endif +#ifdef CONFIG_NET_IGMP +static int lpc43_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac); +#endif +#ifdef CONFIG_NETDEV_PHY_IOCTL +static int lpc43_ioctl(struct net_driver_s *dev, int cmd, long arg); +#endif +/* Descriptor Initialization */ + +static void lpc43_txdescinit(FAR struct lpc43_ethmac_s *priv); +static void lpc43_rxdescinit(FAR struct lpc43_ethmac_s *priv); + +/* PHY Initialization */ +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int lpc43_phyintenable(FAR struct lpc43_ethmac_s *priv); +#endif +static int lpc43_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value); +static int lpc43_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value); +#ifdef CONFIG_ETH0_PHY_DM9161 +static inline int lpc43_dm9161(FAR struct lpc43_ethmac_s *priv); +#endif +static int lpc43_phyinit(FAR struct lpc43_ethmac_s *priv); + +/* MAC/DMA Initialization */ + +#ifdef CONFIG_LPC43_MII +static inline void lpc43_selectmii(void); +#endif +#ifdef CONFIG_LPC43_RMII +static inline void lpc43_selectrmii(void); +#endif +static inline void lpc43_ethgpioconfig(FAR struct lpc43_ethmac_s *priv); +static void lpc43_ethreset(FAR struct lpc43_ethmac_s *priv); +static int lpc43_macconfig(FAR struct lpc43_ethmac_s *priv); +static void lpc43_macaddress(FAR struct lpc43_ethmac_s *priv); +#ifdef CONFIG_NET_ICMPv6 +static void lpc43_ipv6multicast(FAR struct lpc43_ethmac_s *priv); +#endif +static int lpc43_macenable(FAR struct lpc43_ethmac_s *priv); +static int lpc43_ethconfig(FAR struct lpc43_ethmac_s *priv); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: lpc43_getreg + * + * Description: + * This function may to used to intercept an monitor all register accesses. + * Clearly this is nothing you would want to do unless you are debugging + * this driver. + * + * Input Parameters: + * addr - The register address to read + * + * Returned Value: + * The value read from the register + * + ****************************************************************************/ + +#if defined(CONFIG_LPC43_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG) +static uint32_t lpc43_getreg(uint32_t addr) +{ + static uint32_t prevaddr = 0; + static uint32_t preval = 0; + static uint32_t count = 0; + + /* Read the value from the register */ + + uint32_t val = getreg32(addr); + + /* Is this the same value that we read from the same register last time? + * Are we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && val == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + lldbg("...\n"); + } + return val; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + lldbg("[repeats %d more times]\n", count-3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = val; + count = 1; + } + + /* Show the register value read */ + + lldbg("%08x->%08x\n", addr, val); + return val; +} +#endif + +/**************************************************************************** + * Name: lpc43_putreg + * + * Description: + * This function may to used to intercept an monitor all register accesses. + * Clearly this is nothing you would want to do unless you are debugging + * this driver. + * + * Input Parameters: + * val - The value to write to the register + * addr - The register address to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_LPC43_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG) +static void lpc43_putreg(uint32_t val, uint32_t addr) +{ + /* Show the register value being written */ + + lldbg("%08x<-%08x\n", addr, val); + + /* Write the value */ + + putreg32(val, addr); +} +#endif + +/**************************************************************************** + * Name: lpc43_checksetup + * + * Description: + * Show the state of critical configuration registers. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_LPC43_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG) +static void lpc43_checksetup(void) +{ +} +#endif + +/**************************************************************************** + * Function: lpc43_initbuffer + * + * Description: + * Initialize the free buffer list. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called during early driver initialization before Ethernet interrupts + * are enabled. + * + ****************************************************************************/ + +static void lpc43_initbuffer(FAR struct lpc43_ethmac_s *priv) +{ + uint8_t *buffer; + int i; + + /* Initialize the head of the free buffer list */ + + sq_init(&priv->freeb); + + /* Add all of the pre-allocated buffers to the free buffer list */ + + for (i = 0, buffer = priv->alloc; + i < LPC43_ETH_NFREEBUFFERS; + i++, buffer += CONFIG_LPC43_ETH_BUFSIZE) + { + sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb); + } +} + +/**************************************************************************** + * Function: lpc43_allocbuffer + * + * Description: + * Allocate one buffer from the free buffer list. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * Pointer to the allocated buffer on success; NULL 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 inline uint8_t *lpc43_allocbuffer(FAR struct lpc43_ethmac_s *priv) +{ + /* Allocate a buffer by returning the head of the free buffer list */ + + return (uint8_t *)sq_remfirst(&priv->freeb); +} + +/**************************************************************************** + * Function: lpc43_freebuffer + * + * Description: + * Return a buffer to the free buffer list. + * + * Parameters: + * priv - Reference to the driver state structure + * buffer - A pointer to the buffer to be freed + * + * Returned Value: + * None + * + * 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 inline void lpc43_freebuffer(FAR struct lpc43_ethmac_s *priv, uint8_t *buffer) +{ + /* Free the buffer by adding it to to the end of the free buffer list */ + + sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb); +} + +/**************************************************************************** + * Function: lpc43_isfreebuffer + * + * Description: + * Return TRUE if the free buffer list is not empty. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * True if there are one or more buffers in the free buffer list; + * false if the free buffer list is empty + * + * Assumptions: + * None. + * + ****************************************************************************/ + +static inline bool lpc43_isfreebuffer(FAR struct lpc43_ethmac_s *priv) +{ + /* Return TRUE if the free buffer list is not empty */ + + return !sq_empty(&priv->freeb); +} + +/**************************************************************************** + * Function: lpc43_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * 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 lpc43_transmit(FAR struct lpc43_ethmac_s *priv) +{ + struct eth_txdesc_s *txdesc; + struct eth_txdesc_s *txfirst; + + /* The internal (optimal) uIP buffer size may be configured to be larger + * than the Ethernet buffer size. + */ + +#if OPTIMAL_ETH_BUFSIZE > CONFIG_LPC43_ETH_BUFSIZE + uint8_t *buffer; + int bufcount; + int lastsize; + int i; +#endif + + /* Verify that the hardware is ready to send another packet. If we get + * here, then we are committed to sending a packet; Higher level logic + * must have assured that there is no transmission in progress. + */ + + txdesc = priv->txhead; + txfirst = txdesc; + + nllvdbg("d_len: %d d_buf: %p txhead: %p tdes0: %08x\n", + priv->dev.d_len, priv->dev.d_buf, txdesc, txdesc->tdes0); + + DEBUGASSERT(txdesc && (txdesc->tdes0 & ETH_TDES0_OWN) == 0); + + /* Is the size to be sent greater than the size of the Ethernet buffer? */ + + DEBUGASSERT(priv->dev.d_len > 0 && priv->dev.d_buf != NULL); + +#if OPTIMAL_ETH_BUFSIZE > CONFIG_LPC43_ETH_BUFSIZE + if (priv->dev.d_len > CONFIG_LPC43_ETH_BUFSIZE) + { + /* Yes... how many buffers will be need to send the packet? */ + + bufcount = (priv->dev.d_len + (CONFIG_LPC43_ETH_BUFSIZE-1)) / CONFIG_LPC43_ETH_BUFSIZE; + lastsize = priv->dev.d_len - (bufcount - 1) * CONFIG_LPC43_ETH_BUFSIZE; + + nllvdbg("bufcount: %d lastsize: %d\n", bufcount, lastsize); + + /* Set the first segment bit in the first TX descriptor */ + + txdesc->tdes0 |= ETH_TDES0_FS; + + /* Set up all but the last TX descriptor */ + + buffer = priv->dev.d_buf; + + for (i = 0; i < bufcount; i++) + { + /* This could be a normal event but the design does not handle it */ + + DEBUGASSERT((txdesc->tdes0 & ETH_TDES0_OWN) == 0); + + /* Set the Buffer1 address pointer */ + + txdesc->tdes2 = (uint32_t)buffer; + + /* Set the buffer size in all TX descriptors */ + + if (i == (bufcount-1)) + { + /* This is the last segment. Set the last segment bit in the + * last TX descriptor and ask for an interrupt when this + * segment transfer completes. + */ + + txdesc->tdes0 |= (ETH_TDES0_LS | ETH_TDES0_IC); + + /* This segement is, most likely, of fractional buffersize */ + + txdesc->tdes1 = lastsize; + buffer += lastsize; + } + else + { + /* This is not the last segment. We don't want an interrupt + * when this segment transfer completes. + */ + + txdesc->tdes0 &= ~ETH_TDES0_IC; + + /* The size of the transfer is the whole buffer */ + + txdesc->tdes1 = CONFIG_LPC43_ETH_BUFSIZE; + buffer += CONFIG_LPC43_ETH_BUFSIZE; + } + + /* Give the descriptor to DMA */ + + txdesc->tdes0 |= ETH_TDES0_OWN; + txdesc = (struct eth_txdesc_s *)txdesc->tdes3; + } + } + else +#endif + { + /* The single descriptor is both the first and last segment. And we do + * want an interrupt when the transfer completes. + */ + + txdesc->tdes0 |= (ETH_TDES0_FS | ETH_TDES0_LS | ETH_TDES0_IC); + + /* Set frame size */ + + DEBUGASSERT(priv->dev.d_len <= CONFIG_NET_ETH_MTU); + txdesc->tdes1 = priv->dev.d_len; + + /* Set the Buffer1 address pointer */ + + txdesc->tdes2 = (uint32_t)priv->dev.d_buf; + + /* Set OWN bit of the TX descriptor tdes0. This gives the buffer to + * Ethernet DMA + */ + + txdesc->tdes0 |= ETH_TDES0_OWN; + + /* Point to the next available TX descriptor */ + + txdesc = (struct eth_txdesc_s *)txdesc->tdes3; + } + + /* Remember where we left off in the TX descriptor chain */ + + priv->txhead = txdesc; + + /* Detach the buffer from priv->dev structure. That buffer is now + * "in-flight". + */ + + priv->dev.d_buf = NULL; + priv->dev.d_len = 0; + + /* If there is no other TX buffer, in flight, then remember the location + * of the TX descriptor. This is the location to check for TX done events. + */ + + if (!priv->txtail) + { + DEBUGASSERT(priv->inflight == 0); + priv->txtail = txfirst; + } + + /* Increment the number of TX transfer in-flight */ + + priv->inflight++; + + nllvdbg("txhead: %p txtail: %p inflight: %d\n", + priv->txhead, priv->txtail, priv->inflight); + + /* If all TX descriptors are in-flight, then we have to disable receive interrupts + * too. This is because receive events can trigger more un-stoppable transmit + * events. + */ + + if (priv->inflight >= CONFIG_LPC43_ETH_NTXDESC) + { + lpc43_disableint(priv, ETH_DMAINT_RI); + } + + /* Check if the TX Buffer unavailable flag is set */ + + if ((lpc43_getreg(LPC43_ETH_DMASTAT) & ETH_DMAINT_TU) != 0) + { + /* Clear TX Buffer unavailable flag */ + + lpc43_putreg(ETH_DMAINT_TU, LPC43_ETH_DMASTAT); + + /* Resume DMA transmission */ + + lpc43_putreg(0, LPC43_ETH_DMATXPD); + } + + /* Enable TX interrupts */ + + lpc43_enableint(priv, ETH_DMAINT_TI); + + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ + + (void)wd_start(priv->txtimeout, LPC43_TXTIMEOUT, lpc43_txtimeout_expiry, 1, (uint32_t)priv); + return OK; +} + +/**************************************************************************** + * Function: lpc43_txpoll + * + * Description: + * The transmitter is available, check if uIP 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 + * + * 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 lpc43_txpoll(struct net_driver_s *dev) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)dev->d_private; + + DEBUGASSERT(priv->dev.d_buf != NULL); + + /* 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 */ + + /* Send the packet */ + + lpc43_transmit(priv); + DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); + + /* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We + * cannot perform the TX poll if we are unable to accept another packet for + * transmission. + * + * In a race condition, ETH_TDES0_OWN may be cleared BUT still not available + * because lpc43_freeframe() has not yet run. If lpc43_freeframe() has run, + * the buffer1 pointer (tdes2) will be nullified (and inflight should be < + * CONFIG_LPC43_ETH_NTXDESC). + */ + + if ((priv->txhead->tdes0 & ETH_TDES0_OWN) != 0 || + priv->txhead->tdes2 != 0) + { + /* We have to terminate the poll if we have no more descriptors + * available for another transfer. + */ + + return -EBUSY; + } + + /* We have the descriptor, we can continue the poll. Allocate a new + * buffer for the poll. + */ + + dev->d_buf = lpc43_allocbuffer(priv); + + /* We can't continue the poll if we have no buffers */ + + if (dev->d_buf == NULL) + { + /* Terminate the poll. */ + + return -ENOMEM; + } + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Function: lpc43_dopoll + * + * Description: + * The function is called when a frame is received using the DMA receive + * interrupt. It scans the RX descriptors to the received frame. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void lpc43_dopoll(FAR struct lpc43_ethmac_s *priv) +{ + FAR struct net_driver_s *dev = &priv->dev; + + /* Check if the next TX descriptor is owned by the Ethernet DMA or + * CPU. We cannot perform the TX poll if we are unable to accept + * another packet for transmission. + * + * In a race condition, ETH_TDES0_OWN may be cleared BUT still not available + * because lpc43_freeframe() has not yet run. If lpc43_freeframe() has run, + * the buffer1 pointer (tdes2) will be nullified (and inflight should be < + * CONFIG_LPC43_ETH_NTXDESC). + */ + + if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 && + priv->txhead->tdes2 == 0) + { + /* If we have the descriptor, then poll for new XMIT data. + * Allocate a buffer for the poll. + */ + + DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); + dev->d_buf = lpc43_allocbuffer(priv); + + /* We can't poll if we have no buffers */ + + if (dev->d_buf) + { + (void)devif_poll(dev, lpc43_txpoll); + + /* We will, most likely end up with a buffer to be freed. But it + * might not be the same one that we allocated above. + */ + + if (dev->d_buf) + { + DEBUGASSERT(dev->d_len == 0); + lpc43_freebuffer(priv, dev->d_buf); + dev->d_buf = NULL; + } + } + } +} + +/**************************************************************************** + * Function: lpc43_enableint + * + * Description: + * Enable a "normal" interrupt + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void lpc43_enableint(FAR struct lpc43_ethmac_s *priv, uint32_t ierbit) +{ + uint32_t regval; + + /* Enable the specified "normal" interrupt */ + + regval = lpc43_getreg(LPC43_ETH_DMAINTEN); + regval |= (ETH_DMAINT_NIS | ierbit); + lpc43_putreg(regval, LPC43_ETH_DMAINTEN); +} + +/**************************************************************************** + * Function: lpc43_disableint + * + * Description: + * Disable a normal interrupt. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void lpc43_disableint(FAR struct lpc43_ethmac_s *priv, uint32_t ierbit) +{ + uint32_t regval; + + /* Disable the "normal" interrupt */ + + regval = lpc43_getreg(LPC43_ETH_DMAINTEN); + regval &= ~ierbit; + + /* Are all "normal" interrupts now disabled? */ + + if ((regval & ETH_DMAINT_NORMAL) == 0) + { + /* Yes.. disable normal interrupts */ + + regval &= ~ETH_DMAINT_NIS; + } + + lpc43_putreg(regval, LPC43_ETH_DMAINTEN); +} + +/**************************************************************************** + * Function: lpc43_freesegment + * + * Description: + * The function is called when a frame is received using the DMA receive + * interrupt. It scans the RX descriptors to the received frame. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void lpc43_freesegment(FAR struct lpc43_ethmac_s *priv, + FAR struct eth_rxdesc_s *rxfirst, int segments) +{ + struct eth_rxdesc_s *rxdesc; + int i; + + nllvdbg("rxfirst: %p segments: %d\n", rxfirst, segments); + + /* Set OWN bit in RX descriptors. This gives the buffers back to DMA */ + + rxdesc = rxfirst; + for (i = 0; i < segments; i++) + { + rxdesc->rdes0 = ETH_RDES0_OWN; + rxdesc = (struct eth_rxdesc_s *)rxdesc->rdes3; + } + + /* Reset the segment management logic */ + + priv->rxcurr = NULL; + priv->segments = 0; + + /* Check if the RX Buffer unavailable flag is set */ + + if ((lpc43_getreg(LPC43_ETH_DMASTAT) & ETH_DMAINT_RU) != 0) + { + /* Clear RBUS Ethernet DMA flag */ + + lpc43_putreg(ETH_DMAINT_RU, LPC43_ETH_DMASTAT); + + /* Resume DMA reception */ + + lpc43_putreg(0, LPC43_ETH_DMARXPD); + } +} + +/**************************************************************************** + * Function: lpc43_recvframe + * + * Description: + * The function is called when a frame is received using the DMA receive + * interrupt. It scans the RX descriptors of the received frame. + * + * NOTE: This function will silently discard any packets containing errors. + * + * 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. + * + ****************************************************************************/ + +static int lpc43_recvframe(FAR struct lpc43_ethmac_s *priv) +{ + struct eth_rxdesc_s *rxdesc; + struct eth_rxdesc_s *rxcurr; + uint8_t *buffer; + int i; + + nllvdbg("rxhead: %p rxcurr: %p segments: %d\n", + priv->rxhead, priv->rxcurr, priv->segments); + + /* Check if there are free buffers. We cannot receive new frames in this + * design unless there is at least one free buffer. + */ + + if (!lpc43_isfreebuffer(priv)) + { + nlldbg("No free buffers\n"); + return -ENOMEM; + } + + /* Scan descriptors owned by the CPU. Scan until: + * + * 1) We find a descriptor still owned by the DMA, + * 2) We have examined all of the RX descriptors, or + * 3) All of the TX descriptors are in flight. + * + * This last case is obscure. It is due to that fact that each packet + * that we receive can generate an unstoppable transmission. So we have + * to stop receiving when we can not longer transmit. In this case, the + * transmit logic should also have disabled further RX interrupts. + */ + + rxdesc = priv->rxhead; + for (i = 0; + (rxdesc->rdes0 & ETH_RDES0_OWN) == 0 && + i < CONFIG_LPC43_ETH_NRXDESC && + priv->inflight < CONFIG_LPC43_ETH_NTXDESC; + i++) + { + /* Check if this is the first segment in the frame */ + + if ((rxdesc->rdes0 & ETH_RDES0_FS) != 0 && + (rxdesc->rdes0 & ETH_RDES0_LS) == 0) + { + priv->rxcurr = rxdesc; + priv->segments = 1; + } + + /* Check if this is an intermediate segment in the frame */ + + else if (((rxdesc->rdes0 & ETH_RDES0_LS) == 0)&& + ((rxdesc->rdes0 & ETH_RDES0_FS) == 0)) + { + priv->segments++; + } + + /* Otherwise, it is the last segment in the frame */ + + else + { + priv->segments++; + + /* Check if the there is only one segment in the frame */ + + if (priv->segments == 1) + { + rxcurr = rxdesc; + } + else + { + rxcurr = priv->rxcurr; + } + + nllvdbg("rxhead: %p rxcurr: %p segments: %d\n", + priv->rxhead, priv->rxcurr, priv->segments); + + /* Check if any errors are reported in the frame */ + + if ((rxdesc->rdes0 & ETH_RDES0_ES) == 0) + { + struct net_driver_s *dev = &priv->dev; + + /* Get the Frame Length of the received packet: subtract 4 + * bytes of the CRC + */ + + dev->d_len = ((rxdesc->rdes0 & ETH_RDES0_FL_MASK) >> ETH_RDES0_FL_SHIFT) - 4; + + /* Get a buffer from the free list. We don't even check if + * this is successful because we already assure the free + * list is not empty above. + */ + + buffer = lpc43_allocbuffer(priv); + + /* Take the buffer from the RX descriptor of the first free + * segment, put it into the uIP device structure, then replace + * the buffer in the RX descriptor with the newly allocated + * buffer. + */ + + DEBUGASSERT(dev->d_buf == NULL); + dev->d_buf = (uint8_t*)rxcurr->rdes2; + rxcurr->rdes2 = (uint32_t)buffer; + + /* Return success, remembering where we should re-start scanning + * and resetting the segment scanning logic + */ + + priv->rxhead = (struct eth_rxdesc_s*)rxdesc->rdes3; + lpc43_freesegment(priv, rxcurr, priv->segments); + + nllvdbg("rxhead: %p d_buf: %p d_len: %d\n", + priv->rxhead, dev->d_buf, dev->d_len); + + return OK; + } + else + { + /* Drop the frame that contains the errors, reset the segment + * scanning logic, and continue scanning with the next frame. + */ + + nlldbg("DROPPED: RX descriptor errors: %08x\n", rxdesc->rdes0); + lpc43_freesegment(priv, rxcurr, priv->segments); + } + } + + /* Try the next descriptor */ + + rxdesc = (struct eth_rxdesc_s*)rxdesc->rdes3; + } + + /* We get here after all of the descriptors have been scanned or when rxdesc points + * to the first descriptor owned by the DMA. Remember where we left off. + */ + + priv->rxhead = rxdesc; + + nllvdbg("rxhead: %p rxcurr: %p segments: %d\n", + priv->rxhead, priv->rxcurr, priv->segments); + + return -EAGAIN; +} + +/**************************************************************************** + * Function: lpc43_receive + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void lpc43_receive(FAR struct lpc43_ethmac_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + + /* Loop while while lpc43_recvframe() successfully retrieves valid + * Ethernet frames. + */ + + while (lpc43_recvframe(priv) == OK) + { +#ifdef CONFIG_NET_PKT + /* When packet sockets are enabled, feed the frame into the packet tap */ + + pkt_input(&priv->dev); +#endif + + /* Check if the packet is a valid size for the uIP buffer configuration + * (this should not happen) + */ + + if (dev->d_len > CONFIG_NET_ETH_MTU) + { + nlldbg("DROPPED: Too big: %d\n", dev->d_len); + /* Free dropped packet buffer */ + + if (dev->d_buf) + { + lpc43_freebuffer(priv, dev->d_buf); + dev->d_buf = NULL; + dev->d_len = 0; + } + + 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)) + { + nllvdbg("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 */ + + lpc43_transmit(priv); + } + } + else +#endif +#ifdef CONFIG_NET_IPv6 + if (BUF->type == HTONS(ETHTYPE_IP6)) + { + nllvdbg("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 */ + + lpc43_transmit(priv); + } + } + else +#endif +#ifdef CONFIG_NET_ARP + if (BUF->type == htons(ETHTYPE_ARP)) + { + nllvdbg("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) + { + lpc43_transmit(priv); + } + } + else +#endif + { + nlldbg("DROPPED: Unknown type: %04x\n", BUF->type); + } + + /* We are finished with the RX buffer. NOTE: If the buffer is + * re-used for transmission, the dev->d_buf field will have been + * nullified. + */ + + if (dev->d_buf) + { + /* Free the receive packet buffer */ + + lpc43_freebuffer(priv, dev->d_buf); + dev->d_buf = NULL; + dev->d_len = 0; + } + } +} + +/**************************************************************************** + * Function: lpc43_freeframe + * + * Description: + * Scans the TX descriptors and frees the buffers of completed TX transfers. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void lpc43_freeframe(FAR struct lpc43_ethmac_s *priv) +{ + struct eth_txdesc_s *txdesc; + int i; + + nllvdbg("txhead: %p txtail: %p inflight: %d\n", + priv->txhead, priv->txtail, priv->inflight); + + /* Scan for "in-flight" descriptors owned by the CPU */ + + txdesc = priv->txtail; + if (txdesc) + { + DEBUGASSERT(priv->inflight > 0); + + for (i = 0; (txdesc->tdes0 & ETH_TDES0_OWN) == 0; i++) + { + /* There should be a buffer assigned to all in-flight + * TX descriptors. + */ + + nllvdbg("txtail: %p tdes0: %08x tdes2: %08x tdes3: %08x\n", + txdesc, txdesc->tdes0, txdesc->tdes2, txdesc->tdes3); + + DEBUGASSERT(txdesc->tdes2 != 0); + + /* Check if this is the first segment of a TX frame. */ + + if ((txdesc->tdes0 & ETH_TDES0_FS) != 0) + { + /* Yes.. Free the buffer */ + + lpc43_freebuffer(priv, (uint8_t*)txdesc->tdes2); + } + + /* In any event, make sure that TDES2 is nullified. */ + + txdesc->tdes2 = 0; + + /* Check if this is the last segment of a TX frame */ + + if ((txdesc->tdes0 & ETH_TDES0_LS) != 0) + { + /* Yes.. Decrement the number of frames "in-flight". */ + + priv->inflight--; + + /* If all of the TX descriptors were in-flight, then RX interrupts + * may have been disabled... we can re-enable them now. + */ + + lpc43_enableint(priv, ETH_DMAINT_RI); + + /* If there are no more frames in-flight, then bail. */ + + if (priv->inflight <= 0) + { + priv->txtail = NULL; + priv->inflight = 0; + return; + } + } + + /* Try the next descriptor in the TX chain */ + + txdesc = (struct eth_txdesc_s*)txdesc->tdes3; + } + + /* We get here if (1) there are still frames "in-flight". Remember + * where we left off. + */ + + priv->txtail = txdesc; + + nllvdbg("txhead: %p txtail: %p inflight: %d\n", + priv->txhead, priv->txtail, priv->inflight); + } +} + +/**************************************************************************** + * Function: lpc43_txdone + * + * Description: + * An interrupt was received indicating that the last TX packet(s) is done + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void lpc43_txdone(FAR struct lpc43_ethmac_s *priv) +{ + DEBUGASSERT(priv->txtail != NULL); + + /* Scan the TX descriptor change, returning buffers to free list */ + + lpc43_freeframe(priv); + + /* If no further xmits are pending, then cancel the TX timeout */ + + if (priv->inflight <= 0) + { + wd_cancel(priv->txtimeout); + + /* And disable further TX interrupts. */ + + lpc43_disableint(priv, ETH_DMAINT_TI); + } + + /* Then poll uIP for new XMIT data */ + + lpc43_dopoll(priv); +} + +/**************************************************************************** + * Function: lpc43_interrupt_process + * + * Description: + * Interrupt processing. This may be performed either within the interrupt + * handler or on the worker thread, depending upon the configuration + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +static inline void lpc43_interrupt_process(FAR struct lpc43_ethmac_s *priv) +{ + uint32_t dmasr; + + /* Get the DMA interrupt status bits (no MAC interrupts are expected) */ + + dmasr = lpc43_getreg(LPC43_ETH_DMASTAT); + + /* Mask only enabled interrupts. This depends on the fact that the interrupt + * related bits (0-16) correspond in these two registers. + */ + + dmasr &= lpc43_getreg(LPC43_ETH_DMAINTEN); + + /* Check if there are pending "normal" interrupts */ + + if ((dmasr & ETH_DMAINT_NIS) != 0) + { + /* Yes.. Check if we received an incoming packet, if so, call + * lpc43_receive() + */ + + if ((dmasr & ETH_DMAINT_RI) != 0) + { + /* Clear the pending receive interrupt */ + + lpc43_putreg(ETH_DMAINT_RI, LPC43_ETH_DMASTAT); + + /* Handle the received package */ + + lpc43_receive(priv); + } + + /* Check if a packet transmission just completed. If so, call + * lpc43_txdone(). This may disable further TX interrupts if there + * are no pending tansmissions. + */ + + if ((dmasr & ETH_DMAINT_TI) != 0) + { + /* Clear the pending receive interrupt */ + + lpc43_putreg(ETH_DMAINT_TI, LPC43_ETH_DMASTAT); + + /* Check if there are pending transmissions */ + + lpc43_txdone(priv); + } + + /* Clear the pending normal summary interrupt */ + + lpc43_putreg(ETH_DMAINT_NIS, LPC43_ETH_DMASTAT); + } + + /* Handle error interrupt only if CONFIG_DEBUG_NET is eanbled */ + +#ifdef CONFIG_DEBUG_NET + + /* Check if there are pending "abnormal" interrupts */ + + if ((dmasr & ETH_DMAINT_AIS) != 0) + { + /* Just let the user know what happened */ + + nlldbg("Abnormal event(s): %08x\n", dmasr); + + /* Clear all pending abnormal events */ + + lpc43_putreg(ETH_DMAINT_ABNORMAL, LPC43_ETH_DMASTAT); + + /* Clear the pending abnormal summary interrupt */ + + lpc43_putreg(ETH_DMAINT_AIS, LPC43_ETH_DMASTAT); + } +#endif +} + +/**************************************************************************** + * Function: lpc43_interrupt_work + * + * Description: + * Perform interrupt related work from the worker thread + * + * Parameters: + * arg - The argument passed when work_queue() was called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void lpc43_interrupt_work(FAR void *arg) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg; + net_lock_t state; + + DEBUGASSERT(priv); + + /* Process pending Ethernet interrupts */ + + state = net_lock(); + lpc43_interrupt_process(priv); + net_unlock(state); + + /* Re-enable Ethernet interrupts at the NVIC */ + + up_enable_irq(LPC43M4_IRQ_ETHERNET); +} +#endif + +/**************************************************************************** + * Function: lpc43_interrupt + * + * Description: + * Hardware interrupt handler + * + * 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 lpc43_interrupt(int irq, FAR void *context) +{ + FAR struct lpc43_ethmac_s *priv = &g_lpc43ethmac; + +#ifdef CONFIG_NET_NOINTS + uint32_t dmasr; + + /* Get the DMA interrupt status bits (no MAC interrupts are expected) */ + + dmasr = lpc43_getreg(LPC43_ETH_DMASTAT); + if (dmasr != 0) + { + /* 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(LPC43M4_IRQ_ETHERNET); + + /* Check if a packet transmission just completed. */ + + if ((dmasr & ETH_DMAINT_TI) != 0) + { + /* If a TX transfer just completed, then cancel the TX timeout so + * there will be no race condition between any subsequent timeout + * expiration and the deferred interrupt processing. + */ + + wd_cancel(priv->txtimeout); + } + + /* Cancel any pending poll work */ + + work_cancel(HPWORK, &priv->work); + + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(HPWORK, &priv->work, lpc43_interrupt_work, priv, 0); + } + +#else + /* Process the interrupt now */ + + lpc43_interrupt_process(priv); +#endif + + return OK; +} + +/**************************************************************************** + * Function: lpc43_txtimeout_process + * + * Description: + * Process a TX timeout. Called from the either the watchdog timer + * expiration logic or from the worker thread, depending upon the + * configuration. The timeout means that the last TX never completed. + * Reset the hardware and start again. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static inline void lpc43_txtimeout_process(FAR struct lpc43_ethmac_s *priv) +{ + /* Then reset the hardware. Just take the interface down, then back + * up again. + */ + + lpc43_ifdown(&priv->dev); + lpc43_ifup(&priv->dev); + + /* Then poll uIP for new XMIT data */ + + lpc43_dopoll(priv); +} + +/**************************************************************************** + * Function: lpc43_txtimeout_work + * + * Description: + * Perform TX timeout related work from the worker thread + * + * Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void lpc43_txtimeout_work(FAR void *arg) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg; + net_lock_t state; + + /* Process pending Ethernet interrupts */ + + state = net_lock(); + lpc43_txtimeout_process(priv); + net_unlock(state); +} +#endif + +/**************************************************************************** + * Function: lpc43_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. + * + * 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 lpc43_txtimeout_expiry(int argc, uint32_t arg, ...) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg; + + nlldbg("Timeout!\n"); + +#ifdef CONFIG_NET_NOINTS + /* 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. + * + * Interrupts will be re-enabled when lpc43_ifup() is called. + */ + + up_disable_irq(STM32_IRQ_ETH); + + /* Cancel any pending poll or interrupt work. This will have no effect + * on work that has already been started. + */ + + work_cancel(HPWORK, &priv->work); + + /* Schedule to perform the TX timeout processing on the worker thread. */ + + work_queue(HPWORK, &priv->work, lpc43_txtimeout_work, priv, 0); + +#else + /* Process the timeout now */ + + lpc43_txtimeout_process(priv); +#endif +} + +/**************************************************************************** + * Function: lpc43_poll_process + * + * Description: + * Perform the periodic poll. This may be called either from watchdog + * timer logic or from the worker thread, depending upon the configuration. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv) +{ + FAR struct net_driver_s *dev = &priv->dev; + + /* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We + * cannot perform the timer poll if we are unable to accept another packet + * for transmission. Hmmm.. might be bug here. Does this mean if there is + * a transmit in progress, we will miss TCP time state updates? + * + * In a race condition, ETH_TDES0_OWN may be cleared BUT still not available + * because lpc43_freeframe() has not yet run. If lpc43_freeframe() has run, + * the buffer1 pointer (tdes2) will be nullified (and inflight should be < + * CONFIG_LPC43_ETH_NTXDESC). + */ + + if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 && + priv->txhead->tdes2 == 0) + { + /* If we have the descriptor, then perform the timer poll. Allocate a + * buffer for the poll. + */ + + DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); + dev->d_buf = lpc43_allocbuffer(priv); + + /* We can't poll if we have no buffers */ + + if (dev->d_buf) + { + /* Update TCP timing states and poll for new XMIT data. + */ + + (void)devif_timer(dev, lpc43_txpoll, LPC43_POLLHSEC); + + /* We will, most likely end up with a buffer to be freed. But it + * might not be the same one that we allocated above. + */ + + if (dev->d_buf) + { + DEBUGASSERT(dev->d_len == 0); + lpc43_freebuffer(priv, dev->d_buf); + dev->d_buf = NULL; + } + } + } + + /* Setup the watchdog poll timer again */ + + (void)wd_start(priv->txpoll, LPC43_WDDELAY, lpc43_poll_expiry, 1, priv); +} + +/**************************************************************************** + * Function: lpc43_poll_work + * + * Description: + * Perform periodic polling from the worker thread + * + * Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Ethernet interrupts are disabled + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void lpc43_poll_work(FAR void *arg) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg; + net_lock_t state; + + /* Perform the poll */ + + state = net_lock(); + lpc43_poll_process(priv); + net_unlock(state); +} +#endif + +/**************************************************************************** + * Function: lpc43_poll_expiry + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * 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 lpc43_poll_expiry(int argc, uint32_t arg, ...) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg; + +#ifdef CONFIG_NET_NOINTS + /* Is our single work structure available? It may not be if there are + * pending interrupt actions. + */ + + if (work_available(&priv->work)) + { + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(HPWORK, &priv->work, lpc43_poll_work, priv, 0); + } + else + { + /* No.. Just re-start the watchdog poll timer, missing one polling + * cycle. + */ + + (void)wd_start(priv->txpoll, LPC43_WDDELAY, lpc43_poll_expiry, 1, + (uint32_t)priv); + } + +#else + /* Process the interrupt now */ + + lpc43_poll_process(priv); +#endif +} + +/**************************************************************************** + * Function: lpc43_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int lpc43_ifup(struct net_driver_s *dev) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)dev->d_private; + int ret; + +#ifdef CONFIG_NET_IPv4 + ndbg("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); +#endif +#ifdef CONFIG_NET_IPv6 + ndbg("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], + dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], + dev->d_ipv6addr[6], dev->d_ipv6addr[7]); +#endif + + /* Configure the Ethernet interface for DMA operation. */ + + ret = lpc43_ethconfig(priv); + if (ret < 0) + { + return ret; + } + + /* Set and activate a timer process */ + + (void)wd_start(priv->txpoll, LPC43_WDDELAY, lpc43_poll_expiry, 1, + (uint32_t)priv); + + /* Enable the Ethernet interrupt */ + + priv->ifup = true; + up_enable_irq(LPC43M4_IRQ_ETHERNET); + + lpc43_checksetup(); + return OK; +} + +/**************************************************************************** + * Function: lpc43_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int lpc43_ifdown(struct net_driver_s *dev) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)dev->d_private; + irqstate_t flags; + + ndbg("Taking the network down\n"); + + /* Disable the Ethernet interrupt */ + + flags = irqsave(); + up_disable_irq(LPC43M4_IRQ_ETHERNET); + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(priv->txpoll); + wd_cancel(priv->txtimeout); + + /* Put the EMAC in its reset, non-operational state. This should be + * a known configuration that will guarantee the lpc43_ifup() always + * successfully brings the interface back up. + */ + + lpc43_ethreset(priv); + + /* Mark the device "down" */ + + priv->ifup = false; + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Function: lpc43_txavail_process + * + * Description: + * Perform an out-of-cycle poll. + * + * Parameters: + * priv - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static inline void lpc43_txavail_process(FAR struct lpc43_ethmac_s *priv) +{ + nvdbg("ifup: %d\n", priv->ifup); + + /* Ignore the notification if the interface is not yet up */ + + if (priv->ifup) + { + /* Poll for new XMIT data */ + + lpc43_dopoll(priv); + } +} + +/**************************************************************************** + * Function: lpc43_txavail_work + * + * Description: + * Perform an out-of-cycle poll on the worker thread. + * + * Parameters: + * arg - Reference to the NuttX driver state structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * Called on the higher priority worker thread. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void lpc43_txavail_work(FAR void *arg) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg; + net_lock_t state; + + /* Perform the poll */ + + state = net_lock(); + lpc43_txavail_process(priv); + net_unlock(state); +} +#endif + +/**************************************************************************** + * Function: lpc43_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. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int lpc43_txavail(struct net_driver_s *dev) +{ + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)dev->d_private; + +#ifdef CONFIG_NET_NOINTS + /* 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->work)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &priv->work, lpc43_txavail_work, priv, 0); + } + +#else + irqstate_t flags; + + /* Disable interrupts because this function may be called from interrupt + * level processing. + */ + + flags = irqsave(); + + /* Perform the out-of-cycle poll now */ + + lpc43_txavail_process(priv); + irqrestore(flags); + #endif + + return OK; +} + +/**************************************************************************** + * Function: lpc43_calcethcrc + * + * Description: + * Function to calculate the CRC used by LPC43 to check an Ethernet frame + * + * Parameters: + * data - the data to be checked + * length - length of the data + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6) +static uint32_t lpc43_calcethcrc(const uint8_t *data, size_t length) +{ + uint32_t crc = 0xffffffff; + size_t i; + int j; + + for (i = 0; i < length; i++) + { + for (j = 0; j < 8; j++) + { + if (((crc >> 31) ^ (data[i] >> j)) & 0x01) + { + /* x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 */ + crc = (crc << 1) ^ 0x04c11db7; + } + else + { + crc = crc << 1; + } + } + } + + return ~crc; +} +#endif + +/**************************************************************************** + * Function: lpc43_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6) +static int lpc43_addmac(struct net_driver_s *dev, FAR const uint8_t *mac) +{ + uint32_t crc; + uint32_t hashindex; + uint32_t temp; + uint32_t registeraddress; + + nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + /* Add the MAC address to the hardware multicast hash table */ + + crc = lpc43_calcethcrc( mac, 6 ); + + hashindex = (crc >> 26) & 0x3F; + + if (hashindex > 31) + { + registeraddress = LPC43_ETH_MACHTHI; + hashindex -= 32; + } + else + { + registeraddress = LPC43_ETH_MACHTLO; + } + + temp = lpc43_getreg(registeraddress); + temp |= 1 << hashindex; + lpc43_putreg(temp, registeraddress); + + temp = lpc43_getreg(LPC43_ETH_MACFFLT); + temp |= (ETH_MACFFLT_HM | ETH_MACFFLT_HPF); + lpc43_putreg(temp, LPC43_ETH_MACFFLT); + + return OK; +} +#endif + +/**************************************************************************** + * Function: lpc43_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int lpc43_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac) +{ + uint32_t crc; + uint32_t hashindex; + uint32_t temp; + uint32_t registeraddress; + + nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + /* Remove the MAC address to the hardware multicast hash table */ + + crc = lpc43_calcethcrc( mac, 6 ); + + hashindex = (crc >> 26) & 0x3F; + + if (hashindex > 31) + { + registeraddress = LPC43_ETH_MACHTHI; + hashindex -= 32; + } + else + { + registeraddress = LPC43_ETH_MACHTLO; + } + + temp = lpc43_getreg(registeraddress); + temp &= ~(1 << hashindex); + lpc43_putreg(temp, registeraddress); + + /* If there is no address registered any more, delete multicast filtering */ + + if (lpc43_getreg(LPC43_ETH_MACHTHI ) == 0 && + lpc43_getreg(LPC43_ETH_MACHTLO) == 0) + { + temp = lpc43_getreg(LPC43_ETH_MACFFLT); + temp &= ~(ETH_MACFFLT_HM | ETH_MACFFLT_HPF); + lpc43_putreg(temp, LPC43_ETH_MACFFLT); + } + + return OK; +} +#endif + +/**************************************************************************** + * Function: lpc43_txdescinit + * + * Description: + * Initializes the DMA TX descriptors in chain mode. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void lpc43_txdescinit(FAR struct lpc43_ethmac_s *priv) +{ + struct eth_txdesc_s *txdesc; + int i; + + /* priv->txhead will point to the first, available TX descriptor in the chain. + * Set the priv->txhead pointer to the first descriptor in the table. + */ + + priv->txhead = priv->txtable; + + /* priv->txtail will point to the first segment of the oldest pending + * "in-flight" TX transfer. NULL means that there are no active TX + * transfers. + */ + + priv->txtail = NULL; + priv->inflight = 0; + + /* Initialize each TX descriptor */ + + for (i = 0; i < CONFIG_LPC43_ETH_NTXDESC; i++) + { + txdesc = &priv->txtable[i]; + + /* Set Second Address Chained bit */ + + txdesc->tdes0 = ETH_TDES0_TCH; + +#ifdef CHECKSUM_BY_HARDWARE + /* Enable the checksum insertion for the TX frames */ + + txdesc->tdes0 |= ETH_TDES0_CIC_ALL; +#endif + + /* Clear Buffer1 address pointer (buffers will be assigned as they + * are used) + */ + + txdesc->tdes2 = 0; + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + + if (i < (CONFIG_LPC43_ETH_NTXDESC-1)) + { + /* Set next descriptor address register with next descriptor base + * address + */ + + txdesc->tdes3 = (uint32_t)&priv->txtable[i+1]; + } + else + { + /* For last descriptor, set next descriptor address register equal + * to the first descriptor base address + */ + + txdesc->tdes3 = (uint32_t)priv->txtable; + } + } + + /* Set Transmit Desciptor List Address Register */ + + lpc43_putreg((uint32_t)priv->txtable, LPC43_ETH_DMATXDLA); +} + +/**************************************************************************** + * Function: lpc43_rxdescinit + * + * Description: + * Initializes the DMA RX descriptors in chain mode. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void lpc43_rxdescinit(FAR struct lpc43_ethmac_s *priv) +{ + struct eth_rxdesc_s *rxdesc; + int i; + + /* priv->rxhead will point to the first, RX descriptor in the chain. + * This will be where we receive the first incomplete frame. + */ + + priv->rxhead = priv->rxtable; + + /* If we accumulate the frame in segments, priv->rxcurr points to the + * RX descriptor of the first segment in the current TX frame. + */ + + priv->rxcurr = NULL; + priv->segments = 0; + + /* Initialize each TX descriptor */ + + for (i = 0; i < CONFIG_LPC43_ETH_NRXDESC; i++) + { + rxdesc = &priv->rxtable[i]; + + /* Set Own bit of the RX descriptor rdes0 */ + + rxdesc->rdes0 = ETH_RDES0_OWN; + + /* Set Buffer1 size and Second Address Chained bit and enabled DMA + * RX desc receive interrupt + */ + + rxdesc->rdes1 = ETH_RDES1_RCH | (uint32_t)CONFIG_LPC43_ETH_BUFSIZE; + + /* Set Buffer1 address pointer */ + + rxdesc->rdes2 = (uint32_t)&priv->rxbuffer[i*CONFIG_LPC43_ETH_BUFSIZE]; + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + + if (i < (CONFIG_LPC43_ETH_NRXDESC-1)) + { + /* Set next descriptor address register with next descriptor base + * address + */ + + rxdesc->rdes3 = (uint32_t)&priv->rxtable[i+1]; + } + else + { + /* For last descriptor, set next descriptor address register equal + * to the first descriptor base address + */ + + rxdesc->rdes3 = (uint32_t)priv->rxtable; + } + } + + /* Set Receive Descriptor List Address Register */ + + lpc43_putreg((uint32_t)priv->rxtable, LPC43_ETH_DMARXDLA); +} + +/**************************************************************************** + * Function: lpc43_ioctl + * + * Description: + * 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. + * + * 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_PHY_IOCTL +static int lpc43_ioctl(struct net_driver_s *dev, int cmd, long arg) +{ +#ifdef CONFIG_ARCH_PHY_INTERRUPT + FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)dev->d_private; +#endif + int ret; + + switch (cmd) + { +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ + { + struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); + + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = lpc43_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 = CONFIG_LPC43_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); + ret = lpc43_phyread(req->phy_id, req->reg_num, &req->val_out); + } + break; + + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = lpc43_phywrite(req->phy_id, req->reg_num, req->val_in); + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} +#endif /* CONFIG_NETDEV_PHY_IOCTL */ + +/**************************************************************************** + * Function: lpc43_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. + * + * 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 lpc43_phyintenable(struct lpc43_ethmac_s *priv) +{ +#warning Missing logic + return -ENOSYS; +} +#endif + +/**************************************************************************** + * Function: lpc43_phyread + * + * Description: + * Read a PHY register. + * + * Parameters: + * phydevaddr - The PHY device address + * phyregaddr - The PHY register address + * value - The location to return the 16-bit PHY register value. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int lpc43_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value) +{ + volatile uint32_t timeout; + uint32_t regval; + + /* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */ + + regval = lpc43_getreg(LPC43_ETH_MACMIIA); + regval &= ETH_MACMIIA_CR_MASK; + + /* Set the PHY device address, PHY register address, and set the buy bit. + * the ETH_MACMIIA_WR is clear, indicating a read operation. + */ + + regval |= (((uint32_t)phydevaddr << ETH_MACMIIA_PA_SHIFT) & ETH_MACMIIA_PA_MASK); + regval |= (((uint32_t)phyregaddr << ETH_MACMIIA_MR_SHIFT) & ETH_MACMIIA_MR_MASK); + regval |= ETH_MACMIIA_GB; + + lpc43_putreg(regval, LPC43_ETH_MACMIIA); + + /* Wait for the transfer to complete */ + + for (timeout = 0; timeout < PHY_READ_TIMEOUT; timeout++) + { + if ((lpc43_getreg(LPC43_ETH_MACMIIA) & ETH_MACMIIA_GB) == 0) + { + *value = (uint16_t)lpc43_getreg(LPC43_ETH_MACMIID); + return OK; + } + } + + ndbg("MII transfer timed out: phydevaddr: %04x phyregaddr: %04x\n", + phydevaddr, phyregaddr); + + return -ETIMEDOUT; +} + +/**************************************************************************** + * Function: lpc43_phywrite + * + * Description: + * Write to a PHY register. + * + * Parameters: + * phydevaddr - The PHY device address + * phyregaddr - The PHY register address + * value - The 16-bit value to write to the PHY register value. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int lpc43_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value) +{ + volatile uint32_t timeout; + uint32_t regval; + + /* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */ + + regval = lpc43_getreg(LPC43_ETH_MACMIIA); + regval &= ETH_MACMIIA_CR_MASK; + + /* Set the PHY device address, PHY register address, and set the busy bit. + * the ETH_MACMIIA_WR is set, indicating a write operation. + */ + + regval |= (((uint32_t)phydevaddr << ETH_MACMIIA_PA_SHIFT) & ETH_MACMIIA_PA_MASK); + regval |= (((uint32_t)phyregaddr << ETH_MACMIIA_MR_SHIFT) & ETH_MACMIIA_MR_MASK); + regval |= (ETH_MACMIIA_GB | ETH_MACMIIA_WR); + + /* Write the value into the MACIIDR register before setting the new MACMIIAR + * register value. + */ + + lpc43_putreg(value, LPC43_ETH_MACMIID); + lpc43_putreg(regval, LPC43_ETH_MACMIIA); + + /* Wait for the transfer to complete */ + + for (timeout = 0; timeout < PHY_WRITE_TIMEOUT; timeout++) + { + if ((lpc43_getreg(LPC43_ETH_MACMIIA) & ETH_MACMIIA_GB) == 0) + { + return OK; + } + } + + ndbg("MII transfer timed out: phydevaddr: %04x phyregaddr: %04x value: %04x\n", + phydevaddr, phyregaddr, value); + + return -ETIMEDOUT; +} + +/**************************************************************************** + * Function: lpc43_dm9161 + * + * Description: + * Special workaround for the Davicom DM9161 PHY is required. On power, + * up, the PHY is not usually configured correctly but will work after + * a powered-up reset. This is really a workaround for some more + * fundamental issue with the PHY clocking initialization, but the + * root cause has not been studied (nor will it be with this workaround). + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_ETH0_PHY_DM9161 +static inline int lpc43_dm9161(FAR struct lpc43_ethmac_s *priv) +{ + uint16_t phyval; + int ret; + + /* Read the PHYID1 register; A failure to read the PHY ID is one + * indication that check if the DM9161 PHY CHIP is not ready. + */ + + ret = lpc43_phyread(CONFIG_LPC43_PHYADDR, MII_PHYID1, &phyval); + if (ret < 0) + { + ndbg("Failed to read the PHY ID1: %d\n", ret); + return ret; + } + + /* If we failed to read the PHY ID1 register, the reset the MCU to recover */ + + else if (phyval == 0xffff) + { + up_systemreset(); + } + + nvdbg("PHY ID1: 0x%04X\n", phyval); + + /* Now check the "DAVICOM Specified Configuration Register (DSCR)", Register 16 */ + + ret = lpc43_phyread(CONFIG_LPC43_PHYADDR, 16, &phyval); + if (ret < 0) + { + ndbg("Failed to read the PHY Register 0x10: %d\n", ret); + return ret; + } + + /* Bit 8 of the DSCR register is zero, then the DM9161 has not selected RMII. + * If RMII is not selected, then reset the MCU to recover. + */ + + else if ((phyval & (1 << 8)) == 0) + { + up_systemreset(); + } + + return OK; +} +#endif + +/**************************************************************************** + * Function: lpc43_phyinit + * + * Description: + * Configure the PHY and determine the link speed/duplex. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int lpc43_phyinit(FAR struct lpc43_ethmac_s *priv) +{ + volatile uint32_t timeout; + uint32_t regval; + uint16_t phyval; + int ret; + + /* Assume 10MBps and half duplex */ + + priv->mbps100 = 0; + priv->fduplex = 0; + + /* Setup up PHY clocking by setting the SR field in the MACMIIAR register */ + + regval = lpc43_getreg(LPC43_ETH_MACMIIA); + regval &= ~ETH_MACMIIA_CR_MASK; + regval |= ETH_MACMIIA_CR; + lpc43_putreg(regval, LPC43_ETH_MACMIIA); + + /* Put the PHY in reset mode */ + + ret = lpc43_phywrite(CONFIG_LPC43_PHYADDR, MII_MCR, MII_MCR_RESET); + if (ret < 0) + { + ndbg("Failed to reset the PHY: %d\n", ret); + return ret; + } + + up_mdelay(PHY_RESET_DELAY); + +#ifdef CONFIG_LPC43_PHYINIT + /* Perform any necessary, board-specific PHY initialization */ + + ret = lpc43_phy_boardinitialize(0); + if (ret < 0) + { + ndbg("Failed to initialize the PHY: %d\n", ret); + return ret; + } +#endif + +#ifdef CONFIG_ETH0_PHY_DM9161 + /* Special workaround for the Davicom DM9161 PHY is required. */ + + ret = lpc43_dm9161(priv); + if (ret < 0) + { + return ret; + } +#endif + + /* Perform auto-negotion if so configured */ + +#ifdef CONFIG_LPC43_AUTONEG + /* Wait for link status */ + + for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++) + { + ret = lpc43_phyread(CONFIG_LPC43_PHYADDR, MII_MSR, &phyval); + if (ret < 0) + { + ndbg("Failed to read the PHY MSR: %d\n", ret); + return ret; + } + else if ((phyval & MII_MSR_LINKSTATUS) != 0) + { + break; + } + } + + if (timeout >= PHY_RETRY_TIMEOUT) + { + ndbg("Timed out waiting for link status: %04x\n", phyval); + return -ETIMEDOUT; + } + + /* Enable auto-negotiation */ + + ret = lpc43_phywrite(CONFIG_LPC43_PHYADDR, MII_MCR, MII_MCR_ANENABLE); + if (ret < 0) + { + ndbg("Failed to enable auto-negotiation: %d\n", ret); + return ret; + } + + /* Wait until auto-negotiation completes */ + + for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++) + { + ret = lpc43_phyread(CONFIG_LPC43_PHYADDR, MII_MSR, &phyval); + if (ret < 0) + { + ndbg("Failed to read the PHY MSR: %d\n", ret); + return ret; + } + else if ((phyval & MII_MSR_ANEGCOMPLETE) != 0) + { + break; + } + } + + if (timeout >= PHY_RETRY_TIMEOUT) + { + ndbg("Timed out waiting for auto-negotiation\n"); + return -ETIMEDOUT; + } + + /* Read the result of the auto-negotiation from the PHY-specific register */ + + ret = lpc43_phyread(CONFIG_LPC43_PHYADDR, CONFIG_LPC43_PHYSR, &phyval); + if (ret < 0) + { + ndbg("Failed to read PHY status register\n"); + return ret; + } + + /* Remember the selected speed and duplex modes */ + + nvdbg("PHYSR[%d]: %04x\n", CONFIG_LPC43_PHYSR, phyval); + + /* Different PHYs present speed and mode information in different ways. IF + * This CONFIG_LPC43_PHYSR_ALTCONFIG is selected, this indicates that the PHY + * represents speed and mode information are combined, for example, with + * separate bits for 10HD, 100HD, 10FD and 100FD. + */ + +#ifdef CONFIG_LPC43_PHYSR_ALTCONFIG + switch (phyval & CONFIG_LPC43_PHYSR_ALTMODE) + { + default: + case CONFIG_LPC43_PHYSR_10HD: + priv->fduplex = 0; + priv->mbps100 = 0; + break; + + case CONFIG_LPC43_PHYSR_100HD: + priv->fduplex = 0; + priv->mbps100 = 1; + break; + + case CONFIG_LPC43_PHYSR_10FD: + priv->fduplex = 1; + priv->mbps100 = 0; + break; + + case CONFIG_LPC43_PHYSR_100FD: + priv->fduplex = 1; + priv->mbps100 = 1; + break; + } + + /* Different PHYs present speed and mode information in different ways. Some + * will present separate information for speed and mode (this is the default). + * Those PHYs, for example, may provide a 10/100 Mbps indication and a separate + * full/half duplex indication. + */ + +#else + if ((phyval & CONFIG_LPC43_PHYSR_MODE) == CONFIG_LPC43_PHYSR_FULLDUPLEX) + { + priv->fduplex = 1; + } + + if ((phyval & CONFIG_LPC43_PHYSR_SPEED) == CONFIG_LPC43_PHYSR_100MBPS) + { + priv->mbps100 = 1; + } +#endif + +#else /* Auto-negotion not selected */ + + phyval = 0; +#ifdef CONFIG_LPC43_ETHFD + phyval |= MII_MCR_FULLDPLX; +#endif +#ifdef CONFIG_LPC43_ETH100MBPS + phyval |= MII_MCR_SPEED100; +#endif + + ret = lpc43_phywrite(CONFIG_LPC43_PHYADDR, MII_MCR, phyval); + if (ret < 0) + { + ndbg("Failed to write the PHY MCR: %d\n", ret); + return ret; + } + up_mdelay(PHY_CONFIG_DELAY); + + /* Remember the selected speed and duplex modes */ + +#ifdef CONFIG_LPC43_ETHFD + priv->fduplex = 1; +#endif +#ifdef CONFIG_LPC43_ETH100MBPS + priv->mbps100 = 1; +#endif +#endif + + ndbg("Duplex: %s Speed: %d MBps\n", + priv->fduplex ? "FULL" : "HALF", + priv->mbps100 ? 100 : 10); + + return OK; +} + +/************************************************************************************ + * Name: lpc43_selectmii + * + * Description: + * Selects the MII inteface. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +#ifdef CONFIG_LPC43_MII +static inline void lpc43_selectmii(void) +{ + uint32_t regval; + + regval = getreg32(LPC43_CREG6); + regval &= ~SYSCFG_PMC_MII_RMII_SEL; + putreg32(regval, LPC43_CREG6); +} +#endif + +/************************************************************************************ + * Name: lpc43_selectrmii + * + * Description: + * Selects the RMII inteface. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ************************************************************************************/ + +static inline void lpc43_selectrmii(void) +{ + uint32_t regval; + + regval = getreg32(LPC43_CREG6); + regval |= CREG6_ETHMODE_RMII; + putreg32(regval, LPC43_CREG6); +} + +/**************************************************************************** + * Function: lpc43_ethgpioconfig + * + * Description: + * Configure GPIOs for the Ethernet interface. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +static inline void lpc43_ethgpioconfig(FAR struct lpc43_ethmac_s *priv) +{ + /* Configure GPIO pins to support Ethernet */ + +#if defined(CONFIG_LPC43_MII) || defined(CONFIG_LPC43_RMII) + /* MDC and MDIO are common to both modes */ + + lpc43_pin_config(PINCONF_ENET_MDC); + lpc43_pin_config(PINCONF_ENET_MDIO); + + /* Set up the MII interface */ + +#if defined(CONFIG_LPC43_MII) + /* Select the MII interface */ + + lpc43_selectmii(); + + /* MII interface pins (17): + * + * MII_TX_CLK, MII_TXD[3:0], MII_TX_EN, MII_RX_CLK, MII_RXD[3:0], MII_RX_ER, + * MII_RX_DV, MII_CRS, MII_COL, MDC, MDIO + */ + + lpc43_pin_config(GPIO_ETH_MII_COL); + lpc43_pin_config(GPIO_ETH_MII_CRS); + lpc43_pin_config(GPIO_ETH_MII_RXD0); + lpc43_pin_config(GPIO_ETH_MII_RXD1); + lpc43_pin_config(GPIO_ETH_MII_RXD2); + lpc43_pin_config(GPIO_ETH_MII_RXD3); + lpc43_pin_config(GPIO_ETH_MII_RX_CLK); + lpc43_pin_config(GPIO_ETH_MII_RX_DV); + lpc43_pin_config(GPIO_ETH_MII_RX_ER); + lpc43_pin_config(GPIO_ETH_MII_TXD0); + lpc43_pin_config(GPIO_ETH_MII_TXD1); + lpc43_pin_config(GPIO_ETH_MII_TXD2); + lpc43_pin_config(GPIO_ETH_MII_TXD3); + lpc43_pin_config(GPIO_ETH_MII_TX_CLK); + lpc43_pin_config(GPIO_ETH_MII_TX_EN); + + /* Set up the RMII interface. */ + +#elif defined(CONFIG_LPC43_RMII) + /* Select the RMII interface */ + + lpc43_selectrmii(); + + /* RMII interface pins (7): + * + * RMII_TXD[1:0], RMII_TX_EN, RMII_RXD[1:0], RMII_CRS_DV, MDC, MDIO, + * RMII_REF_CLK + */ + + lpc43_pin_config(PINCONF_ENET_RX_DV); + lpc43_pin_config(PINCONF_ENET_REF_CLK); + lpc43_pin_config(PINCONF_ENET_RXD0); + lpc43_pin_config(PINCONF_ENET_RXD1); + lpc43_pin_config(PINCONF_ENET_TXD0); + lpc43_pin_config(PINCONF_ENET_TXD1); + lpc43_pin_config(PINCONF_ENET_TXEN); + +#endif +#endif +} + +/**************************************************************************** + * Function: lpc43_ethreset + * + * Description: + * Reset the Ethernet block. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +static void lpc43_ethreset(FAR struct lpc43_ethmac_s *priv) +{ + uint32_t regval; + + /* Reset the Ethernet */ + + lpc43_putreg(RGU_CTRL0_ETHERNET_RST, LPC43_RGU_CTRL0); + + /* Perform a software reset by setting the SR bit in the DMABMR register. + * This Resets all MAC subsystem internal registers and logic. After this + * reset all the registers holds their reset values. + */ + + regval = lpc43_getreg(LPC43_ETH_DMABMODE); + regval |= ETH_DMABMODE_SWR; + lpc43_putreg(regval, LPC43_ETH_DMABMODE); + + /* Wait for software reset to complete. The SR bit is cleared automatically + * after the reset operation has completed in all of the core clock domains. + */ + + while ((lpc43_getreg(LPC43_ETH_DMABMODE) & ETH_DMABMODE_SWR) != 0); +} + +/**************************************************************************** + * Function: lpc43_macconfig + * + * Description: + * Configure the Ethernet MAC for DMA operation. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int lpc43_macconfig(FAR struct lpc43_ethmac_s *priv) +{ + uint32_t regval; + + /* Set up the MACCR register */ + + regval = lpc43_getreg(LPC43_ETH_MACCR); + regval &= ~MACCR_CLEAR_BITS; + regval |= MACCR_SET_BITS; + + if (priv->fduplex) + { + /* Set the DM bit for full duplex support */ + + regval |= ETH_MACCFG_DM; + } + + if (priv->mbps100) + { + /* Set the FES bit for 100Mbps fast ethernet support */ + + regval |= ETH_MACCFG_FES; + } + + lpc43_putreg(regval, LPC43_ETH_MACCR); + + /* Set up the MACFFR register */ + + regval = lpc43_getreg(LPC43_ETH_MACFFLT); + regval &= ~MACFFR_CLEAR_BITS; + regval |= MACFFR_SET_BITS; + lpc43_putreg(regval, LPC43_ETH_MACFFLT); + + /* Set up the MACHTHR and MACHTLR registers */ + + lpc43_putreg(0, LPC43_ETH_MACHTHI); + lpc43_putreg(0, LPC43_ETH_MACHTLO); + + /* Setup up the MACFCR register */ + + regval = lpc43_getreg(LPC43_ETH_MACFC); + regval &= ~MACFCR_CLEAR_MASK; + regval |= MACFCR_SET_MASK; + lpc43_putreg(regval, LPC43_ETH_MACFC); + + /* Setup up the MACVLANTR register */ + + lpc43_putreg(0, LPC43_ETH_MACVLANT); + + /* DMA Configuration */ + /* Set up the DMAOMR register */ + + regval = lpc43_getreg(LPC43_ETH_DMAOPMODE); + regval &= ~DMAOMR_CLEAR_MASK; + regval |= DMAOMR_SET_MASK; + lpc43_putreg(regval, LPC43_ETH_DMAOPMODE); + + /* Set up the DMABMR register */ + + regval = lpc43_getreg(LPC43_ETH_DMABMODE); + regval &= ~DMABMR_CLEAR_MASK; + regval |= DMABMR_SET_MASK; + lpc43_putreg(regval, LPC43_ETH_DMABMODE); + + return OK; +} + +/**************************************************************************** + * Function: lpc43_macaddress + * + * Description: + * Configure the selected MAC address. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static void lpc43_macaddress(FAR struct lpc43_ethmac_s *priv) +{ + FAR struct net_driver_s *dev = &priv->dev; + uint32_t regval; + + nllvdbg("%s MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->d_ifname, + dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1], + dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3], + dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5]); + + /* Set the MAC address high register */ + + regval = ((uint32_t)dev->d_mac.ether_addr_octet[5] << 8) | + (uint32_t)dev->d_mac.ether_addr_octet[4]; + lpc43_putreg(regval, LPC43_ETH_MACA0HI); + + /* Set the MAC address low register */ + + regval = ((uint32_t)dev->d_mac.ether_addr_octet[3] << 24) | + ((uint32_t)dev->d_mac.ether_addr_octet[2] << 16) | + ((uint32_t)dev->d_mac.ether_addr_octet[1] << 8) | + (uint32_t)dev->d_mac.ether_addr_octet[0]; + lpc43_putreg(regval, LPC43_ETH_MACA0LO); +} + +/**************************************************************************** + * Function: lpc43_ipv6multicast + * + * Description: + * Configure the IPv6 multicast MAC address. + * + * 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 lpc43_ipv6multicast(FAR struct lpc43_ethmac_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; + + nvdbg("IPv6 Multicast: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + (void)lpc43_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)lpc43_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)lpc43_addmac(dev, g_ipv6_ethallrouters.ether_addr_octet); + +#endif /* CONFIG_NET_ICMPv6_ROUTER */ +} +#endif /* CONFIG_NET_ICMPv6 */ + +/**************************************************************************** + * Function: lpc43_macenable + * + * Description: + * Enable normal MAC operation. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int lpc43_macenable(FAR struct lpc43_ethmac_s *priv) +{ + uint32_t regval; + + /* Set the MAC address */ + + lpc43_macaddress(priv); + +#ifdef CONFIG_NET_ICMPv6 + /* Set up the IPv6 multicast address */ + + lpc43_ipv6multicast(priv); +#endif + + /* Enable transmit state machine of the MAC for transmission on the MII */ + + regval = lpc43_getreg(LPC43_ETH_MACCR); + regval |= ETH_MACCFG_TE; + lpc43_putreg(regval, LPC43_ETH_MACCR); + + /* Flush Transmit FIFO */ + + regval = lpc43_getreg(LPC43_ETH_DMAOPMODE); + regval |= ETH_DMAOPMODE_FTF; + lpc43_putreg(regval, LPC43_ETH_DMAOPMODE); + + /* Enable receive state machine of the MAC for reception from the MII */ + + /* Enables or disables the MAC reception. */ + + regval = lpc43_getreg(LPC43_ETH_MACCR); + regval |= ETH_MACCFG_RE; + lpc43_putreg(regval, LPC43_ETH_MACCR); + + /* Start DMA transmission */ + + regval = lpc43_getreg(LPC43_ETH_DMAOPMODE); + regval |= ETH_DMAOPMODE_ST; + lpc43_putreg(regval, LPC43_ETH_DMAOPMODE); + + /* Start DMA reception */ + + regval = lpc43_getreg(LPC43_ETH_DMAOPMODE); + regval |= ETH_DMAOPMODE_SR; + lpc43_putreg(regval, LPC43_ETH_DMAOPMODE); + + /* Enable Ethernet DMA interrupts. + * + * The LPC43 hardware supports two interrupts: (1) one dedicated to normal + * Ethernet operations and the other, used only for the Ethernet wakeup + * event. The wake-up interrupt is not used by this driver. + * + * The first Ethernet vector is reserved for interrupts generated by the + * MAC and the DMA. The MAC provides PMT and time stamp trigger interrupts, + * neither of which are used by this driver. + */ + + lpc43_putreg(ETH_MACIM_ALLINTS, LPC43_ETH_MACIM); + + /* Ethernet DMA supports two classes of interrupts: Normal interrupt + * summary (NIS) and Abnormal interrupt summary (AIS) with a variety + * individual normal and abnormal interrupting events. Here only + * the normal receive event is enabled (unless DEBUG is enabled). Transmit + * events will only be enabled when a transmit interrupt is expected. + */ + + lpc43_putreg((ETH_DMAINT_RECV_ENABLE | ETH_DMAINT_ERROR_ENABLE), + LPC43_ETH_DMAINTEN); + return OK; +} + +/**************************************************************************** + * Function: lpc43_ethconfig + * + * Description: + * Configure the Ethernet interface for DMA operation. + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static int lpc43_ethconfig(FAR struct lpc43_ethmac_s *priv) +{ + int ret; + + /* NOTE: The Ethernet clocks were initialized early in the boot-up + * sequence in lpc43_rcc.c. + */ + + /* Reset the Ethernet block */ + + nllvdbg("Reset the Ethernet block\n"); + lpc43_ethreset(priv); + + /* Initialize the PHY */ + + nllvdbg("Initialize the PHY\n"); + ret = lpc43_phyinit(priv); + if (ret < 0) + { + return ret; + } + + /* Initialize the MAC and DMA */ + + nllvdbg("Initialize the MAC and DMA\n"); + ret = lpc43_macconfig(priv); + if (ret < 0) + { + return ret; + } + + /* Initialize the free buffer list */ + + lpc43_initbuffer(priv); + + /* Initialize TX Descriptors list: Chain Mode */ + + lpc43_txdescinit(priv); + + /* Initialize RX Descriptors list: Chain Mode */ + + lpc43_rxdescinit(priv); + + /* Enable normal MAC operation */ + + nllvdbg("Enable normal operation\n"); + return lpc43_macenable(priv); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: lpc43_ethinitialize + * + * Description: + * Initialize the Ethernet driver for one interface. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +static inline int lpc43_ethinitialize(void) +{ + struct lpc43_ethmac_s *priv; + + /* Get the interface structure associated with this interface number. */ + + priv = &g_lpc43ethmac; + + /* Initialize the driver structure */ + + memset(priv, 0, sizeof(struct lpc43_ethmac_s)); + priv->dev.d_ifup = lpc43_ifup; /* I/F up (new IP address) callback */ + priv->dev.d_ifdown = lpc43_ifdown; /* I/F down callback */ + priv->dev.d_txavail = lpc43_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + priv->dev.d_addmac = lpc43_addmac; /* Add multicast MAC address */ + priv->dev.d_rmmac = lpc43_rmmac; /* Remove multicast MAC address */ +#endif +#ifdef CONFIG_NETDEV_PHY_IOCTL + priv->dev.d_ioctl = lpc43_ioctl; /* Support PHY ioctl() calls */ +#endif + priv->dev.d_private = (void*)&g_lpc43ethmac; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for and timing of transmisstions */ + + priv->txpoll = wd_create(); /* Create periodic poll timer */ + priv->txtimeout = wd_create(); /* Create TX timeout timer */ + + /* Configure GPIO pins to support Ethernet */ + + lpc43_ethgpioconfig(priv); + + /* Attach the IRQ to the driver */ + + if (irq_attach(LPC43M4_IRQ_ETHERNET, lpc43_interrupt)) + { + /* We could not attach the ISR to the interrupt */ + + return -EAGAIN; + } + + /* Put the interface in the down state. */ + + lpc43_ifdown(&priv->dev); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + (void)netdev_register(&priv->dev, NET_LL_ETHERNET); + return OK; +} + +/**************************************************************************** + * Function: up_netinitialize + * + * Description: + * This is the "standard" network initialization logic called from the + * low-level initialization logic in up_initialize.c. + * + * Parameters: + * None. + * + * Returned Value: + * None. + * + * Assumptions: + * + ****************************************************************************/ + +void up_netinitialize(void) +{ + (void)lpc43_ethinitialize(); +} + +#endif /* CONFIG_NET && CONFIG_LPC43_ETHERNET */ diff --git a/arch/arm/src/lpc43xx/lpc43_ethernet.h b/arch/arm/src/lpc43xx/lpc43_ethernet.h new file mode 100644 index 00000000000..55888fc7270 --- /dev/null +++ b/arch/arm/src/lpc43xx/lpc43_ethernet.h @@ -0,0 +1,93 @@ +/************************************************************************************ + * arch/arm/src/lpc43xx/lpc43_eth.h + * + * Copyright (C) 2009-2015 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_LPC43XX_LPC43_ETH_H +#define __ARCH_ARM_SRC_LPC43XX_LPC43_ETH_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +#include "chip/lpc43_ethernet.h" + +#ifndef __ASSEMBLY__ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Function: lpc43_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_LPC43_PHYINIT is defined in the configuration then the board specific + * logic must provide lpc43_phyinitialize(); The LPC43 Ethernet driver will call + * this function one time before it first uses the PHY. + * + * Parameters: + * intf - Always zero for now. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ************************************************************************************/ + +#ifdef CONFIG_LPC43_PHYINIT +int lpc43_phy_boardinitialize(int intf); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LPC43XX_LPC43_ETH_H */ diff --git a/arch/arm/src/lpc43xx/lpc43_irq.c b/arch/arm/src/lpc43xx/lpc43_irq.c index e9e57e5ef63..ee82f24fb3a 100644 --- a/arch/arm/src/lpc43xx/lpc43_irq.c +++ b/arch/arm/src/lpc43xx/lpc43_irq.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/lpc43/lpc43_irq.c * - * Copyright (C) 2012-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -77,11 +77,17 @@ * Public Data ****************************************************************************/ +/* This is the address of current interrupt saved state data. Used for + * context switching. Only value during interrupt handling. + */ + volatile uint32_t *current_regs; -/* This is the address of the vector table */ +/* This is the address of the exception vector table (determined by the + * linker script). + */ -extern unsigned _vectors[]; +extern uint32_t _vectors[]; /**************************************************************************** * Private Data @@ -316,15 +322,16 @@ void up_irqinitialize(void) * positioned in SRAM or in external FLASH, then we may need to reset * the interrupt vector so that it refers to the table in SRAM or in * external FLASH. - * - * If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ -#ifdef CONFIG_ARCH_RAMVECTORS up_ramvec_initialize(); -#else - putreg32((uint32_t)_vectors, NVIC_VECTAB); #endif /* Set all interrupts (and exceptions) to the default priority */ diff --git a/arch/arm/src/lpc43xx/lpc43_spi.c b/arch/arm/src/lpc43xx/lpc43_spi.c index 39b9d59d170..c613bd14352 100644 --- a/arch/arm/src/lpc43xx/lpc43_spi.c +++ b/arch/arm/src/lpc43xx/lpc43_spi.c @@ -54,8 +54,7 @@ #include "up_arch.h" #include "chip.h" -#include "lpc43_syscon.h" -#include "lpc43_pinconn.h" +#include "lpc43_pinconfig.h" #include "lpc43_spi.h" #ifdef CONFIG_LPC43_SPI @@ -93,7 +92,6 @@ * use the CCLK undivided to get the SPI_CLOCK. */ -#define SPI_PCLKSET_DIV SYSCON_PCLKSEL_CCLK #define SPI_CLOCK LPC43_CCLK /**************************************************************************** @@ -545,36 +543,19 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nw FAR struct spi_dev_s *lpc43_spiinitialize(int port) { FAR struct lpc43_spidev_s *priv = &g_spidev; - irqstate_t flags; - uint32_t regval; /* Configure multiplexed pins as connected on the board. Chip select * pins must be configured by board-specific logic. All SPI pins and - * one SPI1 pin (SCK) have multiple, alternative pin selection. + * one SPI1 pin (SCK) have multiple, alternative pin selections. * Definitions in the board.h file must be provided to resolve the * board-specific pin configuration like: * - * #define GPIO_SPI_SCK GPIO_SPI_SCK_1 + * #define PINCONF_SPI_SCK PINCONF_SPI_SCK_1 */ - flags = irqsave(); - lpc43_configgpio(GPIO_SPI_SCK); - lpc43_configgpio(GPIO_SPI_MISO); - lpc43_configgpio(GPIO_SPI_MOSI); - - /* Configure clocking */ - - regval = getreg32(LPC43_SYSCON_PCLKSEL0); - regval &= ~SYSCON_PCLKSEL0_SPI_MASK; - regval |= (SPI_PCLKSET_DIV << SYSCON_PCLKSEL0_SPI_SHIFT); - putreg32(regval, LPC43_SYSCON_PCLKSEL0); - - /* Enable peripheral clocking to SPI and SPI1 */ - - regval = getreg32(LPC43_SYSCON_PCONP); - regval |= SYSCON_PCONP_PCSPI; - putreg32(regval, LPC43_SYSCON_PCONP); - irqrestore(flags); + lpc43_pin_config(PINCONF_SPI_SCK); + lpc43_pin_config(PINCONF_SPI_MISO); + lpc43_pin_config(PINCONF_SPI_MOSI); /* Configure 8-bit SPI mode and master mode */ diff --git a/arch/arm/src/lpc43xx/lpc43_spifi.c b/arch/arm/src/lpc43xx/lpc43_spifi.c index 237dc1ac257..610c41f582e 100644 --- a/arch/arm/src/lpc43xx/lpc43_spifi.c +++ b/arch/arm/src/lpc43xx/lpc43_spifi.c @@ -1093,7 +1093,7 @@ static inline int lpc43_rominit(FAR struct lpc43_dev_s *priv) fvdbg(" blksize: %08x\n", priv->blksize); fvdbg(" nblocks: %d\n", priv->nblocks); -#if CONFIG_SPIFI_SECTOR512 +#ifdef CONFIG_SPIFI_SECTOR512 DEBUGASSERT(log2 > 9); #endif diff --git a/arch/arm/src/lpc43xx/lpc43_start.c b/arch/arm/src/lpc43xx/lpc43_start.c index bc51e226b09..092271e1850 100644 --- a/arch/arm/src/lpc43xx/lpc43_start.c +++ b/arch/arm/src/lpc43xx/lpc43_start.c @@ -63,6 +63,7 @@ #include #include +#include #include "up_arch.h" #include "up_internal.h" diff --git a/arch/arm/src/lpc43xx/lpc43_uart.c b/arch/arm/src/lpc43xx/lpc43_uart.c index 50579b6b3f2..4eefe8470ba 100644 --- a/arch/arm/src/lpc43xx/lpc43_uart.c +++ b/arch/arm/src/lpc43xx/lpc43_uart.c @@ -192,23 +192,18 @@ void up_lowputc(char ch) * as possible. * * The USART0/2/3 and UART1 peripherals are configured using the following registers: - * 1. Power: In the PCONP register, set bits PCUSART0/1/2/3. - * On reset, USART0 and UART 1 are enabled (PCUSART0 = 1 and PCUART1 = 1) - * and USART2/3 are disabled (PCUART1 = 0 and PCUSART3 = 0). - * 2. Peripheral clock: In the PCLKSEL0 register, select PCLK_USART0 and - * PCLK_UART1; in the PCLKSEL1 register, select PCLK_USART2 and PCLK_USART3. - * 3. Baud rate: In the LCR register, set bit DLAB = 1. This enables access + * 1. Baud rate: In the LCR register, set bit DLAB = 1. This enables access * to registers DLL and DLM for setting the baud rate. Also, if needed, * set the fractional baud rate in the fractional divider - * 4. UART FIFO: Use bit FIFO enable (bit 0) in FCR register to + * 2. UART FIFO: Use bit FIFO enable (bit 0) in FCR register to * enable FIFO. - * 5. Pins: Select UART pins through the PINSEL registers and pin modes + * 3. Pins: Select UART pins through the PINSEL registers and pin modes * through the PINMODE registers. UART receive pins should not have * pull-down resistors enabled. - * 6. Interrupts: To enable UART interrupts set bit DLAB = 0 in the LCRF + * 4. Interrupts: To enable UART interrupts set bit DLAB = 0 in the LCRF * register. This enables access to IER. Interrupts are enabled * in the NVIC using the appropriate Interrupt Set Enable register. - * 7. DMA: UART transmit and receive functions can operate with the + * 5. DMA: UART transmit and receive functions can operate with the * GPDMA controller. * **************************************************************************/ diff --git a/arch/arm/src/moxart/Kconfig b/arch/arm/src/moxart/Kconfig index 3c8166499ff..d7487ee8a02 100644 --- a/arch/arm/src/moxart/Kconfig +++ b/arch/arm/src/moxart/Kconfig @@ -7,3 +7,12 @@ comment "MoxART Configuration Options" config UART_MOXA_MODE_REG hex "16550 UART mode register address" + default 0x982000E0 + +config UART_MOXA_IRQ_STATUS_REG + hex "16550 UART shared IRQ status register address" + default 0x982000C0 + +config UART_MOXA_SHARED_IRQ + int "16550 UART shared IRQ number" + default 31 diff --git a/arch/arm/src/moxart/moxart_16550.c b/arch/arm/src/moxart/moxart_16550.c index a1dbed0bb30..8152c28a800 100644 --- a/arch/arm/src/moxart/moxart_16550.c +++ b/arch/arm/src/moxart/moxart_16550.c @@ -67,6 +67,30 @@ void uart_putreg(uart_addrwidth_t base, unsigned int offset, uart_datawidth_t va *((volatile uart_addrwidth_t *)base + offset) = value; } +void uart_decodeirq(int irq, FAR void *context) +{ + int i; + uint32_t status; + static int os = 0; + + status = *((volatile uart_addrwidth_t *)CONFIG_UART_MOXA_IRQ_STATUS_REG); + + if ((status & 0x3f) == 0x3f) + { + return; + } + + i = 0; + do + { + if (!(status & 0x1)) { + irq_dispatch(VIRQ_START + i, context); + } + status >>= 1; + } + while (++i <= 4); +} + #ifdef CONFIG_SERIAL_UART_ARCH_IOCTL int uart_ioctl(struct file *filep, int cmd, unsigned long arg) { @@ -109,9 +133,12 @@ int uart_ioctl(struct file *filep, int cmd, unsigned long arg) /* Update mode register with requested mode */ vmode = getreg32(CONFIG_UART_MOXA_MODE_REG); - putreg32(CONFIG_UART_MOXA_MODE_REG, (vmode & ~(OP_MODE_MASK << 2 * bitm_off)) | ((opmode << 2 * bitm_off) & 0xffff)); + putreg32(vmode & ~(OP_MODE_MASK << 2 * bitm_off), CONFIG_UART_MOXA_MODE_REG); + vmode = opmode << 2 * bitm_off; + putreg32(getreg32(CONFIG_UART_MOXA_MODE_REG) | vmode, CONFIG_UART_MOXA_MODE_REG); irqrestore(flags); + ret = OK; break; } @@ -126,6 +153,7 @@ int uart_ioctl(struct file *filep, int cmd, unsigned long arg) irqrestore(flags); *(unsigned long *)arg = opmode; + ret = OK; break; } } diff --git a/arch/arm/src/moxart/moxart_irq.c b/arch/arm/src/moxart/moxart_irq.c index a29f5b2c4a8..4e8747b45c0 100644 --- a/arch/arm/src/moxart/moxart_irq.c +++ b/arch/arm/src/moxart/moxart_irq.c @@ -81,6 +81,8 @@ volatile uint32_t *current_regs; * Public Functions ****************************************************************************/ +extern void uart_decodeirq(int irq, uint32_t *regs); + /**************************************************************************** * Name: up_irqinitialize * @@ -93,6 +95,10 @@ void up_irqinitialize(void) { /* Prepare hardware */ + *(volatile int *)0x98700000 |= 0x3f; + + /* PMU setup */ + (*(volatile uint32_t *)0x98100008) &= ~0x9; while (!((*(volatile uint32_t *)0x98100008) & 0x2)) { ; } @@ -101,6 +107,8 @@ void up_irqinitialize(void) (*(volatile uint32_t *)0x98800100) = 0xDFF8003F; + /* Check board type */ + /* Mask all interrupts off */ putreg32(0, IRQ_REG(IRQ__MASK)); @@ -119,6 +127,11 @@ void up_irqinitialize(void) current_regs = NULL; + /* Setup UART shared interrupt */ + + irq_attach(CONFIG_UART_MOXA_SHARED_IRQ, uart_decodeirq); + up_enable_irq(CONFIG_UART_MOXA_SHARED_IRQ); + /* And finally, enable interrupts */ #if 1 diff --git a/arch/arm/src/moxart/moxart_timer.c b/arch/arm/src/moxart/moxart_timer.c index b085e631151..e2c115bee8a 100644 --- a/arch/arm/src/moxart/moxart_timer.c +++ b/arch/arm/src/moxart/moxart_timer.c @@ -132,9 +132,6 @@ void up_timer_initialize(void) uint32_t tmp; // up_disable_irq(IRQ_SYSTIMER); - - *(volatile int *)0x98700000 = 0x3f; - putreg32(0, TM1_ADDR + CNTL_TIMER); putreg32(0, TM1_ADDR + INTR_STATE_TIMER); putreg32(0x1ff, TM1_ADDR + INTR_MASK_TIMER); diff --git a/arch/arm/src/nuc1xx/chip/nuc_gcr.h b/arch/arm/src/nuc1xx/chip/nuc_gcr.h index c9ad2df98ad..065c3defbb2 100644 --- a/arch/arm/src/nuc1xx/chip/nuc_gcr.h +++ b/arch/arm/src/nuc1xx/chip/nuc_gcr.h @@ -356,7 +356,7 @@ # define GCR_REGWRPROT_2 (0x16) # define GCR_REGWRPROT_3 (0x88) /* Read: */ -#define GCR_REGWRPROT_DIS (1 << 0) /* Bit 0: Register write protectino disable index */ +#define GCR_REGWRPROT_DIS (1 << 0) /* Bit 0: Register write protection disable index */ /******************************************************************************************** * Public Types diff --git a/arch/arm/src/sam34/Make.defs b/arch/arm/src/sam34/Make.defs index 2e8a03d93aa..551a5cdd682 100644 --- a/arch/arm/src/sam34/Make.defs +++ b/arch/arm/src/sam34/Make.defs @@ -91,6 +91,8 @@ ifeq ($(CONFIG_ARCH_FPU),y) CMN_ASRCS += up_fpu.S ifneq ($(CONFIG_ARMV7M_CMNVECTOR),y) CMN_CSRCS += up_copyarmstate.c +else ifeq ($(CONFIG_ARMV7M_LAZYFPU),y) +CMN_CSRCS += up_copyarmstate.c endif endif diff --git a/arch/arm/src/sam34/sam4l_clockconfig.c b/arch/arm/src/sam34/sam4l_clockconfig.c index c02368dc86e..df325632a3d 100644 --- a/arch/arm/src/sam34/sam4l_clockconfig.c +++ b/arch/arm/src/sam34/sam4l_clockconfig.c @@ -1293,7 +1293,7 @@ void sam_clockconfig(void) * OSC32: Might be source clock for DFLL0 */ -#if NEED_OSC0 +#ifdef NEED_OSC0 /* Enable OSC0 using the settings in board.h */ sam_enableosc0(); diff --git a/arch/arm/src/sam34/sam_dmac.c b/arch/arm/src/sam34/sam_dmac.c index 63b46ada61d..d9f31eb52db 100644 --- a/arch/arm/src/sam34/sam_dmac.c +++ b/arch/arm/src/sam34/sam_dmac.c @@ -1225,7 +1225,7 @@ static inline int sam_multiple(struct sam_dma_s *dmach) * Additionally, the CTRLA DONE bit is asserted when the buffer transfer has completed. * * The DMAC transfer continues until the CTRLB register disables the descriptor - * (DSCR bits) registers at the final buffer tranfer. + * (DSCR bits) registers at the final buffer transfer. * * Enable error, buffer complete and transfer complete interrupts. We * don't really need the buffer complete interrupts, but we will take them diff --git a/arch/arm/src/sam34/sam_hsmci.c b/arch/arm/src/sam34/sam_hsmci.c index c2ab81d1bdd..ba1aa09d9b9 100644 --- a/arch/arm/src/sam34/sam_hsmci.c +++ b/arch/arm/src/sam34/sam_hsmci.c @@ -80,7 +80,7 @@ # include "chip/sam_pdc.h" #endif -#if CONFIG_SAM34_HSMCI +#ifdef CONFIG_SAM34_HSMCI /**************************************************************************** * Pre-processor Definitions diff --git a/arch/arm/src/sam34/sam_irq.c b/arch/arm/src/sam34/sam_irq.c index 80f7b5af785..0c33e75f13b 100644 --- a/arch/arm/src/sam34/sam_irq.c +++ b/arch/arm/src/sam34/sam_irq.c @@ -78,7 +78,16 @@ * Public Data ****************************************************************************/ +/* This is the address of current interrupt saved state data. Used for + * context switching. Only value during interrupt handling. + */ + volatile uint32_t *current_regs; + +/* This is the address of the exception vector table (determined by the + * linker script). + */ + extern uint32_t _vectors[]; /**************************************************************************** @@ -378,16 +387,21 @@ void up_irqinitialize(void) } #endif - /* Set up the vector table address. - * - * If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ -#if defined(CONFIG_ARCH_RAMVECTORS) up_ramvec_initialize(); -#elif defined(CONFIG_SAM_BOOTLOADER) - putreg32((uint32_t)_vectors, NVIC_VECTAB); #endif /* Set all interrupts (and exceptions) to the default priority */ diff --git a/arch/arm/src/sam34/sam_rtc.c b/arch/arm/src/sam34/sam_rtc.c index c92672aa97e..614bcb5fc1a 100644 --- a/arch/arm/src/sam34/sam_rtc.c +++ b/arch/arm/src/sam34/sam_rtc.c @@ -254,7 +254,7 @@ static int rtc_bcd2bin(uint32_t value) * ************************************************************************************/ -#if CONFIG_RTC_ALARM +#ifdef CONFIG_RTC_ALARM static void rtc_worker(FAR void *arg) { /* Sample once (atomically) */ @@ -287,7 +287,7 @@ static void rtc_worker(FAR void *arg) * ************************************************************************************/ -#if CONFIG_RTC_ALARM +#ifdef CONFIG_RTC_ALARM static int rtc_interrupt(int irq, void *context) { int ret; @@ -414,7 +414,7 @@ int up_rtcinitialize(void) #endif -#if defined(CONFIG_RTC_HIRES) && defined (CONFIG_SAM34_RTT) +#if defined(CONFIG_RTC_HIRES) && defined(CONFIG_SAM34_RTT) /* Using the RTT for subsecond ticks. */ sam_rtt_enableclk(); diff --git a/arch/arm/src/sam34/sam_timerisr.c b/arch/arm/src/sam34/sam_timerisr.c index 5d23640bbdd..a1ebf3421d6 100644 --- a/arch/arm/src/sam34/sam_timerisr.c +++ b/arch/arm/src/sam34/sam_timerisr.c @@ -85,7 +85,7 @@ #undef CONFIG_SAM34_SYSTICK_HCLKd8 /* Power up default is MCK, not MCK/8 */ -#if CONFIG_SAM34_SYSTICK_HCLKd8 +#ifdef CONFIG_SAM34_SYSTICK_HCLKd8 # define SYSTICK_RELOAD ((SAM_SYSTICK_CLOCK / 8 / CLK_TCK) - 1) #else # define SYSTICK_RELOAD ((SAM_SYSTICK_CLOCK / CLK_TCK) - 1) @@ -152,7 +152,7 @@ void up_timer_initialize(void) #if 0 /* Does not work. Comes up with HCLK source and I can't change it */ regval = getreg32(NVIC_SYSTICK_CTRL); -#if CONFIG_SAM34_SYSTICK_HCLKd8 +#ifdef CONFIG_SAM34_SYSTICK_HCLKd8 regval &= ~NVIC_SYSTICK_CTRL_CLKSOURCE; #else regval |= NVIC_SYSTICK_CTRL_CLKSOURCE; diff --git a/arch/arm/src/sam34/sam_udp.c b/arch/arm/src/sam34/sam_udp.c index b933a310d5a..a79c7502740 100644 --- a/arch/arm/src/sam34/sam_udp.c +++ b/arch/arm/src/sam34/sam_udp.c @@ -500,7 +500,7 @@ static const struct usb_epdesc_s g_ep0desc = .interval = 0 }; -/* Device error strings that may be enabled for more desciptive USB trace +/* Device error strings that may be enabled for more descriptive USB trace * output. */ @@ -540,7 +540,7 @@ const struct trace_msg_t g_usb_trace_strings_deverror[] = }; #endif -/* Interrupt event strings that may be enabled for more desciptive USB trace +/* Interrupt event strings that may be enabled for more descriptive USB trace * output. */ diff --git a/arch/arm/src/sama5/Kconfig b/arch/arm/src/sama5/Kconfig index d0074d0b120..6a5d3d88651 100644 --- a/arch/arm/src/sama5/Kconfig +++ b/arch/arm/src/sama5/Kconfig @@ -73,6 +73,10 @@ config SAMA5_HAVE_HSMCI2 bool default n +config SAMA5_HAVE_PIOE + bool + default n + config SAMA5_HAVE_SAIC bool default n @@ -115,10 +119,30 @@ config SAMA5_HAVE_VDEC # Chip Selection +config ARCH_CHIP_SAMA5D2 + bool + default n + select SAMA5_HAVE_AESB + select ARCH_NAND_HWECC + select SAMA5_HAVE_EMACB + select SAMA5_HAVE_ICM + select SAMA5_HAVE_LCDC + select SAMA5_HAVE_UART0 + select SAMA5_HAVE_UART1 + select SAMA5_HAVE_USART4 + select SAMA5_HAVE_QSPI + select SAMA5_HAVE_XDMA + select SAMA5_HAVE_SAIC + select SAMA5_HAVE_SFC + select SAMA5_HAVE_SPI2 + select SAMA5_HAVE_TC1 + select SAMA5_HAVE_TRUSTZONE + config ARCH_CHIP_SAMA5D3 bool default n select SAMA5_HAVE_DMA + select SAMA5_HAVE_PIOE config ARCH_CHIP_SAMA5D4 bool @@ -134,6 +158,7 @@ config ARCH_CHIP_SAMA5D4 select SAMA5_HAVE_UART1 select SAMA5_HAVE_USART4 select SAMA5_HAVE_XDMA + select SAMA5_HAVE_PIOE select SAMA5_HAVE_SAIC select SAMA5_HAVE_SBM select SAMA5_HAVE_SFC @@ -147,6 +172,44 @@ choice prompt "Atmel AT91SAMA5 Chip Selection" default ARCH_CHIP_ATSAMA5D33 +config ARCH_CHIP_ATSAMA5D21 + bool "Atmel ATSAMA5D21" + select ARCH_CHIP_SAMA5D2 + +config ARCH_CHIP_ATSAMA5D22 + bool "Atmel ATSAMA5D22" + select ARCH_CHIP_SAMA5D2 + select SAMA5_HAVE_CAN0 + +config ARCH_CHIP_ATSAMA5D23 + bool "Atmel ATSAMA5D23" + select ARCH_CHIP_SAMA5D2 + select SAMA5_HAVE_CAN0 + +config ARCH_CHIP_ATSAMA5D24 + bool "Atmel ATSAMA5D24" + select ARCH_CHIP_SAMA5D2 + select SAMA5_HAVE_DDR32 + +config ARCH_CHIP_ATSAMA5D26 + bool "Atmel ATSAMA5D26" + select ARCH_CHIP_SAMA5D2 + select SAMA5_HAVE_DDR32 + +config ARCH_CHIP_ATSAMA5D27 + bool "Atmel ATSAMA5D27" + select ARCH_CHIP_SAMA5D2 + select SAMA5_HAVE_CAN0 + select SAMA5_HAVE_CAN1 + select SAMA5_HAVE_DDR32 + +config ARCH_CHIP_ATSAMA5D28 + bool "Atmel ATSAMA5D28" + select ARCH_CHIP_SAMA5D2 + select SAMA5_HAVE_CAN0 + select SAMA5_HAVE_CAN1 + select SAMA5_HAVE_DDR32 + config ARCH_CHIP_ATSAMA5D31 bool "Atmel ATSAMA5D31" select ARCH_CHIP_SAMA5D3 @@ -572,6 +635,7 @@ config SAMA5_PIOD_IRQ config SAMA5_PIOE_IRQ bool "PIOE interrupts" default n + depends on SAMA5_HAVE_PIOE endif # PIO_IRQ diff --git a/arch/arm/src/sama5/chip/sam_memorymap.h b/arch/arm/src/sama5/chip/sam_memorymap.h index 9f31c154745..1ab773ba2ba 100644 --- a/arch/arm/src/sama5/chip/sam_memorymap.h +++ b/arch/arm/src/sama5/chip/sam_memorymap.h @@ -1,7 +1,7 @@ /************************************************************************************ * arch/arm/src/sama5/chip/sam_memorymap.h * - * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -43,7 +43,9 @@ #include #include -#if defined(ATSAMA5D3) +#if defined(ATSAMA5D2) +# include "chip/sama5d2x_memorymap.h" +#elif defined(ATSAMA5D3) # include "chip/sama5d3x_memorymap.h" #elif defined(ATSAMA5D4) # include "chip/sama5d4x_memorymap.h" diff --git a/arch/arm/src/sama5/sam_adc.c b/arch/arm/src/sama5/sam_adc.c index 1c739d1030d..261434229e6 100644 --- a/arch/arm/src/sama5/sam_adc.c +++ b/arch/arm/src/sama5/sam_adc.c @@ -1577,10 +1577,10 @@ static void sam_adc_offset(struct sam_adc_s *priv) * used for all channel. */ -#if CONFIG_SAMA5_ADC_OFFSET +#ifdef CONFIG_SAMA5_ADC_OFFSET regval |= ADC_COR_OFF0; #endif -#if CONFIG_SAMA5_ADC_DIFFMODE +#ifdef CONFIG_SAMA5_ADC_DIFFMODE regval |= ADC_COR_DIFF0; #endif #endif diff --git a/arch/arm/src/sama5/sam_can.c b/arch/arm/src/sama5/sam_can.c index aa4a3255de7..b201d88a559 100644 --- a/arch/arm/src/sama5/sam_can.c +++ b/arch/arm/src/sama5/sam_can.c @@ -733,7 +733,10 @@ static int can_recvsetup(FAR struct sam_can_s *priv) canvdbg("CAN%d Mailbox %d: Index=%d rxmbset=%02x\n", config->port, mbno, mbndx, priv->rxmbset); - /* Set up the message ID and filter mask */ + /* Set up the message ID and filter mask + * REVISIT: This logic should be capable of setting up standard + * filters when CONFIG_CAN_EXTID is selected. + */ #ifdef CONFIG_CAN_EXTID can_putreg(priv, SAM_CAN_MnID_OFFSET(mbndx), @@ -1125,14 +1128,16 @@ static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg) canvdbg("Mailbox Index=%d txmbset=%02x\n", mbndx, priv->txmbset); - /* Set up the ID and mask, standard 11-bit or extended 29-bit. */ + /* Set up the ID and mask, standard 11-bit or extended 29-bit. + * REVISIT: This logic should be capable of sending standard messages + * when CONFIG_CAN_EXTID is selected. + */ #ifdef CONFIG_CAN_EXTID DEBUGASSERT(msg->cm_hdr.ch_extid); DEBUGASSERT(msg->cm_hdr.ch_id < (1 << 29)); can_putreg(priv, SAM_CAN_MnID_OFFSET(mbndx), CAN_MID_EXTID(msg->cm_hdr.ch_id)); #else - DEBUGASSERT(!msg->cm_hdr.ch_extid); DEBUGASSERT(msg->cm_hdr.ch_id < (1 << 11)); can_putreg(priv, SAM_CAN_MnID_OFFSET(mbndx), CAN_MID_STDID(msg->cm_hdr.ch_id)); #endif @@ -1309,24 +1314,27 @@ static inline void can_rxinterrupt(FAR struct can_dev_s *dev, int mbndx, mid = can_getreg(priv, SAM_CAN_MnID_OFFSET(mbndx)); - /* Format the CAN header */ + /* Format the CAN header. + * REVISIT: This logic should be capable of receiving standard messages + * when CONFIG_CAN_EXTID is selected. + */ #ifdef CONFIG_CAN_EXTID /* Save the extended ID of the newly received message */ hdr.ch_id = (mid & CAN_MAM_EXTID_MASK) >> CAN_MAM_EXTID_SHIFT; - hdr.ch_dlc = (msr & CAN_MSR_MDLC_MASK) >> CAN_MSR_MDLC_SHIFT; - hdr.ch_rtr = 0; hdr.ch_extid = true; - hdr.ch_unused = 0; #else /* Save the standard ID of the newly received message */ - hdr.ch_dlc = (msr & CAN_MSR_MDLC_MASK) >> CAN_MSR_MDLC_SHIFT; - hdr.ch_rtr = 0; hdr.ch_id = (mid & CAN_MAM_STDID_MASK) >> CAN_MAM_STDID_SHIFT; #endif + hdr.ch_dlc = (msr & CAN_MSR_MDLC_MASK) >> CAN_MSR_MDLC_SHIFT; + hdr.ch_rtr = 0; + hdr.ch_error = 0; + hdr.ch_unused = 0; + /* And provide the CAN message to the upper half logic */ ret = can_receive(dev, &hdr, (FAR uint8_t *)md); diff --git a/arch/arm/src/sama5/sam_dmac.c b/arch/arm/src/sama5/sam_dmac.c index f248d58937c..300c4e11f4f 100644 --- a/arch/arm/src/sama5/sam_dmac.c +++ b/arch/arm/src/sama5/sam_dmac.c @@ -1721,7 +1721,7 @@ static inline int sam_multiple(struct sam_dmach_s *dmach) * buffer transfer has completed. * * The DMAC transfer continues until the CTRLB register disables the - * descriptor (DSCR bits) registers at the final buffer tranfer. + * descriptor (DSCR bits) registers at the final buffer transfer. * * Enable error, buffer complete and transfer complete interrupts. We * don't really need the buffer complete interrupts, but we will take them @@ -2309,7 +2309,7 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg) dmach->callback = callback; dmach->arg = arg; - /* Is this a single block transfer? Or a multiple block tranfer? */ + /* Is this a single block transfer? Or a multiple block transfer? */ if (dmach->llhead == dmach->lltail) { diff --git a/arch/arm/src/sama5/sam_periphclks.h b/arch/arm/src/sama5/sam_periphclks.h index c7de0758dd1..bdef121d145 100644 --- a/arch/arm/src/sama5/sam_periphclks.h +++ b/arch/arm/src/sama5/sam_periphclks.h @@ -1,7 +1,7 @@ /************************************************************************************ * arch/arm/src/sama5/sam_periphclks.h * - * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,9 @@ /* Include the correctly logic for the configured chip */ -#if defined(ATSAMA5D3) +#if defined(ATSAMA5D2) +# include "sama5d2x_periphclks.h" +#elif defined(ATSAMA5D3) # include "sama5d3x_periphclks.h" #elif defined(ATSAMA5D4) # include "sama5d4x_periphclks.h" diff --git a/arch/arm/src/sama5/sam_rtc.c b/arch/arm/src/sama5/sam_rtc.c index db1be973892..01539235a6c 100644 --- a/arch/arm/src/sama5/sam_rtc.c +++ b/arch/arm/src/sama5/sam_rtc.c @@ -245,7 +245,7 @@ static int rtc_bcd2bin(uint32_t value) * ************************************************************************************/ -#if CONFIG_RTC_ALARM +#ifdef CONFIG_RTC_ALARM static void rtc_worker(FAR void *arg) { /* Sample once (atomically) */ @@ -278,7 +278,7 @@ static void rtc_worker(FAR void *arg) * ************************************************************************************/ -#if CONFIG_RTC_ALARM +#ifdef CONFIG_RTC_ALARM static int rtc_interrupt(int irq, void *context) { int ret; diff --git a/arch/arm/src/sama5/sam_tsd.c b/arch/arm/src/sama5/sam_tsd.c index fd9d55f7a0f..9c44bdd370a 100644 --- a/arch/arm/src/sama5/sam_tsd.c +++ b/arch/arm/src/sama5/sam_tsd.c @@ -1552,7 +1552,7 @@ static void sam_tsd_initialize(struct sam_tsd_s *priv) sam_adc_getreg(priv->adc, SAM_ADC_XPOSR); sam_adc_getreg(priv->adc, SAM_ADC_YPOSR); -#if CONFIG_SAMA5_TSD_4WIRE +#ifdef CONFIG_SAMA5_TSD_4WIRE sam_adc_getreg(priv->adc, SAM_ADC_PRESSR); #endif diff --git a/arch/arm/src/sama5/sam_udphs.c b/arch/arm/src/sama5/sam_udphs.c index 7d4d700cd97..e5791f4af91 100644 --- a/arch/arm/src/sama5/sam_udphs.c +++ b/arch/arm/src/sama5/sam_udphs.c @@ -555,7 +555,7 @@ static const struct usb_epdesc_s g_ep0desc = #ifdef CONFIG_SAMA5_UDPHS_SCATTERGATHER #ifdef CONFIG_SAMA5_UDPHS_PREALLOCATE -/* This is a properly aligned pool of preallocated DMA transfer desciptors */ +/* This is a properly aligned pool of preallocated DMA transfer descriptors */ static struct sam_dtd_s g_dtdpool[CONFIG_SAMA5_UDPHS_NDTDS] __attribute__ ((aligned(16))); @@ -563,7 +563,7 @@ static struct sam_dtd_s g_dtdpool[CONFIG_SAMA5_UDPHS_NDTDS] #endif -/* Device error strings that may be enabled for more desciptive USB trace +/* Device error strings that may be enabled for more descriptive USB trace * output. */ @@ -604,7 +604,7 @@ const struct trace_msg_t g_usb_trace_strings_deverror[] = }; #endif -/* Interrupt event strings that may be enabled for more desciptive USB trace +/* Interrupt event strings that may be enabled for more descriptive USB trace * output. */ @@ -1280,7 +1280,7 @@ static void sam_req_wrsetup(struct sam_usbdev_s *priv, * When a request is queued, the request 'len' is the number of bytes * to transfer and 'xfrd' and 'inflight' must be zero. * - * When this function starts a tranfer it will update the request + * When this function starts a transfer it will update the request * 'inflight' field to indicate the size of the transfer. * * When the transfer completes, the the 'inflight' field must hold the @@ -1547,7 +1547,7 @@ static void sam_req_rddisable(uint8_t epno) * - When receiving data via DMA, then data has already been transferred * and this function is called on the terminating event. The transfer * is complete and we just need to check for end of request events and - * if we need to setup the tranfer for the next request. + * if we need to setup the transfer for the next request. * - When receiving via the FIFO, the transfer is not complete. The * data is in the FIFO and must be transferred from the FIFO to the * request buffer. No setup is needed for the next transfer other than diff --git a/arch/arm/src/sama5/sam_xdmac.c b/arch/arm/src/sama5/sam_xdmac.c index ba3af1b2675..2936dec8d95 100644 --- a/arch/arm/src/sama5/sam_xdmac.c +++ b/arch/arm/src/sama5/sam_xdmac.c @@ -2355,7 +2355,7 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg) xdmach->callback = callback; xdmach->arg = arg; - /* Is this a single block transfer? Or a multiple block tranfer? */ + /* Is this a single block transfer? Or a multiple block transfer? */ if (xdmach->llhead == xdmach->lltail) { diff --git a/arch/arm/src/sama5/sama5d2x_periphclks.h b/arch/arm/src/sama5/sama5d2x_periphclks.h new file mode 100644 index 00000000000..13db76d756a --- /dev/null +++ b/arch/arm/src/sama5/sama5d2x_periphclks.h @@ -0,0 +1,303 @@ +/************************************************************************************ + * arch/arm/src/sama5/sama5d2x_periphclks.h + * + * Copyright (C) 2015 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_SAMAD52X_PERIPHCLKS_H +#define __ARCH_ARM_SRC_SAMA5_SAMAD52X_PERIPHCLKS_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include +#include "chip/sam_pmc.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Helper macros */ + +#define sam_enableperiph0(s) putreg32((1 << (s)), SAM_PMC_PCER0) +#define sam_enableperiph1(s) putreg32((1 << ((s) - 32)), SAM_PMC_PCER1) +#define sam_disableperiph0(s) putreg32((1 << (s)), SAM_PMC_PCDR0) +#define sam_disableperiph1(s) putreg32((1 << ((s) - 32)), SAM_PMC_PCDR1) +#define sam_isenabled0(s) (getreg32(SAM_PMC_PCER0) & (1 << (s)) != 0) +#define sam_isenabled1(s) (getreg32(SAM_PMC_PCER1) & (1 << ((s) - 32)) != 0) + +#define sam_fiq_enableclk() /* No peripheral clock */ +#define sam_arm_enableclk() /* No peripheral clock */ +#define sam_pit_enableclk() sam_enableperiph0(SAM_PID_PIT) +#define sam_wdt_enableclk() sam_enableperiph0(SAM_PID_WDT) +#define sam_emac0_enableclk() sam_enableperiph0(SAM_PID_EMAC0) +#define sam_xdmac0_enableclk() sam_enableperiph0(SAM_PID_XDMAC0) +#define sam_xdmac1_enableclk() sam_enableperiph0(SAM_PID_XDMAC1) +#define sam_icm_enableclk() sam_enableperiph0(SAM_PID_ICM) +#define sam_aes_enableclk() sam_enableperiph0(SAM_PID_AES) +#define sam_aesb_enableclk() sam_enableperiph0(SAM_PID_AESB) +#define sam_tdes_enableclk() sam_enableperiph0(SAM_PID_TDES) +#define sam_sha_enableclk() sam_enableperiph0(SAM_PID_SHA) +#define sam_mpddrc_enableclk() sam_enableperiph0(SAM_PID_MPDDRC) +#define sam_matrix1_enableclk() sam_enableperiph0(SAM_PID_MATRIX1) +#define sam_matrix0_enableclk() sam_enableperiph0(SAM_PID_MATRIX0) +#define sam_secumod_enableclk() sam_enableperiph0(SAM_PID_SECUMOD) +#define sam_hsmc_enableclk() sam_enableperiph0(SAM_PID_HSMC) +#define sam_pioa_enableclk() sam_enableperiph0(SAM_PID_PIOA) +#define sam_flexcom0_enableclk() sam_enableperiph0(SAM_PID_FLEXCOM0) +#define sam_flexcom1_enableclk() sam_enableperiph0(SAM_PID_FLEXCOM1) +#define sam_flexcom2_enableclk() sam_enableperiph0(SAM_PID_FLEXCOM2) +#define sam_flexcom3_enableclk() sam_enableperiph0(SAM_PID_FLEXCOM3) +#define sam_flexcom4_enableclk() sam_enableperiph0(SAM_PID_FLEXCOM4) +#define sam_uart0_enableclk() sam_enableperiph0(SAM_PID_UART0) +#define sam_uart1_enableclk() sam_enableperiph0(SAM_PID_UART1) +#define sam_uart2_enableclk() sam_enableperiph0(SAM_PID_UART2) +#define sam_uart3_enableclk() sam_enableperiph0(SAM_PID_UART3) +#define sam_uart4_enableclk() sam_enableperiph0(SAM_PID_UART4) +#define sam_twi0_enableclk() sam_enableperiph0(SAM_PID_TWI0) +#define sam_twi1_enableclk() sam_enableperiph0(SAM_PID_TWI1) +#define sam_sdmmc0_enableclk() sam_enableperiph0(SAM_PID_SDMMC0) + +#define sam_sdmmc1_enableclk() sam_enableperiph1(SAM_PID_SDMMC1) +#define sam_spi0_enableclk() sam_enableperiph1(SAM_PID_SPI0) +#define sam_spi1_enableclk() sam_enableperiph1(SAM_PID_SPI1) +#define sam_tc0_enableclk() sam_enableperiph1(SAM_PID_TC0) +#define sam_tc1_enableclk() sam_enableperiph1(SAM_PID_TC1) +#define sam_pwm_enableclk() sam_enableperiph1(SAM_PID_PWM) +#define sam_adc_enableclk() sam_enableperiph1(SAM_PID_ADC) +#define sam_uhphs_enableclk() sam_enableperiph1(SAM_PID_UHPHS) +#define sam_udphs_enableclk() sam_enableperiph1(SAM_PID_UDPHS) +#define sam_ssc0_enableclk() sam_enableperiph1(SAM_PID_SSC0) +#define sam_ssc1_enableclk() sam_enableperiph1(SAM_PID_SSC1) +#define sam_lcdc_enableclk() sam_enableperiph1(SAM_PID_LCDC) +#define sam_isc_enableclk() sam_enableperiph1(SAM_PID_ISC) +#define sam_trng_enableclk() sam_enableperiph1(SAM_PID_TRNG) +#define sam_pdmic_enableclk() sam_enableperiph1(SAM_PID_PDMIC) +#define sam_irqid_enableclk() sam_enableperiph1(SAM_PID_IRQID) +#define sam_sfc_enableclk() sam_enableperiph1(SAM_PID_SFC) +#define sam_securam_enableclk() sam_enableperiph1(SAM_PID_SECURAM) +#define sam_qspi0_enableclk() sam_enableperiph1(SAM_PID_QSPI0) +#define sam_qspi1_enableclk() sam_enableperiph1(SAM_PID_QSPI1) +#define sam_i2sc0_enableclk() sam_enableperiph1(SAM_PID_I2SC0) +#define sam_i2sc1_enableclk() sam_enableperiph1(SAM_PID_I2SC1) +#define sam_mcan0_enableclk() sam_enableperiph1(SAM_PID_MCAN00) +#define sam_mcan1_enableclk() sam_enableperiph1(SAM_PID_MCAN10) +#define sam_classd_enableclk() sam_enableperiph1(SAM_PID_CLASSD) +#define sam_sfr_enableclk() sam_enableperiph1(SAM_PID_SFR) +#define sam_saic_enableclk() sam_enableperiph1(SAM_PID_SAIC) +#define sam_aic_enableclk() sam_enableperiph1(SAM_PID_AIC) + +#define sam_piob_enableclk() /* No peripheral clock */ +#define sam_pioc_enableclk() /* No peripheral clock */ +#define sam_piod_enableclk() /* No peripheral clock */ +#define sam_sys_enableclk() /* No peripheral clock */ +#define sam_acc_enableclk() /* No peripheral clock */ +#define sam_rxlp_enableclk() /* No peripheral clock */ +#define sam_sfrbu_enableclk() /* No peripheral clock */ +#define sam_chipid_enableclk() /* No peripheral clock */ + +#define sam_fiq_disableclk() /* No peripheral clock */ +#define sam_arm_disableclk() /* No peripheral clock */ +#define sam_pit_disableclk() sam_disableperiph0(SAM_PID_PIT) +#define sam_wdt_disableclk() sam_disableperiph0(SAM_PID_WDT) +#define sam_emac0_disableclk() sam_disableperiph0(SAM_PID_EMAC0) +#define sam_xdmac0_disableclk() sam_disableperiph0(SAM_PID_XDMAC0) +#define sam_xdmac1_disableclk() sam_disableperiph0(SAM_PID_XDMAC1) +#define sam_icm_disableclk() sam_disableperiph0(SAM_PID_ICM) +#define sam_aes_disableclk() sam_disableperiph0(SAM_PID_AES) +#define sam_aesb_disableclk() sam_disableperiph0(SAM_PID_AESB) +#define sam_tdes_disableclk() sam_disableperiph0(SAM_PID_TDES) +#define sam_sha_disableclk() sam_disableperiph0(SAM_PID_SHA) +#define sam_mpddrc_disableclk() sam_disableperiph0(SAM_PID_MPDDRC) +#define sam_matrix1_disableclk() sam_disableperiph0(SAM_PID_MATRIX1) +#define sam_matrix0_disableclk() sam_disableperiph0(SAM_PID_MATRIX0) +#define sam_secumod_disableclk() sam_disableperiph0(SAM_PID_SECUMOD) +#define sam_hsmc_disableclk() sam_disableperiph0(SAM_PID_HSMC) +#define sam_pioa_disableclk() sam_disableperiph0(SAM_PID_PIOA) +#define sam_flexcom0_disableclk() sam_disableperiph0(SAM_PID_FLEXCOM0) +#define sam_flexcom1_disableclk() sam_disableperiph0(SAM_PID_FLEXCOM1) +#define sam_flexcom2_disableclk() sam_disableperiph0(SAM_PID_FLEXCOM2) +#define sam_flexcom3_disableclk() sam_disableperiph0(SAM_PID_FLEXCOM3) +#define sam_flexcom4_disableclk() sam_disableperiph0(SAM_PID_FLEXCOM4) +#define sam_uart0_disableclk() sam_disableperiph0(SAM_PID_UART0) +#define sam_uart1_disableclk() sam_disableperiph0(SAM_PID_UART1) +#define sam_uart2_disableclk() sam_disableperiph0(SAM_PID_UART2) +#define sam_uart3_disableclk() sam_disableperiph0(SAM_PID_UART3) +#define sam_uart4_disableclk() sam_disableperiph0(SAM_PID_UART4) +#define sam_twi0_disableclk() sam_disableperiph0(SAM_PID_TWI0) +#define sam_twi1_disableclk() sam_disableperiph0(SAM_PID_TWI1) +#define sam_sdmmc0_disableclk() sam_disableperiph0(SAM_PID_SDMMC0) + +#define sam_sdmmc1_disableclk() sam_disableperiph1(SAM_PID_SDMMC1) +#define sam_spi0_disableclk() sam_disableperiph1(SAM_PID_SPI0) +#define sam_spi1_disableclk() sam_disableperiph1(SAM_PID_SPI1) +#define sam_tc0_disableclk() sam_disableperiph1(SAM_PID_TC0) +#define sam_tc1_disableclk() sam_disableperiph1(SAM_PID_TC1) +#define sam_pwm_disableclk() sam_disableperiph1(SAM_PID_PWM) +#define sam_adc_disableclk() sam_disableperiph1(SAM_PID_ADC) +#define sam_uhphs_disableclk() sam_disableperiph1(SAM_PID_UHPHS) +#define sam_udphs_disableclk() sam_disableperiph1(SAM_PID_UDPHS) +#define sam_ssc0_disableclk() sam_disableperiph1(SAM_PID_SSC0) +#define sam_ssc1_disableclk() sam_disableperiph1(SAM_PID_SSC1) +#define sam_lcdc_disableclk() sam_disableperiph1(SAM_PID_LCDC) +#define sam_isc_disableclk() sam_disableperiph1(SAM_PID_ISC) +#define sam_trng_disableclk() sam_disableperiph1(SAM_PID_TRNG) +#define sam_pdmic_disableclk() sam_disableperiph1(SAM_PID_PDMIC) +#define sam_irqid_disableclk() sam_disableperiph1(SAM_PID_IRQID) +#define sam_sfc_disableclk() sam_disableperiph1(SAM_PID_SFC) +#define sam_securam_disableclk() sam_disableperiph1(SAM_PID_SECURAM) +#define sam_qspi0_disableclk() sam_disableperiph1(SAM_PID_QSPI0) +#define sam_qspi1_disableclk() sam_disableperiph1(SAM_PID_QSPI1) +#define sam_i2sc0_disableclk() sam_disableperiph1(SAM_PID_I2SC0) +#define sam_i2sc1_disableclk() sam_disableperiph1(SAM_PID_I2SC1) +#define sam_mcan0_disableclk() sam_disableperiph1(SAM_PID_MCAN00) +#define sam_mcan1_disableclk() sam_disableperiph1(SAM_PID_MCAN10) +#define sam_classd_disableclk() sam_disableperiph1(SAM_PID_CLASSD) +#define sam_sfr_disableclk() sam_disableperiph1(SAM_PID_SFR) +#define sam_saic_disableclk() sam_disableperiph1(SAM_PID_SAIC) +#define sam_aic_disableclk() sam_disableperiph1(SAM_PID_AIC) + +#define sam_piob_disableclk() /* No peripheral clock */ +#define sam_pioc_disableclk() /* No peripheral clock */ +#define sam_piod_disableclk() /* No peripheral clock */ +#define sam_sys_disableclk() /* No peripheral clock */ +#define sam_acc_disableclk() /* No peripheral clock */ +#define sam_rxlp_disableclk() /* No peripheral clock */ +#define sam_sfrbu_disableclk() /* No peripheral clock */ +#define sam_chipid_disableclk() /* No peripheral clock */ + +#define sam_fiq_isenabled() (false) /* No peripheral clock */ +#define sam_arm_isenabled() (false) /* No peripheral clock */ +#define sam_pit_isenabled() sam_isenabled0(SAM_PID_PIT) +#define sam_wdt_isenabled() sam_isenabled0(SAM_PID_WDT) +#define sam_emac0_isenabled() sam_isenabled0(SAM_PID_EMAC0) +#define sam_xdmac0_isenabled() sam_isenabled0(SAM_PID_XDMAC0) +#define sam_xdmac1_isenabled() sam_isenabled0(SAM_PID_XDMAC1) +#define sam_icm_isenabled() sam_isenabled0(SAM_PID_ICM) +#define sam_aes_isenabled() sam_isenabled0(SAM_PID_AES) +#define sam_aesb_isenabled() sam_isenabled0(SAM_PID_AESB) +#define sam_tdes_isenabled() sam_isenabled0(SAM_PID_TDES) +#define sam_sha_isenabled() sam_isenabled0(SAM_PID_SHA) +#define sam_mpddrc_isenabled() sam_isenabled0(SAM_PID_MPDDRC) +#define sam_matrix1_isenabled() sam_isenabled0(SAM_PID_MATRIX1) +#define sam_matrix0_isenabled() sam_isenabled0(SAM_PID_MATRIX0) +#define sam_secumod_isenabled() sam_isenabled0(SAM_PID_SECUMOD) +#define sam_hsmc_isenabled() sam_isenabled0(SAM_PID_HSMC) +#define sam_pioa_isenabled() sam_isenabled0(SAM_PID_PIOA) +#define sam_flexcom0_isenabled() sam_isenabled0(SAM_PID_FLEXCOM0) +#define sam_flexcom1_isenabled() sam_isenabled0(SAM_PID_FLEXCOM1) +#define sam_flexcom2_isenabled() sam_isenabled0(SAM_PID_FLEXCOM2) +#define sam_flexcom3_isenabled() sam_isenabled0(SAM_PID_FLEXCOM3) +#define sam_flexcom4_isenabled() sam_isenabled0(SAM_PID_FLEXCOM4) +#define sam_uart0_isenabled() sam_isenabled0(SAM_PID_UART0) +#define sam_uart1_isenabled() sam_isenabled0(SAM_PID_UART1) +#define sam_uart2_isenabled() sam_isenabled0(SAM_PID_UART2) +#define sam_uart3_isenabled() sam_isenabled0(SAM_PID_UART3) +#define sam_uart4_isenabled() sam_isenabled0(SAM_PID_UART4) +#define sam_twi0_isenabled() sam_isenabled0(SAM_PID_TWI0) +#define sam_twi1_isenabled() sam_isenabled0(SAM_PID_TWI1) +#define sam_sdmmc0_isenabled() sam_isenabled0(SAM_PID_SDMMC0) + +#define sam_sdmmc1_isenabled() sam_isenabled1(SAM_PID_SDMMC1) +#define sam_spi0_isenabled() sam_isenabled1(SAM_PID_SPI0) +#define sam_spi1_isenabled() sam_isenabled1(SAM_PID_SPI1) +#define sam_tc0_isenabled() sam_isenabled1(SAM_PID_TC0) +#define sam_tc1_isenabled() sam_isenabled1(SAM_PID_TC1) +#define sam_pwm_isenabled() sam_isenabled1(SAM_PID_PWM) +#define sam_adc_isenabled() sam_isenabled1(SAM_PID_ADC) +#define sam_uhphs_isenabled() sam_isenabled1(SAM_PID_UHPHS) +#define sam_udphs_isenabled() sam_isenabled1(SAM_PID_UDPHS) +#define sam_ssc0_isenabled() sam_isenabled1(SAM_PID_SSC0) +#define sam_ssc1_isenabled() sam_isenabled1(SAM_PID_SSC1) +#define sam_lcdc_isenabled() sam_isenabled1(SAM_PID_LCDC) +#define sam_isc_isenabled() sam_isenabled1(SAM_PID_ISC) +#define sam_trng_isenabled() sam_isenabled1(SAM_PID_TRNG) +#define sam_pdmic_isenabled() sam_isenabled1(SAM_PID_PDMIC) +#define sam_irqid_isenabled() sam_isenabled1(SAM_PID_IRQID) +#define sam_sfc_isenabled() sam_isenabled1(SAM_PID_SFC) +#define sam_securam_isenabled() sam_isenabled1(SAM_PID_SECURAM) +#define sam_qspi0_isenabled() sam_isenabled1(SAM_PID_QSPI0) +#define sam_qspi1_isenabled() sam_isenabled1(SAM_PID_QSPI1) +#define sam_i2sc0_isenabled() sam_isenabled1(SAM_PID_I2SC0) +#define sam_i2sc1_isenabled() sam_isenabled1(SAM_PID_I2SC1) +#define sam_mcan0_isenabled() sam_isenabled1(SAM_PID_MCAN00) +#define sam_mcan1_isenabled() sam_isenabled1(SAM_PID_MCAN10) +#define sam_classd_isenabled() sam_isenabled1(SAM_PID_CLASSD) +#define sam_sfr_isenabled() sam_isenabled1(SAM_PID_SFR) +#define sam_saic_isenabled() sam_isenabled1(SAM_PID_SAIC) +#define sam_aic_isenabled() sam_isenabled1(SAM_PID_AIC) + +#define sam_piob_isenabled() (false) /* No peripheral clock */ +#define sam_pioc_isenabled() (false) /* No peripheral clock */ +#define sam_piod_isenabled() (false) /* No peripheral clock */ +#define sam_sys_isenabled() (false) /* No peripheral clock */ +#define sam_acc_isenabled() (false) /* No peripheral clock */ +#define sam_rxlp_isenabled() (false) /* No peripheral clock */ +#define sam_sfrbu_isenabled() (false) /* No peripheral clock */ +#define sam_chipid_isenabled() (false) /* No peripheral clock */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_SAMA5_SAMAD52X_PERIPHCLKS_H */ diff --git a/arch/arm/src/samdl/chip/saml_eic.h b/arch/arm/src/samdl/chip/saml_eic.h index fca13fe45fc..e6bb167e2eb 100644 --- a/arch/arm/src/samdl/chip/saml_eic.h +++ b/arch/arm/src/samdl/chip/saml_eic.h @@ -106,7 +106,7 @@ # define EIC_NVMICTRL_NMISENSE_HIGH (4 << EIC_NVMICTRL_NMISENSE_SHIFT) /* High level detection */ # define EIC_NVMICTRL_NMISENSE_LOW (5 << EIC_NVMICTRL_NMISENSE_SHIFT) /* Low level detection */ #define EIC_NVMICTRL_NMIFLTEN (1 << 3) /* Bit 3: Non-maskable interrupt filter enable */ -#define EIC_NVMICTRL_ASYNC (1 << 4) /* Bit 4: Asynchronous edge detectino mode */ +#define EIC_NVMICTRL_ASYNC (1 << 4) /* Bit 4: Asynchronous edge detection mode */ /* Non-maskable interrupt flas status and clear register */ diff --git a/arch/arm/src/samdl/sam_lowputc.c b/arch/arm/src/samdl/sam_lowputc.c index a8b4d117623..fcc512279d7 100644 --- a/arch/arm/src/samdl/sam_lowputc.c +++ b/arch/arm/src/samdl/sam_lowputc.c @@ -296,6 +296,9 @@ sam_pad_configure(const struct sam_usart_config_s * const config) #ifdef SAMDL_HAVE_USART int sam_usart_internal(const struct sam_usart_config_s * const config) { +#ifdef CONFIG_ARCH_FAMILY_SAML21 + int channel; +#endif int ret; /* Enable clocking to the SERCOM module */ @@ -306,10 +309,20 @@ int sam_usart_internal(const struct sam_usart_config_s * const config) #if defined(CONFIG_ARCH_FAMILY_SAMD20) || defined(CONFIG_ARCH_FAMILY_SAMD21) sercom_coreclk_configure(config->sercom, config->gclkgen, false); + #elif defined(CONFIG_ARCH_FAMILY_SAML21) - sam_gclk_chan_enable(config->sercom + GCLK_CHAN_SERCOM0_CORE, - config->gclkgen); + if (config->sercom == 5) + { + channel = GCLK_CHAN_SERCOM5_CORE; + } + else + { + channel = config->sercom + GCLK_CHAN_SERCOM0_CORE; + } + + sam_gclk_chan_enable(channel, config->gclkgen); #endif + sercom_slowclk_configure(config->sercom, config->slowgen); /* Set USART configuration according to the board configuration */ diff --git a/arch/arm/src/samdl/sam_port.c b/arch/arm/src/samdl/sam_port.c index dddc7a1ae9e..b8445c7f1af 100644 --- a/arch/arm/src/samdl/sam_port.c +++ b/arch/arm/src/samdl/sam_port.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/samdl/sam_port.c * - * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * References: @@ -94,7 +94,7 @@ static inline uintptr_t sam_portbase(port_pinset_t pinset) * Name: sam_portpin * * Description: - * Returun the base address of the PORT register set + * Return the bit associated with the pin * ****************************************************************************/ @@ -330,7 +330,7 @@ static inline void sam_configperiph(uintptr_t base, port_pinset_t pinset) regval |= PORT_WRCONFIG_INEN; } - if (pin > 16) + if (pin >= 16) { /* Select the upper half word and adjust the bit setting */ @@ -538,15 +538,15 @@ int sam_dumpport(uint32_t pinset, const char *msg) /* Get the base address associated with the PIO port */ - pin = sam_portpin(pinset); + pin = (pinset & PORT_PIN_MASK) >> PORT_PIN_SHIFT; port = (pinset & PORT_MASK) >> PORT_SHIFT; base = SAM_PORTN_BASE(port); /* The following requires exclusive access to the PORT registers */ flags = irqsave(); - lldbg("PORT%c pinset: %08x base: %08x -- %s\n", - g_portchar[port], pinset, base, msg); + lldbg("PORT%c pin: %d pinset: %08x base: %08x -- %s\n", + g_portchar[port], pin, pinset, base, msg); lldbg(" DIR: %08x OUT: %08x IN: %08x\n", getreg32(base + SAM_PORT_DIR_OFFSET), getreg32(base + SAM_PORT_OUT_OFFSET), diff --git a/arch/arm/src/samdl/sam_port.h b/arch/arm/src/samdl/sam_port.h index d40c9246a41..26ba8bcb5d3 100644 --- a/arch/arm/src/samdl/sam_port.h +++ b/arch/arm/src/samdl/sam_port.h @@ -380,7 +380,7 @@ bool sam_portread(port_pinset_t pinset); ****************************************************************************/ #ifdef CONFIG_DEBUG -void sam_dumpport(port_pinset_t pinset, const char *msg); +int sam_dumpport(port_pinset_t pinset, const char *msg); #else # define sam_dumpport(p,m) #endif diff --git a/arch/arm/src/samdl/sam_spi.c b/arch/arm/src/samdl/sam_spi.c index a90737debac..bbbfb55101b 100644 --- a/arch/arm/src/samdl/sam_spi.c +++ b/arch/arm/src/samdl/sam_spi.c @@ -1467,6 +1467,9 @@ struct spi_dev_s *up_spiinitialize(int port) struct sam_spidev_s *priv; irqstate_t flags; uint32_t regval; +#ifdef CONFIG_ARCH_FAMILY_SAML21 + int channel; +#endif #if 0 /* Not used */ int ret; #endif @@ -1534,7 +1537,22 @@ struct spi_dev_s *up_spiinitialize(int port) /* Configure the GCLKs for the SERCOM module */ +#if defined(CONFIG_ARCH_FAMILY_SAMD20) || defined(CONFIG_ARCH_FAMILY_SAMD21) sercom_coreclk_configure(priv->sercom, priv->gclkgen, false); + +#elif defined(CONFIG_ARCH_FAMILY_SAML21) + if (priv->sercom == 5) + { + channel = GCLK_CHAN_SERCOM5_CORE; + } + else + { + channel = priv->sercom + GCLK_CHAN_SERCOM0_CORE; + } + + sam_gclk_chan_enable(channel, config->gclkgen); +#endif + sercom_slowclk_configure(priv->sercom, priv->slowgen); /* Set the SERCOM in SPI master mode (no address) */ diff --git a/arch/arm/src/samv7/Kconfig b/arch/arm/src/samv7/Kconfig index 9e42f55b745..3dede34314e 100644 --- a/arch/arm/src/samv7/Kconfig +++ b/arch/arm/src/samv7/Kconfig @@ -147,10 +147,6 @@ config SAMV7_HAVE_SDRAMC bool default n -config SAMV7_HAVE_SPI - bool - default n - config SAMV7_HAVE_SPI0 bool default n @@ -191,6 +187,18 @@ config SAMV7_HAVE_USART2 bool default n +config SAMV7_SPI + bool + default n + +config SAMV7_SPI_MASTER + bool + default n + +config SAMV7_SPI_SLAVE + bool + default n + # Peripheral Selection menu "SAMV7 Peripheral Selection" @@ -299,14 +307,14 @@ config SAMV7_SPI0 bool "Serial Peripheral Interface 0 (SPI0)" default n depends on SAMV7_HAVE_SPI0 - select SAMV7_HAVE_SPI + select SAMV7_SPI select SPI config SAMV7_SPI1 bool "Serial Peripheral Interface 1 (SPI1)" default n depends on SAMV7_HAVE_SPI1 - select SAMV7_HAVE_SPI + select SAMV7_SPI select SPI config SAMV7_SSC0 @@ -504,7 +512,6 @@ config SAMV7_GPIOE_IRQ default n endif # SAMV7_GPIO_IRQ -endif # ARCH_CHIP_SAMV7 menu "SDRAM Configuration" depends on SAMV7_SDRAMC @@ -526,8 +533,51 @@ config SAMV7_SDRAMHEAP endmenu # SDRAM Configuration -menu "SAMV7 SPI device driver options" - depends on AMV7_SPI0 || SAMV7_SPI1 +menu "SPI Device Driver Configuration" + depends on SAMV7_SPI + +choice + prompt "SPI0 Configuration" + default SAMV7_SPI0_MASTER + depends on SAMV7_SPI0 + +config SAMV7_SPI0_MASTER + bool "Master" + select SAMV7_SPI_MASTER + ---help--- + Configure SPI0 as an SPI master driver. Default: Master + +config SAMV7_SPI0_SLAVE + bool "Slave" + depends on EXPERIMENTAL + select SAMV7_SPI_SLAVE + ---help--- + Configure SPI0 as an SPI slave driver. Default: Master + +endchoice # SPI0 Configuration + +choice + prompt "SPI1 Configuration" + default SAMV7_SPI1_MASTER + depends on SAMV7_SPI1 + +config SAMV7_SPI1_MASTER + bool "Master" + select SAMV7_SPI_MASTER + ---help--- + Configure SPI1 as an SPI master driver. Default: Master + +config SAMV7_SPI1_SLAVE + bool "Slave" + depends on EXPERIMENTAL + select SAMV7_SPI_SLAVE + ---help--- + Configure SPI1 as an SPI slave driver. Default: Master + +endchoice # SPI1 Configuration + +if SAMV7_SPI_MASTER +comment "SPI Master Configuration" config SAMV7_SPI_DMA bool "SPI DMA" @@ -555,6 +605,20 @@ config SAMV7_SPI_DMADEBUG registers at key points in the data transfer and then dumps all of the registers at the end of the transfer. +endif # SAMV7_SPI_MASTER + +if SAMV7_SPI_SLAVE +comment "SPI Slave Configuration" + +config SAMV7_SPI_SLAVE_QSIZE + int "Output queue size" + default 8 + ---help--- + The number of words that an be retained in the controller driver's + output queue. + +endif # SAMV7_SPI_SLAVE + config SAMV7_SPI_REGDEBUG bool "SPI Register level debug" depends on DEBUG @@ -563,7 +627,54 @@ config SAMV7_SPI_REGDEBUG Output detailed register-level SPI device debug information. Requires also DEBUG. -endmenu # SAMV7 SPI device driver options +endmenu # SPI device driver options + +menu "QSPI Device Driver Configuration" + depends on SAMV7_QSPI && !SAMV7_QSPI_IS_SPI + +config SAMV7_QSPI_DLYBS + int "Delay Before QSCK (nsec)" + default 0 + +config SAMV7_QSPI_DLYBCT + int "Delay Between Consecutive Transfers (nsec)" + default 0 + +config SAMV7_QSPI_DMA + bool "QSPI DMA" + default n + depends on SAMV7_XDMAC + ---help--- + Use DMA to improve SPI transfer performance. + +config SAMV7_QSPI_DMATHRESHOLD + int "QSPI DMA threshold" + default 4 + depends on SAMV7_QSPI_DMA + ---help--- + When ASPI DMA is enabled, small DMA transfers will still be performed + by polling logic. But we need a threshold value to determine what + is small. That value is provided by SAMV7_QSPI_DMATHRESHOLD. + +config SAMV7_QSPI_DMADEBUG + bool "QSPI DMA transfer debug" + depends on SAMV7_QSPI_DMA && DEBUG && DEBUG_DMA + default n + ---help--- + Enable special debug instrumentation analyze QSPI DMA data transfers. + This logic is as non-invasive as possible: It samples DMA + registers at key points in the data transfer and then dumps all of + the registers at the end of the transfer. + +config SAMV7_QSPI_REGDEBUG + bool "QSPI Register level debug" + depends on DEBUG + default n + ---help--- + Output detailed register-level QSPI device debug information. + Requires also DEBUG. + +endmenu # QSPI device driver options menu "TWIHS device driver options" depends on SAMV7_TWIHS0 || SAMV7_TWIHS1 || SAMV7_TWIHS2 @@ -1264,7 +1375,6 @@ menu "USB High Speed Device Controller driver (DCD) options" config SAMV7_USBDEVHS_LOWPOWER bool "Low-power mode" default n - depends on EXPERIMENTAL ---help--- The USBHS can work in two modes: @@ -1272,7 +1382,9 @@ config SAMV7_USBDEVHS_LOWPOWER available. - Low-power mode where only Full speed and Low speed are available. - This options selects the low-power mode. + This options selects the low-power mode. In order to use high speed + mode, this option must be disabled and USBDEV_DUALSPEED must be + enabled. config SAMV7_USBHS_SCATTERGATHER bool @@ -1311,7 +1423,7 @@ menu "MCAN device driver options" choice prompt "MCAN clock source (PCK5)" - default SAMV7_MCAN_CLKSRC_MAIN + default SAMV7_MCAN_CLKSRC_MCK config SAMV7_MCAN_CLKSRC_SLOW bool "Slow clock" @@ -1333,7 +1445,11 @@ endchoice # MCAN clock source config SAMV7_MCAN_CLKSRC_PRESCALER int "MCAN clock prescaler" default 1 - range 1 256 + range 1 1024 + ---help--- + The frequency associated with time quanta is derived by dividing + down the input frequency. This setting provides prescaler/divider + must lie the range of 1 to 1024. menu "MCAN0 device driver options" depends on SAMV7_MCAN0 @@ -1447,6 +1563,7 @@ config SAMV7_MCAN0_NEXTFILTERS int "MCAN0 number of extended filters" default 8 range 0 64 + depends on CAN_EXTID ---help--- Number of extended message ID filters. @@ -1489,8 +1606,8 @@ endchoice # MCAN0 RX buffer element size config SAMV7_MCAN0_RXFIFO0_SIZE int "MCAN0 RX FIFO0 size" - default 12 - range 0 64 + default 8 + range 1 64 ---help--- Number of receive FIFO 0 elements. Zero disables FIFO 0. @@ -1533,8 +1650,8 @@ endchoice # MCAN0 RX buffer element size config SAMV7_MCAN0_RXFIFO1_SIZE int "MCAN0 RX FIFO1 size" - default 0 - range 0 64 + default 4 + range 1 64 ---help--- Number of receive FIFO 1 elements for MCAN0. Zero disables FIFO 1. @@ -1635,7 +1752,7 @@ config SAMV7_MCAN0_DEDICATED_TXBUFFER_SIZE config SAMV7_MCAN0_TXFIFOQ_SIZE int "MCAN0 TX FIFO queue size" default 4 - range 0 32 + range 1 32 ---help--- Number of dedicated TX buffer elements for MCAN0. @@ -1643,6 +1760,7 @@ config SAMV7_MCAN0_TXEVENTFIFO_SIZE int "MCAN0 TX event FIFO size" default 0 range 0 32 + depends on EXPERIMENTAL ---help--- Number of TX event FIFO elements for MCAN0. Zero disables TX event FIFO. @@ -1761,6 +1879,7 @@ config SAMV7_MCAN1_NEXTFILTERS int "MCAN1 number of extended filters" default 8 range 0 64 + depends on CAN_EXTID ---help--- Number of extended message ID filters. @@ -1803,8 +1922,8 @@ endchoice # MCAN1 RX buffer element size config SAMV7_MCAN1_RXFIFO0_SIZE int "MCAN1 RX FIFO0 size" - default 0 - range 0 64 + default 8 + range 1 64 ---help--- Number of receive FIFO 0 elements. Zero disables FIFO 0. @@ -1847,8 +1966,8 @@ endchoice # MCAN1 RX buffer element size config SAMV7_MCAN1_RXFIFO1_SIZE int "MCAN1 RX FIFO1 size" - default 0 - range 0 64 + default 4 + range 1 64 ---help--- Number of receive FIFO 1 elements for MCAN1. Zero disables FIFO 1. @@ -1940,6 +2059,7 @@ config SAMV7_MCAN1_TXEVENTFIFO_SIZE int "MCAN1 TX event FIFO size" default 0 range 0 32 + depends on EXPERIMENTAL ---help--- Number of TX event FIFO elements for MCAN1. Zero disables TX event FIFO. @@ -1954,9 +2074,9 @@ config SAMV7_MCAN1_DEDICATED_TXBUFFER_SIZE NOTE: Dedicated TX buffers are not used in the current MCAN design. config SAMV7_MCAN1_TXFIFOQ_SIZE - int "MCAN1 dedicated TX FIFO queue" + int "MCAN1 TX FIFO queue" default 4 - range 0 32 + range 1 32 ---help--- Number of dedicated TX buffer elements for MCAN1. @@ -1972,3 +2092,4 @@ config SAMV7_MCAN_REGDEBUG endmenu # CAN device driver options endif # SAMV7_MCAN +endif # ARCH_CHIP_SAMV7 diff --git a/arch/arm/src/samv7/Make.defs b/arch/arm/src/samv7/Make.defs index e919cf69256..5545c86c65f 100644 --- a/arch/arm/src/samv7/Make.defs +++ b/arch/arm/src/samv7/Make.defs @@ -77,6 +77,8 @@ ifeq ($(CONFIG_ARCH_FPU),y) CMN_ASRCS += up_fpu.S ifneq ($(CONFIG_ARMV7M_CMNVECTOR),y) CMN_CSRCS += up_copyarmstate.c +else ifeq ($(CONFIG_ARMV7M_LAZYFPU),y) +CMN_CSRCS += up_copyarmstate.c endif endif @@ -124,12 +126,18 @@ ifeq ($(CONFIG_SAMV7_XDMAC),y) CHIP_CSRCS += sam_xdmac.c endif -ifeq ($(CONFIG_SAMV7_SPI0),y) -CHIP_CSRCS += sam_spi.c -else ifeq ($(CONFIG_SAMV7_SPI1),y) +ifeq ($(CONFIG_SAMV7_SPI_MASTER),y) CHIP_CSRCS += sam_spi.c endif +ifeq ($(CONFIG_SAMV7_SPI_SLAVE),y) +CHIP_CSRCS += sam_spi_slave.c +endif + +ifeq ($(CONFIG_SAMV7_QSPI),y) +CHIP_CSRCS += sam_qspi.c +endif + ifeq ($(CONFIG_SAMV7_TWIHS0),y) CHIP_CSRCS += sam_twihs.c else ifeq ($(CONFIG_SAMV7_TWIHS1),y) diff --git a/arch/arm/src/samv7/chip/sam_qspi.h b/arch/arm/src/samv7/chip/sam_qspi.h new file mode 100644 index 00000000000..55605634e44 --- /dev/null +++ b/arch/arm/src/samv7/chip/sam_qspi.h @@ -0,0 +1,274 @@ +/**************************************************************************************** + * arch/arm/src/samv7/chip/sam_qspi.h + * Quad SPI (QSPI) definitions for the SAMV71 + * + * Copyright (C) 2015 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_SAMV7_CHIP_SAM_QSPI_H +#define __ARCH_ARM_SRC_SAMV7_CHIP_SAM_QSPI_H + +/**************************************************************************************** + * Included Files + ****************************************************************************************/ + +#include +#include + +#include "chip/sam_memorymap.h" + +#if SAMV7_NQSPI > 0 + +/**************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************/ +/* General Characteristics **************************************************************/ + +#define SAM_QSPI_MINBITS 8 /* Minimum word width */ +#define SAM_QSPI_MAXBITS 16 /* Maximum word width */ + +/* QSPI register offsets ****************************************************************/ + +#define SAM_QSPI_CR_OFFSET 0x0000 /* Control Register */ +#define SAM_QSPI_MR_OFFSET 0x0004 /* Mode Register */ +#define SAM_QSPI_RDR_OFFSET 0x0008 /* Receive Data Register */ +#define SAM_QSPI_TDR_OFFSET 0x000c /* Transmit Data Register */ +#define SAM_QSPI_SR_OFFSET 0x0010 /* Status Register */ +#define SAM_QSPI_IER_OFFSET 0x0014 /* Interrupt Enable Register */ +#define SAM_QSPI_IDR_OFFSET 0x0018 /* Interrupt Disable Register */ +#define SAM_QSPI_IMR_OFFSET 0x001c /* Interrupt Mask Register */ +#define SAM_QSPI_SCR_OFFSET 0x0020 /* Serial Clock Register */ +#define SAM_QSPI_IAR_OFFSET 0x0030 /* Instruction Address Register */ +#define SAM_QSPI_ICR_OFFSET 0x0034 /* Instruction Code Register */ +#define SAM_QSPI_IFR_OFFSET 0x0038 /* Instruction Frame Register */ + /* 0x003c Reserved */ +#define SAM_QSPI_SMR_OFFSET 0x0040 /* Scrambling Mode Register */ +#define SAM_QSPI_SKR_OFFSET 0x0044 /* Scrambling Key Register */ + /* 0x0048–0x00e0 Reserved */ +#define SAM_QSPI_WPCR_OFFSET 0x00e4 /* Write Protection Control Register */ +#define SAM_QSPI_WPSR_OFFSET 0x00e8 /* Write Protection Status Register */ + /* 0xec-0xfc: Reserved */ + +/* QSPI register addresses **************************************************************/ + +#define SAM_QSPI0_CR (SAM_QSPI0_BASE+SAM_QSPI_CR_OFFSET) /* Control Register */ +#define SAM_QSPI0_MR (SAM_QSPI0_BASE+SAM_QSPI_MR_OFFSET) /* Mode Register */ +#define SAM_QSPI0_RDR (SAM_QSPI0_BASE+SAM_QSPI_RDR_OFFSET) /* Receive Data Register */ +#define SAM_QSPI0_TDR (SAM_QSPI0_BASE+SAM_QSPI_TDR_OFFSET) /* Transmit Data Register */ +#define SAM_QSPI0_SR (SAM_QSPI0_BASE+SAM_QSPI_SR_OFFSET) /* Status Register */ +#define SAM_QSPI0_IER (SAM_QSPI0_BASE+SAM_QSPI_IER_OFFSET) /* Interrupt Enable Register */ +#define SAM_QSPI0_IDR (SAM_QSPI0_BASE+SAM_QSPI_IDR_OFFSET) /* Interrupt Disable Register */ +#define SAM_QSPI0_IMR (SAM_QSPI0_BASE+SAM_QSPI_IMR_OFFSET) /* Interrupt Mask Register */ +#define SAM_QSPI0_SCR (SAM_QSPI0_BASE+SAM_QSPI_SCR_OFFSET) /* Serial Clock Register */ +#define SAM_QSPI0_IAR (SAM_QSPI0_BASE+SAM_QSPI_IAR_OFFSET) /* Instruction Address Register */ +#define SAM_QSPI0_ICR (SAM_QSPI0_BASE+SAM_QSPI_ICR_OFFSET) /* Instruction Code Register */ +#define SAM_QSPI0_IFR (SAM_QSPI0_BASE+SAM_QSPI_IFR_OFFSET) /* Instruction Frame Register */ +#define SAM_QSPI0_SMR (SAM_QSPI0_BASE+SAM_QSPI_SMR_OFFSET) /* Scrambling Mode Register */ +#define SAM_QSPI0_SKR (SAM_QSPI0_BASE+SAM_QSPI_SKR_OFFSET) /* Scrambling Key Register */ +#define SAM_QSPI0_WPCR (SAM_QSPI0_BASE+SAM_QSPI_WPCR_OFFSET) /* Write Protection Control Register */ +#define SAM_QSPI0_WPSR (SAM_QSPI0_BASE+SAM_QSPI_WPSR_OFFSET) /* Write Protection Status Register */ + +#if SAMV7_NQSPI > 1 +# define SAM_QSPI1_CR (SAM_QSPI1_BASE+SAM_QSPI_CR_OFFSET) /* Control Register */ +# define SAM_QSPI1_MR (SAM_QSPI1_BASE+SAM_QSPI_MR_OFFSET) /* Mode Register */ +# define SAM_QSPI1_RDR (SAM_QSPI1_BASE+SAM_QSPI_RDR_OFFSET) /* Receive Data Register */ +# define SAM_QSPI1_TDR (SAM_QSPI1_BASE+SAM_QSPI_TDR_OFFSET) /* Transmit Data Register */ +# define SAM_QSPI1_SR (SAM_QSPI1_BASE+SAM_QSPI_SR_OFFSET) /* Status Register */ +# define SAM_QSPI1_IER (SAM_QSPI1_BASE+SAM_QSPI_IER_OFFSET) /* Interrupt Enable Register */ +# define SAM_QSPI1_IDR (SAM_QSPI1_BASE+SAM_QSPI_IDR_OFFSET) /* Interrupt Disable Register */ +# define SAM_QSPI1_IMR (SAM_QSPI1_BASE+SAM_QSPI_IMR_OFFSET) /* Interrupt Mask Register */ +# define SAM_QSPI1_SCR (SAM_QSPI1_BASE+SAM_QSPI_SCR_OFFSET) /* Serial Clock Register */ +# define SAM_QSPI1_IAR (SAM_QSPI1_BASE+SAM_QSPI_IAR_OFFSET) /* Instruction Address Register */ +# define SAM_QSPI1_ICR (SAM_QSPI1_BASE+SAM_QSPI_ICR_OFFSET) /* Instruction Code Register */ +# define SAM_QSPI1_IFR (SAM_QSPI1_BASE+SAM_QSPI_IFR_OFFSET) /* Instruction Frame Register */ +# define SAM_QSPI1_SMR (SAM_QSPI1_BASE+SAM_QSPI_SMR_OFFSET) /* Scrambling Mode Register */ +# define SAM_QSPI1_SKR (SAM_QSPI1_BASE+SAM_QSPI_SKR_OFFSET) /* Scrambling Key Register */ +# define SAM_QSPI1_WPCR (SAM_QSPI1_BASE+SAM_QSPI_WPCR_OFFSET) /* Write Protection Control Register */ +# define SAM_QSPI1_WPSR (SAM_QSPI1_BASE+SAM_QSPI_WPSR_OFFSET) /* Write Protection Status Register */ +#endif + +/* QSPI register bit definitions ********************************************************/ + +/* QSPI Control Register */ + +#define QSPI_CR_QSPIEN (1 << 0) /* Bit 0: QSPI Enable */ +#define QSPI_CR_QSPIDIS (1 << 1) /* Bit 1: QSPI Disable */ +#define QSPI_CR_SWRST (1 << 7) /* Bit 7: QSPI Software Reset */ +#define QSPI_CR_LASTXFER (1 << 24) /* Bit 24: Last Transfer */ + +/* QSPI Mode Register */ + +#define QSPI_MR_SMM (1 << 0) /* Bit 0: Serial Memory Mode */ +#define QSPI_MR_LLB (1 << 1) /* Bit 1: Local Loopback Enable */ +#define QSPI_MR_WDRBT (1 << 2) /* Bit 2: Wait Data Read Before Transfer */ +#define QSPI_MR_CSMODE_SHIFT (4) /* Bits 4-5: Chip Select Mode */ +#define QSPI_MR_CSMODE_MASK (3 << QSPI_MR_CSMODE_SHIFT) +# define QSPI_MR_CSMODE_NRELOAD (0 << QSPI_MR_CSMODE_SHIFT) /* CS deasserted if TD not reloaded */ +# define QSPI_MR_CSMODE_LASTXFER (1 << QSPI_MR_CSMODE_SHIFT) /* CS deasserted when LASTXFER transferred */ +# define QSPI_MR_CSMODE_SYSTEM (2 << QSPI_MR_CSMODE_SHIFT) /* CS deasserted after each transfer */ +#define QSPI_MR_NBBITS_SHIFT (8) /* Bits 8-11: Number Of Bits Per Transfer */ +#define QSPI_MR_NBBITS_MASK (15 << QSPI_MR_NBBITS_SHIFT) +# define QSPI_MR_NBBITS(n) ((uint32_t)((n)-SAM_QSPI_MINBITS) << QSPI_MR_NBBITS_SHIFT) +# define QSPI_MR_NBBITS_8BIT (0 << QSPI_MR_NBBITS_SHIFT) /* 8 bits for transfer */ +# define QSPI_MR_NBBITS_9BIT (1 << QSPI_MR_NBBITS_SHIFT) /* 9 bits for transfer */ +# define QSPI_MR_NBBITS_10BIT (2 << QSPI_MR_NBBITS_SHIFT) /* 10 bits for transfer */ +# define QSPI_MR_NBBITS_11BIT (3 << QSPI_MR_NBBITS_SHIFT) /* 11 bits for transfer */ +# define QSPI_MR_NBBITS_12BIT (4 << QSPI_MR_NBBITS_SHIFT) /* 12 bits for transfer */ +# define QSPI_MR_NBBITS_13BIT (5 << QSPI_MR_NBBITS_SHIFT) /* 13 bits for transfer */ +# define QSPI_MR_NBBITS_14BIT (6 << QSPI_MR_NBBITS_SHIFT) /* 14 bits for transfer */ +# define QSPI_MR_NBBITS_15BIT (7 << QSPI_MR_NBBITS_SHIFT) /* 15 bits for transfer */ +# define QSPI_MR_NBBITS_16BIT (8 << QSPI_MR_NBBITS_SHIFT) /* 16 bits for transfer */ +#define QSPI_MR_DLYBCT_SHIFT (16) /* Bits 16-23: Delay Between Consecutive Transfers */ +#define QSPI_MR_DLYBCT_MASK (0xff << QSPI_MR_DLYBCT_SHIFT) +# define QSPI_MR_DLYBCT(n) ((uint32_t)(n) << QSPI_MR_DLYBCT_SHIFT) +#define QSPI_MR_DLYCS_SHIFT (24) /* Bits 24-31: Minimum Inactive QCS Delay */ +#define QSPI_MR_DLYCS_MASK (0xff << QSPI_MR_DLYCS_SHIFT) +# define QSPI_MR_DLYCS(n) ((uint32_t)(n) << QSPI_MR_DLYCS_SHIFT) + +/* QSPI Receive Data Register */ + +#define QSPI_RDR_RD_SHIFT (0) /* Bits 0-15: Receive Data */ +#define QSPI_RDR_RD_MASK (0xffff << QSPI_RDR_RD_SHIFT) + +/* QSPI Transmit Data Register */ + +#define QSPI_TDR_TD_SHIFT (0) /* Bits 0-15: Transmit Data */ +#define QSPI_TDR_TD_MASK (0xffff << QSPI_TDR_TD_SHIFT) + +/* QSPI Status Register, QSPI Interrupt Enable Register, QSPI Interrupt Disable Register, + * and QSPI Interrupt Mask Register (common bit fields) + */ + +#define QSPI_INT_RDRF (1 << 0) /* Bit 0: Receive Data Register Full Interrupt */ +#define QSPI_INT_TDRE (1 << 1) /* Bit 1: Transmit Data Register Empty Interrupt */ +#define QSPI_INT_TXEMPTY (1 << 2) /* Bit 2: Transmission Registers Empty Interrupt */ +#define QSPI_INT_OVRES (1 << 3) /* Bit 3: Overrun Error Interrupt */ +#define QSPI_INT_CSR (1 << 8) /* Bit 8: Chip Select Rise Interrupt */ +#define QSPI_SR_CSS (1 << 9) /* Bit 9: Chip Select Status Interrupt */ +#define QSPI_SR_INSTRE (1 << 10) /* Bit 10: Instruction End Status Interrupt */ +#define QSPI_SR_QSPIENS (1 << 24) /* Bit 24: QSPI Enable Status (SR only) */ + +#define QSPI_INT_ALL (0x0000070f) + +/* Serial Clock Register */ + +#define QSPI_SCR_CPOL (1 << 0) /* Bit 0: Clock Polarity */ +#define QSPI_SCR_CPHA (1 << 1) /* Bit 1: Clock Phase */ +#define QSPI_SCR_SCBR_SHIFT (8) /* Bits 8-15: Serial Clock Baud Rate */ +#define QSPI_SCR_SCBR_MASK (0xff << QSPI_SCR_SCBR_SHIFT) +# define QSPI_SCR_SCBR(n) ((uint32_t)(n) << QSPI_SCR_SCBR_SHIFT) +#define QSPI_SCR_DLYBS_SHIFT (16) /* Bits 16-23: Delay Before QSCK */ +#define QSPI_SCR_DLYBS_MASK (0xff << QSPI_SCR_DLYBS_SHIFT) +# define QSPI_SCR_DLYBS(n) ((uint32_t)(n) << QSPI_SCR_DLYBS_SHIFT) + +/* Instruction Address Register (32-bit value) */ + +/* Instruction Code Register */ + +#define QSPI_ICR_INST_SHIFT (0) /* Bits 0-7: Instruction Code */ +#define QSPI_ICR_INST_MASK (0xff << QSPI_ICR_INST_SHIFT) +# define QSPI_ICR_INST(n) ((uint32_t)(n) << QSPI_ICR_INST_SHIFT) +#define QSPI_ICR_OPT_SHIFT (16) /* Bits 16-23: Option Code */ +#define QSPI_ICR_OPT_MASK (0xff << QSPI_ICR_OPT_SHIFT) +# define QSPI_ICR_OPT(n) ((uint32_t)(n) << QSPI_ICR_OPT_SHIFT) + +/* Instruction Frame Register */ + +#define QSPI_IFR_WIDTH_SHIFT (0) /* Bits 0-2: Width of Instruction Code, + * Address, Option Code and Data */ +#define QSPI_IFR_WIDTH_MASK (7 << QSPI_IFR_WIDTH_SHIFT) + /* Instruction Address-Option Data */ +# define QSPI_IFR_WIDTH_SINGLE (0 << QSPI_IFR_WIDTH_SHIFT) /* Single-bit Single-bit Single-bit */ +# define QSPI_IFR_WIDTH_DUALOUT (1 << QSPI_IFR_WIDTH_SHIFT) /* Single-bit Single-bit Dual */ +# define QSPI_IFR_WIDTH_QUADOUT (2 << QSPI_IFR_WIDTH_SHIFT) /* Single-bit Single-bit Quad */ +# define QSPI_IFR_WIDTH_DUALIO (3 << QSPI_IFR_WIDTH_SHIFT) /* Single-bit Dual Dual */ +# define QSPI_IFR_WIDTH_QUADIO (4 << QSPI_IFR_WIDTH_SHIFT) /* Single-bit Quad Quad */ +# define QSPI_IFR_WIDTH_DUALCMD (5 << QSPI_IFR_WIDTH_SHIFT) /* Dual Dual Dual */ +# define QSPI_IFR_WIDTH_QUADCMD (6 << QSPI_IFR_WIDTH_SHIFT) /* Quad Quad Quad */ +#define QSPI_IFR_INSTEN (1 << 4) /* Bit 4: Instruction Enable */ +#define QSPI_IFR_ADDREN (1 << 5) /* Bit 5: Address Enable */ +#define QSPI_IFR_OPTEN (1 << 6) /* Bit 6: Option Enable */ +#define QSPI_IFR_DATAEN (1 << 7) /* Bit 7: Data Enable */ +#define QSPI_IFR_OPTL_SHIFT (8) /* Bits 8-9: Option Code Length */ +#define QSPI_IFR_OPTL_MASK (3 << QSPI_IFR_OPTL_SHIFT) +# define QSPI_IFR_OPTL_1BIT (0 << QSPI_IFR_OPTL_SHIFT) /* Option is 1 bit */ +# define QSPI_IFR_OPTL_2BIT (1 << QSPI_IFR_OPTL_SHIFT) /* Option is 2 bits */ +# define QSPI_IFR_OPTL_4BIT (2 << QSPI_IFR_OPTL_SHIFT) /* Option is 4 bits */ +# define QSPI_IFR_OPTL_8BIT (3 << QSPI_IFR_OPTL_SHIFT) /* Option is 8 bits */ +#define QSPI_IFR_ADDRL (1 << 10) /* Bit 10: Address Length */ +# define QSPI_IFR_ADDRL_24BIT (0 << 10) /* 0=24-bit */ +# define QSPI_IFR_ADDRL_32BIT (1 << 10) /* 1=32-bit */ +#define QSPI_IFR_TFRTYP_SHIFT (12) /* Bits 12-13: Data Transfer Type */ +#define QSPI_IFR_TFRTYP_MASK (3 << QSPI_IFR_TFRTYP_SHIFT) +# define QSPI_IFR_TFRTYP_READ (0 << QSPI_IFR_TFRTYP_SHIFT) /* Read transfer from serial memory */ +# define QSPI_IFR_TFRTYP_RDMEM (1 << QSPI_IFR_TFRTYP_SHIFT) /* Read data transfer from serial memory */ +# define QSPI_IFR_TFRTYP_WRITE (2 << QSPI_IFR_TFRTYP_SHIFT) /* Write transfer into serial memory */ +# define QSPI_IFR_TFRTYP_WRMEM (3 << QSPI_IFR_TFRTYP_SHIFT) /* Write data transfer the serial memory */ +#define QSPI_IFR_CRM (1 << 14) /* Bit 14: Continuous Read Mode */ +#define QSPI_IFR_NBDUM_SHIFT (16) /* Bits 16-20: Number Of Dummy Cycles */ +#define QSPI_IFR_NBDUM_MASK (31 << QSPI_IFR_NBDUM_SHIFT) +# define QSPI_IFR_NBDUM(n) ((uint32_t)(n) << QSPI_IFR_NBDUM_SHIFT) + +/* Scrambling Mode Register */ + +#define QSPI_SMR_SCREN (1 << 0) /* Bit 0: Scrambling/Unscrambling Enable */ +#define QSPI_SMR_RVDIS (1 << 1) /* Bit 1: Scrambling/Unscrambling Random Value Disable */ + +/* Scrambling Key Register (32-bit value) */ + +/* QSPI Write Protection Control Register */ + +#define QSPI_WPCR_WPEN (1 << 0) /* Bit 0: QSPI Write Protection Enable */ +#define QSPI_WPCR_WPKEY_SHIFT (8) /* Bits 8-31: QSPI Write Protection Key Password */ +#define QSPI_WPCR_WPKEY_MASK (0x00ffffff << QSPI_WPCR_WPKEY_SHIFT) +# define QSPI_WPCR_WPKEY (0x00515350 << QSPI_WPCR_WPKEY_SHIFT) + +/* QSPI Write Protection Status Register */ + +#define QSPI_WPSR_WPVS (1 << 0) /* Bit 0: QSPI Write Protection Violation Status */ +#define QSPI_WPSR_WPVSRC_SHIFT (8) /* Bits 8-15: QSPI Write Protection Violation Source */ +#define QSPI_WPSR_WPVSRC_MASK (0xff << QSPI_WPSR_WPVSRC_SHIFT) + +/**************************************************************************************** + * Public Types + ****************************************************************************************/ + +/**************************************************************************************** + * Public Data + ****************************************************************************************/ + +/**************************************************************************************** + * Public Functions + ****************************************************************************************/ + +#endif /* SAMV7_NQSPI > 0 */ +#endif /* __ARCH_ARM_SRC_SAMV7_CHIP_SAM_QSPI_H */ diff --git a/arch/arm/src/samv7/chip/sam_spi.h b/arch/arm/src/samv7/chip/sam_spi.h index 44ec25e8759..fe738b2e184 100644 --- a/arch/arm/src/samv7/chip/sam_spi.h +++ b/arch/arm/src/samv7/chip/sam_spi.h @@ -120,7 +120,8 @@ /* SPI Mode Register */ -#define SPI_MR_MSTR (1 << 0) /* Bit 0: Master/Slave Mode */ +#define SPI_MR_MSTR (1 << 0) /* Bit 0: 1=Master Mode */ +# define SPI_MR_SLAVE (0) /* 0=Slave Mode */ #define SPI_MR_PS (1 << 1) /* Bit 1: Peripheral Select */ #define SPI_MR_PCSDEC (1 << 2) /* Bit 2: Chip Select Decode */ #define SPI_MR_MODFDIS (1 << 4) /* Bit 4: Mode Fault Detection */ @@ -170,7 +171,9 @@ #define SPI_INT_NSSR (1 << 8) /* Bit 8: NSS Rising Interrupt */ #define SPI_INT_TXEMPTY (1 << 9) /* Bit 9: Transmission Registers Empty Interrupt */ #define SPI_INT_UNDES (1 << 10) /* Bit 10: Underrun Error Status Interrupt (slave) */ -#define SPI_SR_SPIENS (1 << 16) /* Bit 16: SPI Enable Status (SR only) */ +#define SPI_SR_SPIENS (1 << 16) /* Bit 16: SPI Enable Status (SR only) */ + +#define SPI_INT_ALL (0x0000070f) /* SPI Chip Select Registers 0-3 */ diff --git a/arch/arm/src/samv7/chip/sam_usbhs.h b/arch/arm/src/samv7/chip/sam_usbhs.h index b01240fc67f..04c9c4db511 100644 --- a/arch/arm/src/samv7/chip/sam_usbhs.h +++ b/arch/arm/src/samv7/chip/sam_usbhs.h @@ -746,6 +746,9 @@ #define USBHS_CTRL_RDERRE (1 << 4) /* Bit 4: Remote Device Connection Error Interrupt Enable */ #define USBHS_CTRL_FRZCLK (1 << 14) /* Bit 14: Freeze USB Clock */ #define USBHS_CTRL_USBE (1 << 15) /* Bit 15: USBHS Enable */ +#define USBHS_CTRL_UIDE (1 << 24) /* Bit 24: UOTGID Pin Enable */ +# define USBHS_CTRL_UIDE_UIMOD (0 << 24) /* 0=USB mode selected UIMOD bit. */ +# define USBHS_CTRL_UIDE_UOTGID (1 << 24) /* 1=USB mode selected by UOTGID */ #define USBHS_CTRL_UIMOD_MASK (1 << 25) /* Bit 25: USBHS Mode */ # define USBHS_CTRL_UIMOD_HOST (0 << 25) /* 0=Host mode */ # define USBHS_CTRL_UIMOD_DEVICE (1 << 25) /* 1=Device mode */ diff --git a/arch/arm/src/samv7/chip/samv71_memorymap.h b/arch/arm/src/samv7/chip/samv71_memorymap.h index 6e9413d5ef5..917bfd0b5ec 100644 --- a/arch/arm/src/samv7/chip/samv71_memorymap.h +++ b/arch/arm/src/samv7/chip/samv71_memorymap.h @@ -55,7 +55,7 @@ #define SAM_MEMORY_BASE 0x60000000 /* 0x60000000-0x7fffffff: Memories */ #define SAM_QSPIMEM_BASE 0x80000000 /* 0x80000000-0x9fffffff: QSPI memory */ #define SAM_AXIMX_BASE 0xa0000000 /* 0xa0000000-0x9fffffff: AXIMX */ -#define SAM_USBHSRAM_BASE 0xa0010000 /* 0xa0100000-0xa01fffff: USBHS RAM */ +#define SAM_USBHSRAM_BASE 0xa0100000 /* 0xa0100000-0xa01fffff: USBHS RAM */ /* 0xa0200000-0xdfffffff: Reserved */ #define SAM_SYSTEM_BASE 0xe0000000 /* 0xe0000000-0xffffffff: System */ diff --git a/arch/arm/src/samv7/chip/samv71_pinmap.h b/arch/arm/src/samv7/chip/samv71_pinmap.h index 14ba4a8098f..cb9942f2d2a 100644 --- a/arch/arm/src/samv7/chip/samv71_pinmap.h +++ b/arch/arm/src/samv7/chip/samv71_pinmap.h @@ -399,6 +399,7 @@ #define GPIO_SPI0_MOSI (GPIO_PERIPHB | GPIO_CFG_DEFAULT | GPIO_PORT_PIOD | GPIO_PIN21) #define GPIO_SPI0_SPCK (GPIO_PERIPHB | GPIO_CFG_DEFAULT | GPIO_PORT_PIOD | GPIO_PIN22) +#define GPIO_SPI0_NSS (GPIO_PERIPHD | GPIO_CFG_DEFAULT | GPIO_PORT_PIOB | GPIO_PIN2) #define GPIO_SPI0_NPCS0 (GPIO_PERIPHD | GPIO_CFG_DEFAULT | GPIO_PORT_PIOB | GPIO_PIN2) #define GPIO_SPI0_NPCS1_1 (GPIO_PERIPHA | GPIO_CFG_DEFAULT | GPIO_PORT_PIOA | GPIO_PIN31) #define GPIO_SPI0_NPCS1_2 (GPIO_PERIPHB | GPIO_CFG_DEFAULT | GPIO_PORT_PIOD | GPIO_PIN25) @@ -409,6 +410,7 @@ #define GPIO_SPI1_MOSI (GPIO_PERIPHC | GPIO_CFG_DEFAULT | GPIO_PORT_PIOC | GPIO_PIN27) #define GPIO_SPI1_SPCK (GPIO_PERIPHC | GPIO_CFG_DEFAULT | GPIO_PORT_PIOC | GPIO_PIN24) +#define GPIO_SPI1_NSS (GPIO_PERIPHC | GPIO_CFG_DEFAULT | GPIO_PORT_PIOC | GPIO_PIN25) #define GPIO_SPI1_NPCS0 (GPIO_PERIPHC | GPIO_CFG_DEFAULT | GPIO_PORT_PIOC | GPIO_PIN25) #define GPIO_SPI1_NPCS1_1 (GPIO_PERIPHC | GPIO_CFG_DEFAULT | GPIO_PORT_PIOC | GPIO_PIN28) #define GPIO_SPI1_NPCS1_2 (GPIO_PERIPHC | GPIO_CFG_DEFAULT | GPIO_PORT_PIOD | GPIO_PIN0) diff --git a/arch/arm/src/samv7/sam_clockconfig.c b/arch/arm/src/samv7/sam_clockconfig.c index 9d68d4d278c..82b834a53d0 100644 --- a/arch/arm/src/samv7/sam_clockconfig.c +++ b/arch/arm/src/samv7/sam_clockconfig.c @@ -224,30 +224,27 @@ static inline void sam_pmcsetup(void) putreg32(BOARD_CKGR_PLLAR, SAM_PMC_CKGR_PLLAR); sam_pmcwait(PMC_INT_LOCKA); -#ifdef CONFIG_USBDEV +#ifdef CONFIG_SAMV7_USBDEVHS /* UTMI configuration: Enable port0, select 12/16 MHz MAINOSC crystal source */ -#if 0 /* REVISIT: Does this apply only to OHCI? */ - putreg32(UTMI_OHCIICR_RES0, SAM_UTMI_OHCIICR); -#endif - #if BOARD_MAINOSC_FREQUENCY == 12000000 putreg32(UTMI_CKTRIM_FREQ_XTAL12, SAM_UTMI_CKTRIM); -#elif BOARD_MAINOSC_FREQUENCY == 12000000 +#elif BOARD_MAINOSC_FREQUENCY == 16000000 putreg32(UTMI_CKTRIM_FREQ_XTAL16, SAM_UTMI_CKTRIM); #else # error ERROR: Unrecognized MAINSOSC frequency #endif +#ifdef CONFIG_SAMV7_USBDEVHS_LOWPOWER /* Enable UTMI Clocking. The USBHS can work in two modes: * * - Normal mode where High speed, Full speed and Low speed are available. * - Low-power mode where only Full speed and Low speed are available. * - * Only the normal mode is supported by this logic. + * Only the Low-power mode is mode is supported by the logic here. Normal + * mode logic is handled in the function sam_usbclock(). */ -#ifdef CONFIG_SAMV7_USBDEVHS_LOWPOWER /* UTMI Low-power mode, Full/Low Speed mode * * Enable the 48MHz FS Clock. @@ -255,15 +252,6 @@ static inline void sam_pmcsetup(void) putreg32(PMC_USBCLK, SAM_PMC_SCER); -#else - /* UTMI normal mode, High/Full/Low Speed - * - * Disable the 48MHz USB FS Clock. It is not used in this configuration - */ - - putreg32(PMC_USBCLK, SAM_PMC_SCDR); -#endif - /* Select the UTMI PLL as the USB PLL clock input (480MHz) with divider * to get to 48MHz. UPLL output frequency is determined only by the * 12/16MHz crystal selection above. @@ -271,7 +259,6 @@ static inline void sam_pmcsetup(void) regval = PMC_USB_USBS_UPLL; -#ifdef CONFIG_SAMV7_USBDEVHS_LOWPOWER if ((getreg32(SAM_PMC_MCKR) & PMC_MCKR_PLLADIV2) != 0) { /* Divider = 480 Mhz / 2 / 48 Mhz = 5 */ @@ -284,7 +271,6 @@ static inline void sam_pmcsetup(void) regval |= PMC_USB_USBDIV(9); } -#endif putreg32(regval, SAM_PMC_USB); @@ -296,7 +282,9 @@ static inline void sam_pmcsetup(void) /* Wait for LOCKU */ sam_pmcwait(PMC_INT_LOCKU); -#endif + +#endif /* CONFIG_SAMV7_USBDEVHS_LOWPOWER */ +#endif /* CONFIG_SAMV7_USBDEVHS */ /* Switch to the fast clock and wait for MCKRDY */ @@ -405,3 +393,51 @@ void sam_clockconfig(void) sam_enabledefaultmaster(); } + +/**************************************************************************** + * Name: sam_usbclock + * + * Description: + * Enable USBHS clocking. + * + ****************************************************************************/ + +#if defined(CONFIG_SAMV7_USBDEVHS) && !defined(CONFIG_SAMV7_USBDEVHS_LOWPOWER) +void sam_usbclock(void) +{ + uint32_t regval; + + /* Enable UTMI Clocking. The USBHS can work in two modes: + * + * - Normal mode where High speed, Full speed and Low speed are available. + * - Low-power mode where only Full speed and Low speed are available. + * + * Only the normal mode is supported by this logic of this function. Low- + * power mode was handled in the sam_clockconfig(). + */ + + /* UTMI normal mode, High/Full/Low Speed + * + * Disable the 48MHz USB FS Clock. It is not used in this configuration + */ + + putreg32(PMC_USBCLK, SAM_PMC_SCDR); + + /* Select the UTMI PLL as the USB PLL clock input (480MHz) with a divider + * of 1. UPLL output frequency is determined only by the 12/16MHz crystal + * selection set in sam_clockconfig(). + */ + + putreg32(PMC_USB_USBS_UPLL, SAM_PMC_USB); + + /* Enable the UTMI PLL with the maximum start-up time */ + + regval = PMC_CKGR_UCKR_UPLLEN | PMC_CKGR_UCKR_UPLLCOUNT_MAX; + putreg32(regval, SAM_PMC_CKGR_UCKR); + + /* Wait for LOCKU */ + + sam_pmcwait(PMC_INT_LOCKU); +} + +#endif /* CONFIG_SAMV7_USBDEVHS && !CONFIG_SAMV7_USBDEVHS_LOWPOWER */ diff --git a/arch/arm/src/samv7/sam_clockconfig.h b/arch/arm/src/samv7/sam_clockconfig.h index 9f264bc84af..f62d7329041 100644 --- a/arch/arm/src/samv7/sam_clockconfig.h +++ b/arch/arm/src/samv7/sam_clockconfig.h @@ -85,6 +85,20 @@ extern "C" void sam_clockconfig(void); +/**************************************************************************** + * Name: sam_usbclock + * + * Description: + * Enable USBHS clocking. + * + ****************************************************************************/ + +#if defined(CONFIG_SAMV7_USBDEVHS) && !defined(CONFIG_SAMV7_USBDEVHS_LOWPOWER) +void sam_usbclock(void); +#else +# define sam_usbclock() +#endif + #undef EXTERN #if defined(__cplusplus) } diff --git a/arch/arm/src/samv7/sam_config.h b/arch/arm/src/samv7/sam_config.h index 547a6a0bb6b..8aca6fb6fd4 100644 --- a/arch/arm/src/samv7/sam_config.h +++ b/arch/arm/src/samv7/sam_config.h @@ -255,22 +255,60 @@ /* SPI ******************************************************************************/ /* Don't enable SPI peripherals not supported by the chip. */ -#if CHIP_NSPI < 1 +#if SAMV7_NSPI < 1 # undef CONFIG_SAMV7_SPI0 +# undef CONFIG_SAMV7_SPI0_MASTER +# undef CONFIG_SAMV7_SPI0_SLAVE # undef CONFIG_SAMV7_SPI1 -#elif CHIP_NSPI < 2 +# undef CONFIG_SAMV7_SPI1_MASTER +# undef CONFIG_SAMV7_SPI1_SLAVE +#elif SAMV7_NSPI < 2 # undef CONFIG_SAMV7_SPI1 +# undef CONFIG_SAMV7_SPI1_MASTER +# undef CONFIG_SAMV7_SPI1_SLAVE #endif -#ifndef CONFIG_SAMV7_HAVE_SPI +#ifndef CONFIG_SAMV7_SPI # undef CONFIG_SAMV7_SPI0 +# undef CONFIG_SAMV7_SPI0_MASTER +# undef CONFIG_SAMV7_SPI0_SLAVE # undef CONFIG_SAMV7_SPI1 +# undef CONFIG_SAMV7_SPI1_MASTER +# undef CONFIG_SAMV7_SPI1_SLAVE #endif /* Are any SPI peripherals enabled? */ #if !defined(CONFIG_SAMV7_SPI0) && !defined(CONFIG_SAMV7_SPI0) -# undef CONFIG_SAMV7_HAVE_SPI +# undef CONFIG_SAMV7_SPI +# undef CONFIG_SAMV7_SPI_MASTER +# undef CONFIG_SAMV7_SPI_SLAVE +#endif + +/* Each SPI peripheral must be enabled as a MASTER or as a SLAVE */ + +#ifndef CONFIG_SAMV7_SPI_MASTER +# undef CONFIG_SAMV7_SPI0_MASTER +# undef CONFIG_SAMV7_SPI1_MASTER +#endif + +#if !defined(CONFIG_SAMV7_SPI0_MASTER) && !defined(CONFIG_SAMV7_SPI1_MASTER) +# undef CONFIG_SAMV7_SPI_MASTER +#endif + +#ifndef CONFIG_SAMV7_SPI_SLAVE +# undef CONFIG_SAMV7_SPI0_SLAVE +# undef CONFIG_SAMV7_SPI1_SLAVE +#endif + +#if !defined(CONFIG_SAMV7_SPI0_SLAVE) && !defined(CONFIG_SAMV7_SPI1_SLAVE) +# undef CONFIG_SAMV7_SPI_SLAVE +#endif + +#if !defined(CONFIG_SAMV7_SPI_MASTER) && !defined(CONFIG_SAMV7_SPI_SLAVE) +# undef CONFIG_SAMV7_SPI +# undef CONFIG_SAMV7_SPI0 +# undef CONFIG_SAMV7_SPI1 #endif /**************************************************************************** diff --git a/arch/arm/src/samv7/sam_emac.c b/arch/arm/src/samv7/sam_emac.c index d435793d48d..af0065d5514 100644 --- a/arch/arm/src/samv7/sam_emac.c +++ b/arch/arm/src/samv7/sam_emac.c @@ -527,9 +527,9 @@ struct sam_emac_s struct work_s work; /* For deferring work to the work queue */ #endif - /* This holds the information visible to uIP/NuttX */ + /* This holds the information visible to the NuttX network */ - struct net_driver_s dev; /* Interface understood by uIP */ + struct net_driver_s dev; /* Interface understood by the network */ /* Constant and configured attributes of the EMAC */ @@ -1470,8 +1470,9 @@ static int sam_transmit(struct sam_emac_s *priv, int qid) * Function: sam_txpoll * * Description: - * The transmitter is available, check if uIP has any outgoing packets ready - * to send. This is a callback from devif_poll(). devif_poll() may be called: + * 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 @@ -1551,7 +1552,7 @@ static int sam_txpoll(struct net_driver_s *dev) * Function: sam_dopoll * * Description: - * Perform the uIP poll. + * Perform the network poll. * * Parameters: * priv - Reference to the driver state structure @@ -1575,7 +1576,7 @@ static void sam_dopoll(struct sam_emac_s *priv, int qid) if (sam_txfree(priv, qid) > 0) { - /* If we have the descriptor, then poll uIP for new XMIT data. */ + /* If we have the descriptor, then poll the network for new XMIT data. */ (void)devif_poll(dev, sam_txpoll); } @@ -1876,8 +1877,8 @@ static void sam_receive(struct sam_emac_s *priv, int qid) { sam_dumppacket("Received packet", dev->d_buf, dev->d_len); - /* Check if the packet is a valid size for the uIP buffer configuration - * (this should not happen) + /* Check if the packet is a valid size for the network buffer + * configuration (this should not happen) */ if (dev->d_len > CONFIG_NET_ETH_MTU) @@ -2090,7 +2091,7 @@ static void sam_txdone(struct sam_emac_s *priv, int qid) xfrq->txtail = tail; - /* Then poll uIP for new XMIT data */ + /* Then poll the network for new XMIT data */ sam_dopoll(priv, qid); } @@ -2103,7 +2104,7 @@ static void sam_txdone(struct sam_emac_s *priv, int qid) * * Parameters: * priv - Reference to the driver state structure - * quid - Index of the tranfer queue that generated the interrupt + * quid - Index of the transfer queue that generated the interrupt * * Returned Value: * None @@ -2216,7 +2217,7 @@ static void sam_txerr_interrupt(FAR struct sam_emac_s *priv, int qid) sam_putreg(priv, SAM_EMAC_IER_OFFSET, EMAC_RX_INTS); - /* Then poll uIP for new XMIT data */ + /* Then poll the network for new XMIT data */ sam_dopoll(priv, qid); } @@ -2230,7 +2231,7 @@ static void sam_txerr_interrupt(FAR struct sam_emac_s *priv, int qid) * * Parameters: * priv - Reference to the driver state structure - * quid - Index of the tranfer queue that generated the interrupt + * quid - Index of the transfer queue that generated the interrupt * * Returned Value: * None @@ -2567,7 +2568,7 @@ static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv) sam_ifdown(&priv->dev); sam_ifup(&priv->dev); - /* Then poll uIP for new XMIT data */ + /* Then poll the network for new XMIT data */ sam_dopoll(priv, EMAC_QUEUE_0); } @@ -2677,7 +2678,7 @@ static inline void sam_poll_process(FAR struct sam_emac_s *priv) if (sam_txfree(priv, EMAC_QUEUE_0) > 0) { - /* Update TCP timing states and poll uIP for new XMIT data. */ + /* Update TCP timing states and poll the network for new XMIT data. */ (void)devif_timer(dev, sam_txpoll, SAM_POLLHSEC); } @@ -2927,7 +2928,7 @@ static inline void sam_txavail_process(FAR struct sam_emac_s *priv) if (priv->ifup) { - /* Poll uIP for new XMIT data */ + /* Poll the network for new XMIT data */ sam_dopoll(priv, EMAC_QUEUE_0); } diff --git a/arch/arm/src/samv7/sam_irq.c b/arch/arm/src/samv7/sam_irq.c index 9efaaf5ec46..ec6fcee54e2 100644 --- a/arch/arm/src/samv7/sam_irq.c +++ b/arch/arm/src/samv7/sam_irq.c @@ -78,7 +78,16 @@ * Public Data ****************************************************************************/ +/* This is the address of current interrupt saved state data. Used for + * context switching. Only value during interrupt handling. + */ + volatile uint32_t *current_regs; + +/* This is the address of the exception vector table (determined by the + * linker script). + */ + extern uint32_t _vectors[]; /**************************************************************************** @@ -378,16 +387,21 @@ void up_irqinitialize(void) } #endif - /* Set up the vector table address. - * - * If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ -#if defined(CONFIG_ARCH_RAMVECTORS) up_ramvec_initialize(); -#elif defined(CONFIG_SAM_BOOTLOADER) - putreg32((uint32_t)_vectors, NVIC_VECTAB); #endif /* Set all interrupts (and exceptions) to the default priority */ diff --git a/arch/arm/src/samv7/sam_mcan.c b/arch/arm/src/samv7/sam_mcan.c old mode 100644 new mode 100755 index 29cad97aee4..45acfe49721 --- a/arch/arm/src/samv7/sam_mcan.c +++ b/arch/arm/src/samv7/sam_mcan.c @@ -122,6 +122,10 @@ # define MCAN_ALIGN ARMV7M_DCACHE_LINESIZE # define MCAN_ALIGN_MASK (MCAN_ALIGN-1) # define MCAN_ALIGN_UP(n) (((n) + MCAN_ALIGN_MASK) & ~MCAN_ALIGN_MASK) + +# ifndef CONFIG_ARMV7M_DCACHE_WRITETHROUGH +# warning !!! This driver will not work without CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y!!! +# endif #endif /* MCAN0 Configuration ******************************************************/ @@ -809,6 +813,15 @@ enum sam_canmode_e MCAN_FD_BSW_MODE = 2 /* CAN FD operation with bit rate switching */ }; +/* CAN driver state */ + +enum can_state_s +{ + MCAN_STATE_UNINIT = 0, /* Not yet initialized */ + MCAN_STATE_RESET, /* Initialized, reset state */ + MCAN_STATE_SETUP, /* can_setup() has been called */ +}; + /* This structure describes the MCAN message RAM layout */ struct sam_msgram_s @@ -869,22 +882,22 @@ struct sam_config_s struct sam_mcan_s { const struct sam_config_s *config; /* The constant configuration */ - bool initialized; /* True: Device has been initialized */ + uint8_t state; /* See enum can_state_s */ #ifdef CONFIG_CAN_EXTID - uint8_t nextalloc; /* Number of allocated extended filters */ -#else - uint8_t nstdalloc; /* Number of allocated standard filters */ + uint8_t nextalloc; /* Number of allocated extended filters */ #endif + uint8_t nstdalloc; /* Number of allocated standard filters */ sem_t locksem; /* Enforces mutually exclusive access */ sem_t txfsem; /* Used to wait for TX FIFO availability */ + uint32_t btp; /* Current bit timing */ + uint32_t fbtp; /* Current fast bit timing */ uint32_t rxints; /* Configured RX interrupts */ uint32_t txints; /* Configured TX interrupts */ #ifdef CONFIG_CAN_EXTID uint32_t extfilters[2]; /* Extended filter bit allocator. 2*32=64 */ -#else - uint32_t stdfilters[4]; /* Standard filter bit allocator. 4*32=128 */ #endif + uint32_t stdfilters[4]; /* Standard filter bit allocator. 4*32=128 */ #ifdef CONFIG_SAMV7_MCAN_REGDEBUG uintptr_t regaddr; /* Last register address read */ @@ -914,7 +927,7 @@ static void mcan_dev_lock(FAR struct sam_mcan_s *priv); #define mcan_dev_unlock(priv) sem_post(&priv->locksem) static void mcan_buffer_reserve(FAR struct sam_mcan_s *priv); -#define mcan_buffer_release(priv) sem_post(&priv->txfsem) +static void mcan_buffer_release(FAR struct sam_mcan_s *priv); /* MCAN helpers */ @@ -925,13 +938,13 @@ static uint8_t mcan_bytes2dlc(FAR struct sam_mcan_s *priv, uint8_t nbytes); #ifdef CONFIG_CAN_EXTID static int mcan_add_extfilter(FAR struct sam_mcan_s *priv, - FAR struct canioc_stdfilter_s *extconfig); + FAR struct canioc_extfilter_s *extconfig); static int mcan_del_extfilter(FAR struct sam_mcan_s *priv, int ndx); -#else +#endif static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, FAR struct canioc_stdfilter_s *stdconfig); static int mcan_del_stdfilter(FAR struct sam_mcan_s *priv, int ndx); -#endif + /* CAN driver methods */ static void mcan_reset(FAR struct can_dev_s *dev); @@ -952,6 +965,7 @@ static bool mcan_txempty(FAR struct can_dev_s *dev); static bool mcan_dedicated_rxbuffer_available(FAR struct sam_mcan_s *priv, int bufndx); #endif +static void mcan_error(FAR struct can_dev_s *dev, uint32_t status); static void mcan_receive(FAR struct can_dev_s *dev, FAR uint32_t *rxbuffer, unsigned long nwords); static void mcan_interrupt(FAR struct can_dev_s *dev); @@ -1385,8 +1399,9 @@ static void mcan_dev_lock(FAR struct sam_mcan_s *priv) * Name: mcan_buffer_reserve * * Description: - * Take the semaphore that indicates the availability of a TX FIFOQ - * buffer, handling any exceptional conditions + * Take the semaphore, decrementing the semaphore count to indicate that + * one fewer TX FIFOQ buffer is available. Handles any exceptional + * conditions. * * Input Parameters: * priv - A reference to the MCAN peripheral state @@ -1394,10 +1409,19 @@ static void mcan_dev_lock(FAR struct sam_mcan_s *priv) * Returned Value: * None * + * Assumptions: + * Called only non-interrupt logic via mcan_write(). We do not have + * exclusive access to the MCAN hardware and interrupts are not disabled. + * mcan_write() does lock the scheduler for reasons noted below. + * ****************************************************************************/ static void mcan_buffer_reserve(FAR struct sam_mcan_s *priv) { + irqstate_t flags; + uint32_t txfqs1; + uint32_t txfqs2; + int sval; int ret; /* Wait until we successfully get the semaphore. EINTR is the only @@ -1407,12 +1431,147 @@ static void mcan_buffer_reserve(FAR struct sam_mcan_s *priv) do { + /* We take some extra precautions here because it is possible that on + * certain error conditions, the semaphore count could get out of + * phase with the actual count of elements in the TX FIFO (I have + * never seen this happen, however. My paranoia). + * + * An missed TX interrupt could cause the semaphore count to fail to + * be incremented and, hence, to be too low. + */ + + for(;;) + { + /* Get the current queue status and semaphore count. */ + + flags = irqsave(); + txfqs1 = mcan_getreg(priv, SAM_MCAN_TXFQS_OFFSET); + (void)sem_getvalue(&priv->txfsem, &sval); + txfqs2 = mcan_getreg(priv, SAM_MCAN_TXFQS_OFFSET); + + /* If the semaphore count and the TXFQS samples are in + * sync, then break out of the look with interrupts + * disabled. + */ + + if (txfqs1 == txfqs2) + { + break; + } + + /* Otherwise, re-enable interrupts to interrupts that may + * resynchronize, the semaphore count and try again. + */ + + irqrestore(flags); + } + + /* We only have one useful bit of information in the TXFQS: + * Is the TX FIFOQ full or not? We can only do limited checks + * with that single bit of information. + */ + + if ((txfqs1 & MCAN_TXFQS_TFQF) != 0) + { + /* The TX FIFOQ is full. The semaphore count should then be + * less than or equal to zero. If it is greater than zero, + * then reinitialize it to 0. + */ + + if (sval > 0) + { + candbg("ERROR: TX FIFOQ full but txfsem is %d\n", sval); + sem_init(&priv->txfsem, 0, 0); + } + } + + /* The FIFO is not full so the semaphore count should be greater + * than zero. If it is not, then we have missed a call to + * mcan_buffer_release(0). + * + * NOTE: Since there is no mutual exclusion, it might be possible + * that mcan_write() could be re-entered AFTER taking the semaphore + * and dropping the count to zero, but BEFORE adding the message + * to the TX FIFOQ. That corner case is handled in mcan_write() by + * locking the scheduler. + */ + + else if (sval <= 0) + { + candbg("ERROR: TX FIFOQ not full but txfsem is %d\n", sval); + + /* Less than zero means that another thread is waiting */ + + if (sval < 0) + { + /* Bump up the count by one and try again */ + + sem_post(&priv->txfsem); + irqrestore(flags); + continue; + } + + /* Exactly zero but the FIFO is not full. Just return without + * decrementing the count. + */ + + irqrestore(flags); + return; + } + + /* The semaphore value is reasonable. Wait for the next TC interrupt. */ + ret = sem_wait(&priv->txfsem); + irqrestore(flags); DEBUGASSERT(ret == 0 || errno == EINTR); } while (ret < 0); } +/**************************************************************************** + * Name: mcan_buffer_release + * + * Description: + * Release the semaphore, increment the semaphore count to indicate that + * one more TX FIFOQ buffer is available. + * + * Input Parameters: + * priv - A reference to the MCAN peripheral state + * + * Returned Value: + * None + * + * Assumptions: + * This function is called only from the interrupt level in response to the + * complete of a transmission. + * + ****************************************************************************/ + +static void mcan_buffer_release(FAR struct sam_mcan_s *priv) +{ + int sval; + + /* We take some extra precautions here because it is possible that on + * certain error conditions, the semaphore count could get out of phase + * with the actual count of elements in the TX FIFO (I have never seen + * this happen, however. My paranoia). + * + * An extra TC interrupt could cause the count to be incremented too + * many times. + */ + + (void)sem_getvalue(&priv->txfsem, &sval); + if (sval < priv->config->ntxfifoq) + { + sem_post(&priv->txfsem); + } + else + { + candbg("ERROR: txfsem would increment beyond %d\n", + priv->config->ntxfifoq); + } +} + /**************************************************************************** * Name: mcan_dlc2bytes * @@ -1554,7 +1713,7 @@ static uint8_t mcan_bytes2dlc(FAR struct sam_mcan_s *priv, uint8_t nbytes) #ifdef CONFIG_CAN_EXTID static int mcan_add_extfilter(FAR struct sam_mcan_s *priv, - FAR struct canioc_stdfilter_s *extconfig) + FAR struct canioc_extfilter_s *extconfig) { FAR const struct sam_config_s *config; FAR uint32_t *extfilter; @@ -1745,7 +1904,6 @@ static int mcan_del_extfilter(FAR struct sam_mcan_s *priv, int ndx) * ****************************************************************************/ -#ifndef CONFIG_CAN_EXTID static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, FAR struct canioc_stdfilter_s *stdconfig) { @@ -1846,7 +2004,6 @@ static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, mcan_dev_unlock(priv); return -EAGAIN; } -#endif /**************************************************************************** * Name: mcan_del_stdfilter @@ -1864,7 +2021,6 @@ static int mcan_add_stdfilter(FAR struct sam_mcan_s *priv, * ****************************************************************************/ -#ifndef CONFIG_CAN_EXTID static int mcan_del_stdfilter(FAR struct sam_mcan_s *priv, int ndx) { FAR const struct sam_config_s *config; @@ -1915,7 +2071,6 @@ static int mcan_del_stdfilter(FAR struct sam_mcan_s *priv, int ndx) mcan_dev_unlock(priv); return OK; } -#endif /**************************************************************************** * Name: mcan_reset @@ -1955,9 +2110,19 @@ static void mcan_reset(FAR struct can_dev_s *dev) mcan_putreg(priv, SAM_MCAN_IE_OFFSET, 0); mcan_putreg(priv, SAM_MCAN_TXBTIE_OFFSET, 0); + /* Make sure that all buffers are released. + * + * REVISIT: What if a thread is waiting for a buffer? The following + * will not wake up any waiting threads. + */ + + sem_destroy(&priv->txfsem); + sem_init(&priv->txfsem, 0, config->ntxfifoq); + /* Disable peripheral clocking to the MCAN controller */ sam_disableperiph1(priv->config->pid); + priv->state = MCAN_STATE_RESET; mcan_dev_unlock(priv); } @@ -2027,6 +2192,7 @@ static int mcan_setup(FAR struct can_dev_s *dev) /* Enable receive interrupts */ + priv->state = MCAN_STATE_SETUP; mcan_rxint(dev, true); mcan_dumpregs(priv, "After receive setup"); @@ -2072,19 +2238,24 @@ static void mcan_shutdown(FAR struct can_dev_s *dev) mcan_dev_lock(priv); - /* Disable the MCAN interrupts */ + /* Disable MCAN interrupts at the NVIC */ up_disable_irq(config->irq0); up_disable_irq(config->irq1); + /* Disable all interrupts from the MCAN peripheral */ + + mcan_putreg(priv, SAM_MCAN_IE_OFFSET, 0); + mcan_putreg(priv, SAM_MCAN_TXBTIE_OFFSET, 0); + /* Detach the MCAN interrupt handler */ irq_detach(config->irq0); irq_detach(config->irq1); - /* And reset the hardware */ + /* Disable peripheral clocking to the MCAN controller */ - mcan_reset(dev); + sam_disableperiph1(priv->config->pid); mcan_dev_unlock(priv); } @@ -2200,6 +2371,125 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) switch (cmd) { + /* CANIOC_GET_BITTIMING: + * Description: Return the current bit timing settings + * Argument: A pointer to a write-able instance of struct + * canioc_bittiming_s in which current bit timing values + * will be returned. + * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) + * is returned with the errno variable set to indicate the + * nature of the error. + * Dependencies: None + */ + + case CANIOC_GET_BITTIMING: + { + FAR struct canioc_bittiming_s *bt = + (FAR struct canioc_bittiming_s *)arg; + uint32_t regval; + uint32_t brp; + + DEBUGASSERT(bt != NULL); + + regval = mcan_getreg(priv, SAM_MCAN_BTP_OFFSET); + bt->bt_sjw = ((regval & MCAN_BTP_SJW_MASK) >> MCAN_BTP_SJW_SHIFT) + 1; + bt->bt_tseg1 = ((regval & MCAN_BTP_TSEG1_MASK) >> MCAN_BTP_TSEG1_SHIFT) + 1; + bt->bt_tseg2 = ((regval & MCAN_BTP_TSEG2_MASK) >> MCAN_BTP_TSEG2_SHIFT) + 1; + + brp = ((regval & MCAN_BTP_BRP_MASK) >> MCAN_BTP_BRP_SHIFT) + 1; + bt->bt_baud = SAMV7_MCANCLK_FREQUENCY / brp / + (bt->bt_tseg1 + bt->bt_tseg2 + 1); + ret = OK; + } + break; + + /* CANIOC_SET_BITTIMING: + * Description: Set new current bit timing values + * Argument: A pointer to a read-able instance of struct + * canioc_bittiming_s in which the new bit timing values + * are provided. + * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) + * is returned with the errno variable set to indicate the + * nature of the error. + * Dependencies: None + * + * REVISIT: There is probably a limitation here: If there are multiple + * threads trying to send CAN packets, when one of these threads reconfigures + * the bitrate, the MCAN hardware will be reset and the context of operation + * will be lost. Hence, this IOCTL can only safely be executed in quiescent + * time periods. + */ + + case CANIOC_SET_BITTIMING: + { + FAR const struct canioc_bittiming_s *bt = + (FAR const struct canioc_bittiming_s *)arg; + irqstate_t flags; + uint32_t brp; + uint32_t tseg1; + uint32_t tseg2; + uint32_t sjw; + uint32_t ie; + uint8_t state; + + DEBUGASSERT(bt != NULL); + DEBUGASSERT(bt->bt_baud < SAMV7_MCANCLK_FREQUENCY); + DEBUGASSERT(bt->bt_sjw > 0 && bt->bt_sjw <= 16); + DEBUGASSERT(bt->bt_tseg1 > 0 && bt->bt_tseg1 <= 16); + DEBUGASSERT(bt->bt_tseg2 > 1 && bt->bt_tseg2 <= 64); + + /* Extract bit timing data */ + + tseg1 = bt->bt_tseg1 - 1; + tseg2 = bt->bt_tseg2 - 1; + sjw = bt->bt_sjw - 1; + + brp = (uint32_t) + (((float) SAMV7_MCANCLK_FREQUENCY / + ((float)(tseg1 + tseg2 + 3) * (float)bt->bt_baud)) - 1); + + /* Save the value of the new bit timing register */ + + flags = irqsave(); + priv->btp = MCAN_BTP_BRP(brp) | MCAN_BTP_TSEG1(tseg1) | + MCAN_BTP_TSEG2(tseg2) | MCAN_BTP_SJW(sjw); + + /* We need to reset to instantiate the new timing. Save + * current state information so that recover to this + * state. + */ + + ie = mcan_getreg(priv, SAM_MCAN_IE_OFFSET); + state = priv->state; + + /* Reset the MCAN */ + + mcan_reset(dev); + ret = OK; + + /* If we have previously been setup, then setup again */ + + if (state == MCAN_STATE_SETUP) + { + ret = mcan_setup(dev); + } + + /* We we have successfully re-initialized, then restore the + * interrupt state. + * + * REVISIT: Since the hardware was reset, any pending TX + * activity was lost. Should we disable TX interrupts? + */ + + if (ret == OK) + { + mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie & ~priv->txints); + } + + irqrestore(flags); + } + break; + #ifdef CONFIG_CAN_EXTID /* CANIOC_ADD_EXTFILTER: * Description: Add an address filter for a extended 29 bit @@ -2232,8 +2522,8 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) ret = mcan_del_extfilter(priv, (int)arg); } break; +#endif -#else /* CANIOC_ADD_STDFILTER: * Description: Add an address filter for a standard 11 bit * address. @@ -2265,7 +2555,6 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) ret = mcan_del_stdfilter(priv, (int)arg); } break; -#endif /* Unsupported/unrecognized command */ @@ -2357,15 +2646,22 @@ static int mcan_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg) * not full and cannot become full at least until we add our packet to * the FIFO. * + * We can't get exclusive access to MAN resource here because that + * lock the MCAN while we wait for a free buffer. Instead, the + * scheduler is locked here momentarily. See discussion in + * mcan_buffer_reserve() for an explanation. + * * REVISIT: This needs to be extended in order to handler case where * the MCAN device was opened O_NONBLOCK. */ + sched_lock(); mcan_buffer_reserve(priv); /* Get exclusive access to the MCAN peripheral */ mcan_dev_lock(priv); + sched_unlock(); /* Get our reserved Tx FIFO/queue put index */ @@ -2387,15 +2683,19 @@ static int mcan_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg) */ #ifdef CONFIG_CAN_EXTID - DEBUGASSERT(msg->cm_hdr.ch_extid); - DEBUGASSERT(msg->cm_hdr.ch_id <= CAN_MAX_EXTMSGID); + if (msg->cm_hdr.ch_extid) + { + DEBUGASSERT(msg->cm_hdr.ch_id <= CAN_MAX_EXTMSGID); - regval = BUFFER_R0_EXTID(msg->cm_hdr.ch_id) | BUFFER_R0_XTD; -#else - DEBUGASSERT(msg->cm_hdr.ch_id <= CAN_MAX_STDMSGID); - - regval = BUFFER_R0_STDID(msg->cm_hdr.ch_id); + regval = BUFFER_R0_EXTID(msg->cm_hdr.ch_id) | BUFFER_R0_XTD; + } + else #endif + { + DEBUGASSERT(msg->cm_hdr.ch_id <= CAN_MAX_STDMSGID); + + regval = BUFFER_R0_STDID(msg->cm_hdr.ch_id); + } if (msg->cm_hdr.ch_rtr) { @@ -2443,6 +2743,17 @@ static int mcan_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg) mcan_putreg(priv, SAM_MCAN_TXBAR_OFFSET, (1 << ndx)); + /* Report that the TX transfer is complete to the upper half logic. Of + * course, the transfer is not complete, but this early notification + * allows the upper half logic to free resources sooner. + * + * REVISTI: Should we disable interrupts? can_txdone() was designed to + * be called from and interrupt handler and, hence, may be unsafe when + * called from the tasking level. + */ + + can_txdone(dev); + mcan_dev_unlock(priv); return OK; } @@ -2591,6 +2902,108 @@ bool mcan_dedicated_rxbuffer_available(FAR struct sam_mcan_s *priv, int bufndx) } #endif +/**************************************************************************** + * Name: mcan_error + * + * Description: + * Report a CAN error + * + * Input Parameters: + * dev - CAN-common state data + * status - Interrupt status with error bits set + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mcan_error(FAR struct can_dev_s *dev, uint32_t status) +{ + struct can_hdr_s hdr; + uint16_t errbits; + int ret; + + /* Encode error bits */ + + errbits = 0; + if ((status & (MCAN_INT_ELO | MCAN_INT_EW)) != 0) + { + errbits |= CAN_ERROR_SYSTEM; + } + + if ((status & (MCAN_INT_RF0L | MCAN_INT_RF1L)) != 0) + { + errbits |= CAN_ERROR_RXLOST; + } + + if ((status & MCAN_INT_TEFL) != 0) + { + errbits |= CAN_ERROR_TXLOST; + } + + if ((status & (MCAN_INT_MRAF | MCAN_INT_BO)) != 0) + { + errbits |= CAN_ERROR_ACCESS; + } + + if ((status & MCAN_INT_TOO) != 0) + { + errbits |= CAN_ERROR_TIMEOUT; + } + + if ((status & MCAN_INT_EP) != 0) + { + errbits |= CAN_ERROR_PASSIVE; + } + + if ((status & MCAN_INT_CRCE) != 0) + { + errbits |= CAN_ERROR_CRC; + } + + if ((status & MCAN_INT_BE) != 0) + { + errbits |= CAN_ERROR_BIT; + } + + if ((status & MCAN_INT_ACKE) != 0) + { + errbits |= CAN_ERROR_ACK; + } + + if ((status & MCAN_INT_FOE) != 0) + { + errbits |= CAN_ERROR_FORMAT; + } + + if ((status & MCAN_INT_STE) != 0) + { + errbits |= CAN_ERROR_STUFF; + } + + if (errbits != 0) + { + /* Format the CAN header for the error report. */ + + hdr.ch_id = errbits; + hdr.ch_dlc = 0; + hdr.ch_rtr = 0; + hdr.ch_error = 1; +#ifdef CONFIG_CAN_EXTID + hdr.ch_extid = 0; +#endif + hdr.ch_unused = 0; + + /* And provide the error report to the upper half logic */ + + ret = can_receive(dev, &hdr, NULL); + if (ret < 0) + { + canlldbg("ERROR: can_receive failed: %d\n", ret); + } + } +} + /**************************************************************************** * Name: mcan_receive * @@ -2627,9 +3040,10 @@ static void mcan_receive(FAR struct can_dev_s *dev, FAR uint32_t *rxbuffer, canregdbg("R0: %08x\n", regval); hdr.ch_rtr = 0; -#ifdef CONFIG_CAN_EXTID + hdr.ch_error = 0; hdr.ch_unused = 0; +#ifdef CONFIG_CAN_EXTID if ((regval & BUFFER_R0_XTD) != 0) { /* Save the extended ID of the newly received message */ @@ -2696,9 +3110,6 @@ static void mcan_interrupt(FAR struct can_dev_s *dev) uint32_t regval; unsigned int nelem; unsigned int ndx; -#ifdef CONFIG_DEBUG - int sval; -#endif bool handled; DEBUGASSERT(priv && priv->config); @@ -2725,6 +3136,10 @@ static void mcan_interrupt(FAR struct can_dev_s *dev) /* Clear the error indications */ mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_CMNERR_INTS); + + /* Report errors */ + + mcan_error(dev, pending & MCAN_CMNERR_INTS); handled = true; } @@ -2738,13 +3153,22 @@ static void mcan_interrupt(FAR struct can_dev_s *dev) mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_TXERR_INTS); + /* Report errors */ + + mcan_error(dev, pending & MCAN_TXERR_INTS); + /* REVISIT: Will MCAN_INT_TC also be set in the event of * a transmission error? Each write must conclude with a - * call to can_txdone(), whether or not the write was - * successful. + * call to man_buffer_release(), whether or not the write + * was successful. + * + * Here we force transmit complete processing just in case. + * This could have the side effect of pushing the semaphore + * count up to high. */ - handled = true; + pending |= MCAN_INT_TC; + handled = true; } /* Check for successful completion of a transmission */ @@ -2765,15 +3189,6 @@ static void mcan_interrupt(FAR struct can_dev_s *dev) */ mcan_buffer_release(priv); - -#ifdef CONFIG_DEBUG - (void)sem_getvalue(&priv->txfsem, &sval); - DEBUGASSERT(sval <= config->ntxfifoq); -#endif - - /* Report that the TX transfer is complete to the upper half logic */ - - can_txdone(dev); handled = true; } else if ((pending & priv->txints) != 0) @@ -2840,6 +3255,11 @@ static void mcan_interrupt(FAR struct can_dev_s *dev) /* Clear the error indications */ mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_RXERR_INTS); + + /* Report errors */ + + mcan_error(dev, pending & MCAN_TXERR_INTS); + handled = true; } /* Clear the RX FIFO1 new message interrupt */ @@ -2871,7 +3291,7 @@ static void mcan_interrupt(FAR struct can_dev_s *dev) /* Handle the newly received message in FIFO1 */ - ndx = (regval & MCAN_RXF1S_F1GI_MASK) >> MCAN_RXF1S_F1GI_SHIFT; + ndx = (regval & MCAN_RXF1S_F1GI_MASK) >> MCAN_RXF1S_F1GI_SHIFT; if ((regval & MCAN_RXF0S_RF0L) != 0) { @@ -3066,8 +3486,8 @@ static int mcan_hw_initialize(struct sam_mcan_s *priv) /* Configure MCAN bit timing */ - mcan_putreg(priv, SAM_MCAN_BTP_OFFSET, config->btp); - mcan_putreg(priv, SAM_MCAN_FBTP_OFFSET, config->fbtp); + mcan_putreg(priv, SAM_MCAN_BTP_OFFSET, priv->btp); + mcan_putreg(priv, SAM_MCAN_FBTP_OFFSET, priv->fbtp); /* Configure message RAM starting addresses and sizes. */ @@ -3335,19 +3755,27 @@ FAR struct can_dev_s *sam_mcan_initialize(int port) /* Is this the first time that we have handed out this device? */ - if (!priv->initialized) + if (priv->state == MCAN_STATE_UNINIT) { /* Yes, then perform one time data initialization */ memset(priv, 0, sizeof(struct sam_mcan_s)); - priv->config = config; - priv->initialized = true; + priv->config = config; + + /* Set the initial bit timing. This might change subsequently + * due to IOCTL command processing. + */ + + priv->btp = config->btp; + priv->fbtp = config->fbtp; + + /* Initialize semaphores */ sem_init(&priv->locksem, 0, 1); sem_init(&priv->txfsem, 0, config->ntxfifoq); - dev->cd_ops = &g_mcanops; - dev->cd_priv = (FAR void *)priv; + dev->cd_ops = &g_mcanops; + dev->cd_priv = (FAR void *)priv; /* And put the hardware in the initial state */ diff --git a/arch/arm/src/samv7/sam_qspi.c b/arch/arm/src/samv7/sam_qspi.c new file mode 100644 index 00000000000..f574e04ca81 --- /dev/null +++ b/arch/arm/src/samv7/sam_qspi.c @@ -0,0 +1,1739 @@ +/**************************************************************************** + * arch/arm/src/samv7/sam_qspi.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Authors: 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 +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "up_internal.h" +#include "up_arch.h" +#include "cache.h" + +#include "sam_gpio.h" +#include "sam_xdmac.h" +#include "sam_periphclks.h" +#include "sam_qspi.h" +#include "chip/sam_pmc.h" +#include "chip/sam_xdmac.h" +#include "chip/sam_qspi.h" +#include "chip/sam_pinmap.h" + +#ifdef CONFIG_SAMV7_QSPI + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_SAMV7_QSPI_DLYBS +# define CONFIG_SAMV7_QSPI_DLYBS 0 +#endif + +#ifndef CONFIG_SAMV7_QSPI_DLYBCT +# define CONFIG_SAMV7_QSPI_DLYBCT 0 +#endif + +/* When QSPI DMA is enabled, small DMA transfers will still be performed by + * polling logic. But we need a threshold value to determine what is small. + * That value is provided by CONFIG_SAMV7_QSPI_DMATHRESHOLD. + */ + +#ifndef CONFIG_SAMV7_QSPI_DMATHRESHOLD +# define CONFIG_SAMV7_QSPI_DMATHRESHOLD 4 +#endif + +#ifndef CONFIG_SAMV7_XDMAC +# undef CONFIG_SAMV7_QSPI_DMA +#endif + +#ifdef CONFIG_SAMV7_QSPI_DMA +# define SAMV7_QSPI0_DMA true +#endif + +#ifndef CONFIG_SAMV7_QSPI_DMA +# undef CONFIG_SAMV7_QSPI_DMADEBUG +#endif + +/* QSPI interrupts are not used */ + +#undef QSPI_USE_INTERRUPTS + +/* Clocking *****************************************************************/ +/* The QSPI Baud rate clock is generated by dividing the peripheral clock by + * a value between 1 and 255 + */ + +#define SAM_QSPI_CLOCK BOARD_MCK_FREQUENCY /* Frequency of the main clock */ + +/* DMA timeout. The value is not critical; we just don't want the system to + * hang in the event that a DMA does not finish. This is set to + */ + +#define DMA_TIMEOUT_MS (800) +#define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS) + +/* QSPI memory synchronization */ + +#define MEMORY_SYNC() do { ARM_DSB();ARM_ISB(); } while (0) + +/* Debug *******************************************************************/ +/* Check if QSPI debug is enabled (non-standard.. no support in + * include/debug.h + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_SPI +# undef CONFIG_SAMV7_QSPI_DMADEBUG +# undef CONFIG_SAMV7_QSPI_REGDEBUG +#endif + +#ifndef CONFIG_DEBUG_DMA +# undef CONFIG_SAMV7_QSPI_DMADEBUG +#endif + +#ifdef CONFIG_DEBUG_SPI +# define qspidbg lldbg +# ifdef CONFIG_DEBUG_VERBOSE +# define qspivdbg lldbg +# else +# define qspivdbg(x...) +# endif +#else +# define qspidbg(x...) +# define qspivdbg(x...) +#endif + +#define DMA_INITIAL 0 +#define DMA_AFTER_SETUP 1 +#define DMA_AFTER_START 2 +#define DMA_CALLBACK 3 +#define DMA_TIMEOUT 3 +#define DMA_END_TRANSFER 4 +#define DMA_NSAMPLES 5 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The state of the QSPI controller. + * + * NOTE: Currently the SAMV7 supports only a single QSPI peripheral. Logic + * here is designed to support multiple QSPI peripherals. + */ + +struct sam_qspidev_s +{ + struct qspi_dev_s qspi; /* Externally visible part of the QSPI interface */ +#ifdef QSPI_USE_INTERRUPTS + xcpt_t handler; /* Interrupt handler */ +#endif + uint32_t base; /* QSPI controller register base address */ + uint32_t frequency; /* Requested clock frequency */ + uint32_t actual; /* Actual clock frequency */ + uint8_t mode; /* Mode 0,1,2,3 */ + uint8_t nbits; /* Width of word in bits (8 to 16) */ + uint8_t intf; /* QSPI controller number (0) */ +#ifdef QSPI_USE_INTERRUPTS + uint8_t irq; /* Interrupt number */ +#endif + bool initialized; /* TRUE: Controller has been initialized */ + sem_t exclsem; /* Assures mutually exclusive access to QSPI */ + +#ifdef CONFIG_SAMV7_QSPI_DMA + bool candma; /* DMA is supported */ + uint8_t rxintf; /* RX hardware interface number */ + uint8_t txintf; /* TX hardware interface number */ + sem_t dmawait; /* Used to wait for DMA completion */ + WDOG_ID dmadog; /* Watchdog that handles DMA timeouts */ + int result; /* DMA result */ + DMA_HANDLE dmach; /* QSPI DMA handle */ +#endif + + /* Debug stuff */ + +#ifdef CONFIG_SAMV7_QSPI_DMADEBUG + struct sam_dmaregs_s dmaregs[DMA_NSAMPLES]; +#endif + +#ifdef CONFIG_SAMV7_QSPI_REGDEBUG + bool wrlast; /* Last was a write */ + uint32_t addresslast; /* Last address */ + uint32_t valuelast; /* Last value */ + int ntimes; /* Number of times */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Helpers */ + +#ifdef CONFIG_SAMV7_QSPI_REGDEBUG +static bool qspi_checkreg(struct sam_qspidev_s *priv, bool wr, + uint32_t value, uint32_t address); +#else +# define qspi_checkreg(priv,wr,value,address) (false) +#endif + +static inline uint32_t qspi_getreg(struct sam_qspidev_s *priv, + unsigned int offset); +static inline void qspi_putreg(struct sam_qspidev_s *priv, uint32_t value, + unsigned int offset); + +#if defined(CONFIG_DEBUG_SPI) && defined(CONFIG_DEBUG_VERBOSE) +static void qspi_dumpregs(struct sam_qspidev_s *priv, const char *msg); +#else +# define qspi_dumpregs(priv,msg) +#endif + +/* DMA support */ + +#ifdef CONFIG_SAMV7_QSPI_DMA +#ifdef CONFIG_SAMV7_QSPI_DMADEBUG +# define qspi_dma_sample(s,i) sam_dmasample((s)->dmach, &(s)->dmaregs[i]) +static void qspi_dma_sampleinit(struct sam_qspidev_s *priv); +static void qspi_dma_sampledone(struct sam_qspidev_s *priv); + +#else +# define qspi_dma_sample(s,i) +# define qspi_dma_sampleinit(s) +# define qspi_dma_sampledone(s) + +#endif + +static void qspi_dma_callback(DMA_HANDLE handle, void *arg, int result); +static inline uintptr_t qspi_regaddr(struct sam_qspidev_s *priv, + unsigned int offset); +#endif + +static int qspi_memory_enable(struct sam_qspidev_s *priv, + struct qspi_meminfo_s *meminfo); +#ifdef CONFIG_SAMV7_QSPI_DMA +static int qspi_memory_dma(struct sam_qspidev_s *priv, + struct qspi_meminfo_s *meminfo); +#endif + +static int qspi_memory_nodma(struct sam_qspidev_s *priv, + struct qspi_meminfo_s *meminfo); + +/* Interrupts */ + +#ifdef QSPI_USE_INTERRUPTS +static int qspi_interrupt(struct sam_qspidev_s *priv); +#ifdef CONFIG_SAMV7_QSPI +static int qspi0_interrupt(int irq, void *context); +#endif +#endif + +/* QSPI methods */ + +static int qspi_lock(struct qspi_dev_s *dev, bool lock); +static uint32_t qspi_setfrequency(struct qspi_dev_s *dev, uint32_t frequency); +static void qspi_setmode(struct qspi_dev_s *dev, enum qspi_mode_e mode); +static void qspi_setbits(struct qspi_dev_s *dev, int nbits); +static int qspi_command(struct qspi_dev_s *dev, + struct qspi_cmdinfo_s *cmdinfo); +static int qspi_memory(struct qspi_dev_s *dev, + struct qspi_meminfo_s *meminfo); + +/* Initialization */ + +static int qspi_hw_initialize(struct sam_qspidev_s *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_SAMV7_QSPI +/* QSPI0 driver operations */ + +static const struct qspi_ops_s g_qspi0ops = +{ + .lock = qspi_lock, + .setfrequency = qspi_setfrequency, + .setmode = qspi_setmode, + .setbits = qspi_setbits, + .command = qspi_command, + .memory = qspi_memory, +}; + +/* This is the overall state of the QSPI0 controller */ + +static struct sam_qspidev_s g_qspi0dev = +{ + .qspi = + { + .ops = &g_qspi0ops, + }, + .base = SAM_QSPI_BASE, +#ifdef QSPI_USE_INTERRUPTS + .handler = qspi0_interrupt, +#endif + .intf = 0, +#ifdef QSPI_USE_INTERRUPTS + .irq = SAM_IRQ_QSPI, +#endif +#ifdef CONFIG_SAMV7_QSPI_DMA + .candma = SAMV7_QSPI0_DMA, + .rxintf = XDMACH_QSPI_RX, + .txintf = XDMACH_QSPI_TX, +#endif +}; +#endif /* CONFIG_SAMV7_QSPI */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: qspi_checkreg + * + * Description: + * Check if the current register access is a duplicate of the preceding. + * + * Input Parameters: + * value - 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_SAMV7_QSPI_REGDEBUG +static bool qspi_checkreg(struct sam_qspidev_s *priv, bool wr, uint32_t value, + uint32_t address) +{ + if (wr == priv->wrlast && /* Same kind of access? */ + value == priv->valuelast && /* Same value? */ + address == priv->addresslast) /* 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 */ + + lldbg("...[Repeats %d times]...\n", priv->ntimes); + } + + /* Save information about the new access */ + + priv->wrlast = wr; + priv->valuelast = value; + priv->addresslast = address; + priv->ntimes = 0; + } + + /* Return true if this is the first time that we have done this operation */ + + return true; +} +#endif + +/**************************************************************************** + * Name: qspi_getreg + * + * Description: + * Read an QSPI register + * + ****************************************************************************/ + +static inline uint32_t qspi_getreg(struct sam_qspidev_s *priv, + unsigned int offset) +{ + uint32_t address = priv->base + offset; + uint32_t value = getreg32(address); + +#ifdef CONFIG_SAMV7_QSPI_REGDEBUG + if (qspi_checkreg(priv, false, value, address)) + { + lldbg("%08x->%08x\n", address, value); + } +#endif + + return value; +} + +/**************************************************************************** + * Name: qspi_putreg + * + * Description: + * Write a value to an QSPI register + * + ****************************************************************************/ + +static inline void qspi_putreg(struct sam_qspidev_s *priv, uint32_t value, + unsigned int offset) +{ + uint32_t address = priv->base + offset; + +#ifdef CONFIG_SAMV7_QSPI_REGDEBUG + if (qspi_checkreg(priv, true, value, address)) + { + lldbg("%08x<-%08x\n", address, value); + } +#endif + + putreg32(value, address); +} + +/**************************************************************************** + * Name: qspi_dumpregs + * + * Description: + * Dump the contents of all QSPI registers + * + * Input Parameters: + * priv - The QSPI controller to dump + * msg - Message to print before the register data + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_SPI) && defined(CONFIG_DEBUG_VERBOSE) +static void qspi_dumpregs(struct sam_qspidev_s *priv, const char *msg) +{ + qspivdbg("%s:\n", msg); + qspivdbg(" MR:%08x SR:%08x IMR:%08x SCR:%08x\n", + getreg32(priv->base + SAM_QSPI_MR_OFFSET), + getreg32(priv->base + SAM_QSPI_SR_OFFSET), + getreg32(priv->base + SAM_QSPI_IMR_OFFSET), + getreg32(priv->base + SAM_QSPI_SCR_OFFSET)); + qspivdbg(" IAR:%08x ICR:%08x IFR:%08x SMR:%08x\n", + getreg32(priv->base + SAM_QSPI_IAR_OFFSET), + getreg32(priv->base + SAM_QSPI_ICR_OFFSET), + getreg32(priv->base + SAM_QSPI_IFR_OFFSET), + getreg32(priv->base + SAM_QSPI_SMR_OFFSET)); + qspivdbg(" WPCR:%08x WPSR:%08x\n", + getreg32(priv->base + SAM_QSPI_WPCR_OFFSET), + getreg32(priv->base + SAM_QSPI_WPSR_OFFSET)); +} +#endif + +/**************************************************************************** + * Name: qspi_dma_sampleinit + * + * Description: + * Initialize sampling of DMA registers (if CONFIG_SAMV7_QSPI_DMADEBUG) + * + * Input Parameters: + * priv - QSPI driver instance + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SAMV7_QSPI_DMADEBUG +static void qspi_dma_sampleinit(struct sam_qspidev_s *priv) +{ + /* Put contents of register samples into a known state */ + + memset(priv->dmaregs, 0xff, DMA_NSAMPLES * sizeof(struct sam_dmaregs_s)); + + /* Then get the initial samples */ + + sam_dmasample(priv->dmach, &priv->dmaregs[DMA_INITIAL]); +} +#endif + +/**************************************************************************** + * Name: qspi_dma_sampledone + * + * Description: + * Dump sampled DMA registers + * + * Input Parameters: + * priv - QSPI driver instance + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SAMV7_QSPI_DMADEBUG +static void qspi_dma_sampledone(struct sam_qspidev_s *priv) +{ + /* Sample the final registers */ + + sam_dmasample(priv->dmach, &priv->dmaregs[DMA_END_TRANSFER]); + + /* Then dump the sampled DMA registers */ + /* Initial register values */ + + sam_dmadump(priv->dmach, &priv->dmaregs[DMA_INITIAL], + "RX: Initial Registers"); + + /* Register values after DMA setup */ + + sam_dmadump(priv->dmach, &priv->dmaregs[DMA_AFTER_SETUP], + "RX: After DMA Setup"); + + /* Register values after DMA start */ + + sam_dmadump(priv->dmach, &priv->dmaregs[DMA_AFTER_START], + "RX: After DMA Start"); + + /* Register values at the time of the TX and RX DMA callbacks + * -OR- DMA timeout. + * + * If the DMA timed out, then there will not be any RX DMA + * callback samples. There is probably no TX DMA callback + * samples either, but we don't know for sure. + */ + + if (priv->result == -ETIMEDOUT) + { + sam_dmadump(priv->dmach, &priv->dmaregs[DMA_TIMEOUT], + "RX: At DMA timeout"); + } + else + { + sam_dmadump(priv->dmach, &priv->dmaregs[DMA_CALLBACK], + "RX: At DMA callback"); + } + + sam_dmadump(priv->dmach, &priv->dmaregs[DMA_END_TRANSFER], + "RX: At End-of-Transfer"); +} +#endif + +/**************************************************************************** + * Name: qspi_dma_timeout + * + * Description: + * The watchdog timeout setup when a has expired without completion of a + * DMA. + * + * Input Parameters: + * argc - The number of arguments (should be 1) + * arg - The argument (state structure reference cast to uint32_t) + * + * Returned Value: + * None + * + * Assumptions: + * Always called from the interrupt level with interrupts disabled. + * + ****************************************************************************/ + +#ifdef CONFIG_SAMV7_QSPI_DMA +static void qspi_dma_timeout(int argc, uint32_t arg) +{ + struct sam_qspidev_s *priv = (struct sam_qspidev_s *)arg; + DEBUGASSERT(priv != NULL); + + /* Sample DMA registers at the time of the timeout */ + + qspi_dma_sample(priv, DMA_CALLBACK); + + /* Report timeout result, perhaps overwriting any failure reports from + * the TX callback. + */ + + priv->result = -ETIMEDOUT; + + /* Then wake up the waiting thread */ + + sem_post(&priv->dmawait); +} +#endif + +/**************************************************************************** + * Name: qspi_dma_callback + * + * Description: + * This callback function is invoked at the completion of the QSPI RX DMA. + * + * Input Parameters: + * handle - The DMA handler + * arg - A pointer to the chip select structure + * result - The result of the DMA transfer + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SAMV7_QSPI_DMA +static void qspi_dma_callback(DMA_HANDLE handle, void *arg, int result) +{ + struct sam_qspidev_s *priv = (struct sam_qspidev_s *)arg; + DEBUGASSERT(priv != NULL); + + /* Cancel the watchdog timeout */ + + (void)wd_cancel(priv->dmadog); + + /* Sample DMA registers at the time of the callback */ + + qspi_dma_sample(priv, DMA_CALLBACK); + + /* Report the result of the transfer only if the TX callback has not already + * reported an error. + */ + + if (priv->result == -EBUSY) + { + /* Save the result of the transfer if no error was previously reported */ + + priv->result = result; + } + + /* Then wake up the waiting thread */ + + sem_post(&priv->dmawait); +} +#endif + +/**************************************************************************** + * Name: qspi_regaddr + * + * Description: + * Return the address of an QSPI register + * + ****************************************************************************/ + +#ifdef CONFIG_SAMV7_QSPI_DMA +static inline uintptr_t qspi_regaddr(struct sam_qspidev_s *priv, + unsigned int offset) +{ + return priv->base + offset; +} +#endif + +/**************************************************************************** + * Name: qspi_memory_enable + * + * Description: + * Enable the QSPI memory transfer + * + * Input Parameters: + * priv - Device-specific state data + * meminfo - Describes the memory transfer to be performed. + * + * Returned Value: + * Zero (OK) on SUCCESS, a negated errno on value of failure + * + ****************************************************************************/ + +static int qspi_memory_enable(struct sam_qspidev_s *priv, + struct qspi_meminfo_s *meminfo) +{ + uint32_t regval; + + /* Write the Instruction code register: + * + * QSPI_ICR_INST(cmd) 8-bit command + * QSPI_ICR_OPT(0) No option + */ + + regval = QSPI_ICR_INST(meminfo->cmd) | QSPI_ICR_OPT(0); + qspi_putreg(priv, regval, SAM_QSPI_ICR_OFFSET); + + /* Is memory data scrambled? */ + + if (QSPIMEM_ISSCRAMBLE(meminfo->flags)) + { + /* Yes.. set the scramble key */ + + qspi_putreg(priv, meminfo->key, SAM_QSPI_SKR_OFFSET); + + /* Enable the scrambler and enable/disable the random value in the + * key. + */ + + regval = QSPI_SMR_SCREN; + if (!QSPIMEM_ISRANDOM(meminfo->flags)) + { + /* Disable random value in key */ + + regval |= QSPI_SMR_RVDIS; + } + + qspi_putreg(priv, 0, SAM_QSPI_SMR_OFFSET); + } + else + { + /* Disable the scrambler */ + + qspi_putreg(priv, 0, SAM_QSPI_SKR_OFFSET); + qspi_putreg(priv, 0, SAM_QSPI_SMR_OFFSET); + } + + /* Write Instruction Frame Register: + * + * QSPI_IFR_WIDTH_? Instruction=single bit/Data depends on meminfo->flags + * QSPI_IFR_INSTEN=1 Instruction Enable + * QSPI_IFR_ADDREN=1 Address Enable + * QSPI_IFR_OPTEN=0 Option Disable + * QSPI_IFR_DATAEN=1 Data Enable + * QSPI_IFR_OPTL_* Not used (zero) + * QSPI_IFR_ADDRL=0/1 Depends on meminfo->addrlen; + * QSPI_IFR_TFRTYP_RD/WRMEM Depends on meminfo->flags + * QSPI_IFR_CRM=0 Not continuous read + * QSPI_IFR_NBDUM Depends on meminfo->dummies + */ + + regval = QSPI_IFR_INSTEN | QSPI_IFR_ADDREN | QSPI_IFR_DATAEN | + QSPI_IFR_NBDUM(meminfo->dummies); + + if (QSPIMEM_ISWRITE(meminfo->flags)) + { + regval |= QSPI_IFR_TFRTYP_WRMEM | QSPI_IFR_WIDTH_SINGLE; + } + else + { + if (QSPIMEM_ISQUADIO(meminfo->flags)) + { + regval |= QSPI_IFR_TFRTYP_RDMEM | QSPI_IFR_WIDTH_QUADIO; + } + else if (QSPIMEM_ISDUALIO(meminfo->flags)) + { + regval |= QSPI_IFR_TFRTYP_RDMEM | QSPI_IFR_WIDTH_DUALIO; + } + else + { + regval |= QSPI_IFR_TFRTYP_RDMEM | QSPI_IFR_WIDTH_SINGLE; + } + } + + if (meminfo->addrlen == 3) + { + regval |= QSPI_IFR_ADDRL_24BIT; + } + else if (meminfo->addrlen == 4) + { + regval |= QSPI_IFR_ADDRL_32BIT; + } + else + { + return -EINVAL; + } + + /* Write the instruction frame value */ + + qspi_putreg(priv, regval, SAM_QSPI_IFR_OFFSET); + (void)qspi_getreg(priv, SAM_QSPI_IFR_OFFSET); + return OK; +} + +/**************************************************************************** + * Name: qspi_memory_dma + * + * Description: + * Perform one QSPI memory transfer using DMA + * + * Input Parameters: + * priv - Device-specific state data + * meminfo - Describes the memory transfer to be performed. + * + * Returned Value: + * Zero (OK) on SUCCESS, a negated errno on value of failure + * + ****************************************************************************/ + +#ifdef CONFIG_SAMV7_QSPI_DMA +static int qspi_memory_dma(struct sam_qspidev_s *priv, + struct qspi_meminfo_s *meminfo) +{ + uintptr_t qspimem = SAM_QSPIMEM_BASE + meminfo->addr; + uint32_t dmaflags; + int ret; + + /* Initialize register sampling */ + + qspi_dma_sampleinit(priv); + + /* Determine DMA flags and setup the DMA */ + + dmaflags = DMACH_FLAG_FIFOCFG_LARGEST | DMACH_FLAG_PERIPHAHB_AHB_IF1 | + DMACH_FLAG_PERIPHISMEMORY | DMACH_FLAG_PERIPHINCREMENT | + DMACH_FLAG_PERIPHCHUNKSIZE_1 | DMACH_FLAG_MEMPID_MAX | + DMACH_FLAG_MEMAHB_AHB_IF1 | DMACH_FLAG_MEMINCREMENT | + DMACH_FLAG_MEMCHUNKSIZE_1 | DMACH_FLAG_MEMBURST_16; + + if (QSPIMEM_ISWRITE(meminfo->flags)) + { + /* Configure TX DMA */ + + dmaflags |= ((uint32_t)priv->txintf << DMACH_FLAG_PERIPHPID_SHIFT) | + DMACH_FLAG_PERIPHWIDTH_8BITS | DMACH_FLAG_MEMWIDTH_8BITS; + sam_dmaconfig(priv->dmach, dmaflags); + + /* Setup the TX DMA (peripheral-to-memory) */ + + ret = sam_dmatxsetup(priv->dmach, qspimem, (uint32_t)meminfo->buffer, + meminfo->buflen); + } + else + { + /* Configure RX DMA */ + + dmaflags |= ((uint32_t)priv->rxintf << DMACH_FLAG_PERIPHPID_SHIFT) | + DMACH_FLAG_PERIPHWIDTH_16BITS | DMACH_FLAG_MEMWIDTH_16BITS; + sam_dmaconfig(priv->dmach, dmaflags); + + /* Setup the RX DMA (memory-to-peripheral) */ + + ret = sam_dmarxsetup(priv->dmach, qspimem, (uint32_t)meminfo->buffer, + meminfo->buflen); + } + + if (ret < 0) + { + qspidbg("ERROR: DMA setup failed: %d\n", ret); + return ret; + } + + qspi_dma_sample(priv, DMA_AFTER_SETUP); + + /* Enable the memory transfer */ + + qspi_memory_enable(priv, meminfo); + + /* Start the DMA */ + + priv->result = -EBUSY; + ret = sam_dmastart(priv->dmach, qspi_dma_callback, (void *)priv); + if (ret < 0) + { + qspidbg("ERROR: sam_dmastart failed: %d\n", ret); + return ret; + } + + qspi_dma_sample(priv, DMA_AFTER_START); + + /* Wait for DMA completion. This is done in a loop because there may be + * false alarm semaphore counts that cause sam_wait() not fail to wait + * or to wake-up prematurely (for example due to the receipt of a signal). + * We know that the DMA has completed when the result is anything other + * that -EBUSY. + */ + + do + { + /* Start (or re-start) the watchdog timeout */ + + ret = wd_start(priv->dmadog, DMA_TIMEOUT_TICKS, + (wdentry_t)qspi_dma_timeout, 1, (uint32_t)priv); + if (ret != OK) + { + qspidbg("ERROR: wd_start failed: %d\n", ret); + } + + /* Wait for the DMA complete */ + + ret = sem_wait(&priv->dmawait); + + /* Cancel the watchdog timeout */ + + (void)wd_cancel(priv->dmadog); + + /* Check if we were awakened by an error of some kind */ + + if (ret < 0) + { + /* EINTR is not a failure. That simply means that the wait + * was awakened by a signal. + */ + + int errorcode = errno; + if (errorcode != EINTR) + { + DEBUGPANIC(); + return -errorcode; + } + } + + /* Not that we might be awakened before the wait is over due to + * residual counts on the semaphore. So, to handle, that case, + * we loop until something changes the DMA result to any value other + * than -EBUSY. + */ + } + while (priv->result == -EBUSY); + + /* Wait until the transmission registers are empty. */ + + while ((qspi_getreg(priv, SAM_QSPI_SR_OFFSET) & QSPI_INT_TXEMPTY) == 0); + qspi_putreg(priv, QSPI_CR_LASTXFER, SAM_QSPI_CR_OFFSET); + + while ((qspi_getreg(priv, SAM_QSPI_SR_OFFSET) & QSPI_SR_INSTRE) == 0); + MEMORY_SYNC(); + + /* Dump the sampled DMA registers */ + + qspi_dma_sampledone(priv); + + /* Make sure that the DMA is stopped (it will be stopped automatically + * on normal transfers, but not necessarily when the transfer terminates + * on an error condition). + */ + + sam_dmastop(priv->dmach); + + /* Complain if the DMA fails */ + + if (priv->result) + { + qspidbg("ERROR: DMA failed with result: %d\n", priv->result); + } + + return priv->result; +} +#endif + +/**************************************************************************** + * Name: qspi_memory_nodma + * + * Description: + * Perform one QSPI memory transfer without using DMA + * + * Input Parameters: + * priv - Device-specific state data + * meminfo - Describes the memory transfer to be performed. + * + * Returned Value: + * Zero (OK) on SUCCESS, a negated errno on value of failure + * + ****************************************************************************/ + +static int qspi_memory_nodma(struct sam_qspidev_s *priv, + struct qspi_meminfo_s *meminfo) +{ + uintptr_t qspimem = SAM_QSPIMEM_BASE + meminfo->addr; + + /* Enable the memory transfer */ + + qspi_memory_enable(priv, meminfo); + + /* Transfer data to/from QSPI memory */ + + if (QSPIMEM_ISWRITE(meminfo->flags)) + { + memcpy((void *)qspimem, meminfo->buffer, meminfo->buflen); + } + else + { + memcpy(meminfo->buffer, (void *)qspimem, meminfo->buflen); + } + + MEMORY_SYNC(); + + /* Indicate the end of the transfer as soon as the transmission + * registers are empty. + */ + + while ((qspi_getreg(priv, SAM_QSPI_SR_OFFSET) & QSPI_INT_TXEMPTY) == 0); + qspi_putreg(priv, QSPI_CR_LASTXFER, SAM_QSPI_CR_OFFSET); + + /* Wait for the end of the transfer + * + * REVISIT: If DMA is not used then large transfers could come through + * this path. In that case, there would be a benefit to waiting for an + * interrupt to signal the end of the transfer. + */ + + while ((qspi_getreg(priv, SAM_QSPI_SR_OFFSET) & QSPI_SR_INSTRE) == 0); + return OK; +} + +/**************************************************************************** + * Name: qspi_lock + * + * Description: + * On QSPI buses where there are multiple devices, it will be necessary to + * lock QSPI to have exclusive access to the buses for a sequence of + * transfers. The bus should be locked before the chip is selected. After + * locking the QSPI bus, the caller should then also call the setfrequency, + * setbits, and setmode methods to make sure that the QSPI is properly + * configured for the device. If the QSPI bus is being shared, then it + * may have been left in an incompatible state. + * + * Input Parameters: + * dev - Device-specific state data + * lock - true: Lock QSPI bus, false: unlock QSPI bus + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int qspi_lock(struct qspi_dev_s *dev, bool lock) +{ + struct sam_qspidev_s *priv = (struct sam_qspidev_s *)dev; + + qspivdbg("lock=%d\n", lock); + if (lock) + { + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&priv->exclsem) != 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(errno == EINTR); + } + } + else + { + (void)sem_post(&priv->exclsem); + } + + return OK; +} + +/**************************************************************************** + * Name: qspi_setfrequency + * + * Description: + * Set the QSPI frequency. + * + * Input Parameters: + * dev - Device-specific state data + * frequency - The QSPI frequency requested + * + * Returned Value: + * Returns the actual frequency selected + * + ****************************************************************************/ + +static uint32_t qspi_setfrequency(struct qspi_dev_s *dev, uint32_t frequency) +{ + struct sam_qspidev_s *priv = (struct sam_qspidev_s *)dev; + uint32_t actual; + uint32_t scbr; +#if CONFIG_SAMV7_QSPI_DLYBS > 0 + uint32_t dlybs; +#endif +#if CONFIG_SAMV7_QSPI_DLYBCT > 0 + uint32_t dlybct; +#endif + uint32_t regval; + + qspivdbg("frequency=%d\n", frequency); + DEBUGASSERT(priv); + + /* Check if the requested frequency is the same as the frequency selection */ + + if (priv->frequency == frequency) + { + /* We are already at this frequency. Return the actual. */ + + return priv->actual; + } + + /* Configure QSPI to a frequency as close as possible to the requested frequency. + * + * QSCK frequency = QSPI_CLK / SCBR, or SCBR = QSPI_CLK / frequency + * + * Where SCBR can have the range 1 to 256 and register holds SCBR - 1. NOTE + * that a "ceiling" type of calculation is performed. 'frequency' is treated + * as a not-to-exceed value. + */ + + scbr = (frequency + SAM_QSPI_CLOCK - 1) / frequency; + + /* Make sure that the divider is within range */ + + if (scbr < 1) + { + scbr = 1; + } + else if (scbr > 256) + { + scbr = 256; + } + + /* Save the new SCBR value (minus one) */ + + regval = qspi_getreg(priv, SAM_QSPI_SCR_OFFSET); + regval &= ~(QSPI_SCR_SCBR_MASK | QSPI_SCR_DLYBS_MASK); + regval |= (scbr - 1) << QSPI_SCR_SCBR_SHIFT; + + /* DLYBS: Delay Before QSCK. This field defines the delay from NPCS valid to the + * first valid QSCK transition. When DLYBS equals zero, the NPCS valid to QSCK + * transition is 1/2 the QSCK clock period. Otherwise, the following equations + * determine the delay: + * + * Delay Before QSCK = DLYBS / QSPI_CLK + * + * For a 100 nsec delay (assumes QSPI_CLK is an even multiple of MHz): + * + * DLYBS == 100 * QSPI_CLK / 1000000000 + * == (100 * (QSPI_CLK / 1000000)) / 1000 + */ + +#if CONFIG_SAMV7_QSPI_DLYBS > 0 + dlybs = (CONFIG_SAMV7_QSPI_DLYBS * (SAM_QSPI_CLOCK / 1000000)) / 1000; + regval |= dlybs << QSPI_SCR_DLYBS_SHIFT; +#endif + + qspi_putreg(priv, regval, SAM_QSPI_SCR_OFFSET); + + /* DLYBCT: Delay Between Consecutive Transfers. This field defines the delay + * between two consecutive transfers with the same peripheral without removing + * the chip select. The delay is always inserted after each transfer and + * before removing the chip select if needed. + * + * Delay Between Consecutive Transfers = (32 x DLYBCT) / QSPI_CLK + * + * For a 500 nsec delay (assumes QSPI_CLK is an even multiple of MHz): + * + * DLYBCT = 500 * QSPI_CLK / 1000000000 / 32 + * = (500 * (QSPI_CLK / 1000000) / 1000 / 32 + */ + + regval = qspi_getreg(priv, SAM_QSPI_MR_OFFSET); + regval &= ~QSPI_MR_DLYBCT_MASK; + +#if CONFIG_SAMV7_QSPI_DLYBCT > 0 + dlybct = ((CONFIG_SAMV7_QSPI_DLYBCT * (SAM_QSPI_CLOCK /1000000)) / 1000 / 32; + regval |= dlybct << QSPI_MR_DLYBCT_SHIFT; +#endif + + qspi_putreg(priv, regval, SAM_QSPI_MR_OFFSET); + + /* Calculate the new actual frequency */ + + actual = SAM_QSPI_CLOCK / scbr; + qspivdbg("SCBR=%d actual=%d\n", scbr, actual); + + /* Save the frequency setting */ + + priv->frequency = frequency; + priv->actual = actual; + + qspidbg("Frequency %d->%d\n", frequency, actual); + return actual; +} + +/**************************************************************************** + * Name: qspi_setmode + * + * Description: + * Set the QSPI mode. Optional. See enum qspi_mode_e for mode definitions + * + * Input Parameters: + * dev - Device-specific state data + * mode - The QSPI mode requested + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void qspi_setmode(struct qspi_dev_s *dev, enum qspi_mode_e mode) +{ + struct sam_qspidev_s *priv = (struct sam_qspidev_s *)dev; + uint32_t regval; + + qspivdbg("mode=%d\n", mode); + + /* Has the mode changed? */ + + if (mode != priv->mode) + { + /* Yes... Set the mode appropriately: + * + * QSPI CPOL CPHA + * MODE + * 0 0 0 + * 1 0 1 + * 2 1 0 + * 3 1 1 + */ + + regval = qspi_getreg(priv, SAM_QSPI_SCR_OFFSET); + regval &= ~(QSPI_SCR_CPOL | QSPI_SCR_CPHA); + + switch (mode) + { + case QSPIDEV_MODE0: /* CPOL=0; CPHA=0 */ + break; + + case QSPIDEV_MODE1: /* CPOL=0; CPHA=1 */ + regval |= QSPI_SCR_CPHA; + break; + + case QSPIDEV_MODE2: /* CPOL=1; CPHA=0 */ + regval |= QSPI_SCR_CPOL; + break; + + case QSPIDEV_MODE3: /* CPOL=1; CPHA=1 */ + regval |= (QSPI_SCR_CPOL | QSPI_SCR_CPHA); + break; + + default: + DEBUGASSERT(FALSE); + return; + } + + qspi_putreg(priv, regval, SAM_QSPI_SCR_OFFSET); + qspivdbg("SCR=%08x\n", regval); + + /* Save the mode so that subsequent re-configurations will be faster */ + + priv->mode = mode; + } +} + +/**************************************************************************** + * Name: qspi_setbits + * + * Description: + * Set the number if bits per word. + * + * Input Parameters: + * dev - Device-specific state data + * nbits - The number of bits requests + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void qspi_setbits(struct qspi_dev_s *dev, int nbits) +{ + struct sam_qspidev_s *priv = (struct sam_qspidev_s *)dev; + uint32_t regval; + + qspivdbg("nbits=%d\n", nbits); + DEBUGASSERT(priv != NULL); + DEBUGASSERT(nbits >= SAM_QSPI_MINBITS && nbits <= SAM_QSPI_MAXBITS); + + /* Has the number of bits changed? */ + + if (nbits != priv->nbits) + { + /* Yes... Set number of bits appropriately */ + + regval = qspi_getreg(priv, SAM_QSPI_MR_OFFSET); + regval &= ~QSPI_MR_NBBITS_MASK; + regval |= QSPI_MR_NBBITS(nbits); + qspi_putreg(priv, regval, SAM_QSPI_MR_OFFSET); + + qspivdbg("SCR%02x]=%08x\n", regval); + + /* Save the selection so the subsequence re-configurations will be faster */ + + priv->nbits = nbits; + } +} + +/**************************************************************************** + * Name: qspi_command + * + * Description: + * Perform one QSPI data transfer + * + * Input Parameters: + * dev - Device-specific state data + * cmdinfo - Describes the command transfer to be performed. + * + * Returned Value: + * Zero (OK) on SUCCESS, a negated errno on value of failure + * + ****************************************************************************/ + +static int qspi_command(struct qspi_dev_s *dev, + struct qspi_cmdinfo_s *cmdinfo) +{ + struct sam_qspidev_s *priv = (struct sam_qspidev_s *)dev; + uint32_t regval; + uint32_t ifr; + + DEBUGASSERT(priv != NULL && cmdinfo != NULL); + +#ifdef CONFIG_DEBUG_SPI + qspivdbg("Transfer:\n"); + qspivdbg(" flags: %02x\n", cmdinfo->flags); + qspivdbg(" cmd: %04x\n", cmdinfo->cmd); + + if (QSPICMD_ISADDRESS(cmdinfo->flags)) + { + qspivdbg(" address/length: %08lx %d\n", + (unsigned long)cmdinfo->addr, cmdinfo->addrlen); + } + + if (QSPICMD_ISDATA(cmdinfo->flags)) + { + qspivdbg(" %s Data:\n", QSPICMD_ISWRITE(cmdinfo->flags) ? "Write" : "Read"); + qspivdbg(" buffer/length: %p %d\n", cmdinfo->buffer, cmdinfo->buflen); + } +#endif + + DEBUGASSERT(cmdinfo->cmd < 256); + + /* Write the instruction address register */ + + ifr = 0; + if (QSPICMD_ISADDRESS(cmdinfo->flags)) + { + DEBUGASSERT(cmdinfo->addrlen == 3 || cmdinfo->addrlen == 4); + + qspi_putreg(priv, cmdinfo->addr, SAM_QSPI_IFR_OFFSET); + ifr |= QSPI_IFR_ADDREN; + + if (cmdinfo->addrlen == 3) + { + ifr |= QSPI_IFR_ADDRL_24BIT; + } + else if (cmdinfo->addrlen == 4) + { + ifr |= QSPI_IFR_ADDRL_32BIT; + } + else + { + return -EINVAL; + } + } + + /* Write the Instruction code register: + * + * QSPI_ICR_INST(cmd) 8-bit command + * QSPI_ICR_OPT(0) No option + */ + + regval = QSPI_ICR_INST(cmdinfo->cmd) | QSPI_ICR_OPT(0); + qspi_putreg(priv, regval, SAM_QSPI_ICR_OFFSET); + + /* Does data accompany the command? */ + + if (QSPICMD_ISDATA(cmdinfo->flags)) + { + uint16_t buflen; + + DEBUGASSERT(cmdinfo->buffer != NULL && cmdinfo->buflen > 0); + + /* Make sure that the length is an even multiple of 32-bit words. + * REVISIT: This could cause access past the end of an allocated + * buffer. + */ + + buflen = (cmdinfo->buflen + 3) & ~3; + + /* Write Instruction Frame Register: + * + * QSPI_IFR_WIDTH_SINGLE Instruction=single bit/Data single bit + * QSPI_IFR_INSTEN=1 Instruction Enable + * QSPI_IFR_ADDREN=? (See logic above) + * QSPI_IFR_OPTEN=0 Option Disable + * QSPI_IFR_DATAEN=1 Data Enable + * QSPI_IFR_OPTL_* Not used (zero) + * QSPI_IFR_ADDRL=0 Not used (zero) + * QSPI_IFR_TFRTYP_WRITE Write transfer into serial memory, OR + * QSPI_IFR_TFRTYP_READ Read transfer from serial memory + * QSPI_IFR_CRM=0 Not continuous read + * QSPI_IFR_NBDUM(0) No dummy cycles + */ + + ifr |= QSPI_IFR_WIDTH_SINGLE | QSPI_IFR_INSTEN | QSPI_IFR_DATAEN | + QSPI_IFR_NBDUM(0); + + if (QSPICMD_ISWRITE(cmdinfo->flags)) + { + ifr |= QSPI_IFR_TFRTYP_WRITE; + qspi_putreg(priv, ifr, SAM_QSPI_IFR_OFFSET); + + (void)qspi_getreg(priv, SAM_QSPI_IFR_OFFSET); + + /* Copy the data to write to QSPI_RAM */ + + memcpy((void *)SAM_QSPIMEM_BASE, cmdinfo->buffer, buflen); + } + else + { + ifr |= QSPI_IFR_TFRTYP_READ; + qspi_putreg(priv, ifr, SAM_QSPI_IFR_OFFSET); + + (void)qspi_getreg(priv, SAM_QSPI_IFR_OFFSET); + + /* Copy the data from QSPI memory into the user buffer */ + memcpy(cmdinfo->buffer, (const void *)SAM_QSPIMEM_BASE, buflen); + } + + MEMORY_SYNC(); + + /* Indicate the end of the transfer as soon as the transmission + * registers are empty. + */ + + while ((qspi_getreg(priv, SAM_QSPI_SR_OFFSET) & QSPI_INT_TXEMPTY) == 0); + + qspi_putreg(priv, QSPI_CR_LASTXFER, SAM_QSPI_CR_OFFSET); + + /* Fall through to INSTRE wait */ + } + else + { + /* Write Instruction Frame Register: + * + * QSPI_IFR_WIDTH_SINGLE Instruction=single bit/Data single bit + * QSPI_IFR_INSTEN=1 Instruction Enable + * QSPI_IFR_ADDREN=? (See logic above) + * QSPI_IFR_OPTEN=0 Option Disable + * QSPI_IFR_DATAEN=0 Data Disable + * QSPI_IFR_OPTL_* Not used (zero) + * QSPI_IFR_ADDRL=0 Not used (zero) + * QSPI_IFR_TFRTYP_READ Shouldn't matter + * QSPI_IFR_CRM=0 Not continuous read + * QSPI_IFR_NBDUM(0) No dummy cycles + */ + + ifr = QSPI_IFR_WIDTH_SINGLE | QSPI_IFR_INSTEN | QSPI_IFR_TFRTYP_READ | + QSPI_IFR_NBDUM(0); + qspi_putreg(priv, ifr, SAM_QSPI_IFR_OFFSET); + + MEMORY_SYNC(); + + /* Fall through to INSTRE wait */ + } + + /* When the command has been sent, Instruction End Status (INTRE) will be + * set in the QSPI status register. + */ + + while ((qspi_getreg(priv, SAM_QSPI_SR_OFFSET) & QSPI_SR_INSTRE) == 0); + + return OK; +} + +/**************************************************************************** + * Name: qspi_memory + * + * Description: + * Perform one QSPI memory transfer + * + * Input Parameters: + * dev - Device-specific state data + * meminfo - Describes the memory transfer to be performed. + * + * Returned Value: + * Zero (OK) on SUCCESS, a negated errno on value of failure + * + ****************************************************************************/ + +static int qspi_memory(struct qspi_dev_s *dev, + struct qspi_meminfo_s *meminfo) +{ + struct sam_qspidev_s *priv = (struct sam_qspidev_s *)dev; + + DEBUGASSERT(priv != NULL && meminfo != NULL); + +#ifdef CONFIG_SAMV7_QSPI_DMA + /* Can we perform DMA? Should we perform DMA? */ + + if (priv->candma && meminfo->buflen > CONFIG_SAMV7_QSPI_DMATHRESHOLD) + { + return qspi_memory_dma(priv, meminfo); + } + else +#endif + { + return qspi_memory_nodma(priv, meminfo); + } +} + +/**************************************************************************** + * Name: qspi_hw_initialize + * + * Description: + * Initialize the QSPI peripheral from hardware reset. + * + * Input Parameters: + * priv - Device state structure. + * + * Returned Value: + * Zero (OK) on SUCCESS, a negated errno on value of failure + * + ****************************************************************************/ + +static int qspi_hw_initialize(struct sam_qspidev_s *priv) +{ + uint32_t regval; + + /* Disable the QSPI */ + + qspi_putreg(priv, QSPI_CR_QSPIDIS, SAM_QSPI_CR_OFFSET); + while ((qspi_getreg(priv, SAM_QSPI_SR_OFFSET) & QSPI_SR_QSPIENS) != 0); + + /* Reset the QSPI (twice) */ + + qspi_putreg(priv, QSPI_CR_SWRST, SAM_QSPI_CR_OFFSET); + qspi_putreg(priv, QSPI_CR_SWRST, SAM_QSPI_CR_OFFSET); + + /* Configure the QSPI + * + * QSPI_MR_SMM - Serial Memory Mode + * QSPI_MR_CSMODE_LASTXFER - CS de-asserted when LASTXFER transferred + */ + + regval = QSPI_MR_SMM; + qspi_putreg(priv, regval, SAM_QSPI_MR_OFFSET); + + regval |= QSPI_MR_CSMODE_LASTXFER; + qspi_putreg(priv, regval, SAM_QSPI_MR_OFFSET); + + /* Set up the initial QSPI clock mode: + * + * Mode 0: CPOL=0; CPHA=0 + */ + + regval = qspi_getreg(priv, SAM_QSPI_SCR_OFFSET); + regval &= ~(QSPI_SCR_CPOL | QSPI_SCR_CPHA); + qspi_putreg(priv, regval, SAM_QSPI_SCR_OFFSET); + + regval |= QSPI_SCR_SCBR(1); + qspi_putreg(priv, regval, SAM_QSPI_SCR_OFFSET); + + /* 8-bit mode */ + + regval = qspi_getreg(priv, SAM_QSPI_MR_OFFSET); + regval &= ~QSPI_MR_NBBITS_MASK; + regval |= QSPI_MR_NBBITS_8BIT; + qspi_putreg(priv, regval, SAM_QSPI_MR_OFFSET); + + priv->nbits = 8; + + /* Enable QSPI */ + + qspi_putreg(priv, QSPI_CR_QSPIEN, SAM_QSPI_CR_OFFSET); + while ((qspi_getreg(priv, SAM_QSPI_SR_OFFSET) & QSPI_SR_QSPIENS) == 0); + + /* Flush any pending transfers */ + + (void)qspi_getreg(priv, SAM_QSPI_SR_OFFSET); + (void)qspi_getreg(priv, SAM_QSPI_RDR_OFFSET); + + qspi_dumpregs(priv, "After initialization"); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sam_qspi_initialize + * + * Description: + * Initialize the selected QSPI port in master mode + * + * Input Parameter: + * intf - Interface number(must be zero) + * + * Returned Value: + * Valid QSPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct qspi_dev_s *sam_qspi_initialize(int intf) +{ + struct sam_qspidev_s *priv; + int ret; + + /* The support SAM parts have only a single QSPI port */ + + qspivdbg("intf: %d\n", intf); + DEBUGASSERT(intf >= 0 && intf < SAMV7_NQSPI); + + /* Select the QSPI interface */ + +#ifdef CONFIG_SAMV7_QSPI + if (intf == 0) + { + /* If this function is called multiple times, the following operatinos + * will be performed multiple times. + */ + + /* Select QSPI0 */ + + priv = &g_qspi0dev; + + /* Enable clocking to the QSPI peripheral */ + + sam_qspi_enableclk(); + + /* Configure multiplexed pins as connected on the board. */ + + sam_configgpio(GPIO_QSPI_CS); + sam_configgpio(GPIO_QSPI_IO0); + sam_configgpio(GPIO_QSPI_IO1); + sam_configgpio(GPIO_QSPI_IO2); + sam_configgpio(GPIO_QSPI_IO3); + sam_configgpio(GPIO_QSPI_SCK); + } + else +#endif + { + qspidbg("ERROR: QSPI%d not supported\n", intf); + return NULL; + } + + /* Has the QSPI hardware been initialized? */ + + if (!priv->initialized) + { + /* No perform one time initialization */ + /* Initialize the QSPI semaphore that enforces mutually exclusive + * access to the QSPI registers. + */ + + sem_init(&priv->exclsem, 0, 1); + +#ifdef CONFIG_SAMV7_QSPI_DMA + /* Pre-allocate DMA channels. */ + + if (priv->candma) + { + priv->dmach = sam_dmachannel(0,0); + if (!priv->dmach) + { + qspidbg("ERROR: Failed to allocate the DMA channel\n"); + priv->candma = false; + } + } + + /* Initialize the QSPI semaphore that is used to wake up the waiting + * thread when the DMA transfer completes. + */ + + sem_init(&priv->dmawait, 0, 0); + + /* Create a watchdog time to catch DMA timeouts */ + + priv->dmadog = wd_create(); + if (priv->dmadog == NULL) + { + qspidbg("ERROR: Failed to create wdog\n"); + goto errout_with_dmahandles; + } +#endif + +#ifdef QSPI_USE_INTERRUPTS + /* Attach the interrupt handler */ + + ret = irq_attach(priv->irq, priv->handler); + if (ret < 0) + { + qspidbg("ERROR: Failed to attach irq %d\n", priv->irq); + goto errout_with_dmadog; + } +#endif + + /* Perform hardware initialization. Puts the QSPI into an active + * state. + */ + + ret = qspi_hw_initialize(priv); + if (ret < 0) + { + qspidbg("ERROR: Failed to initialize QSPI hardware\n"); + goto errout_with_irq; + } + + /* Enable interrupts at the NVIC */ + + priv->initialized = true; +#ifdef QSPI_USE_INTERRUPTS + up_enable_irq(priv->irq); +#endif + } + + return &priv->qspi; + +errout_with_irq: +#ifdef QSPI_USE_INTERRUPTS + irq_detach(priv->irq); + +errout_with_dmadog: +#endif +#ifdef CONFIG_SAMV7_QSPI_DMA + wd_delete(priv->dmadog); + +errout_with_dmahandles: + sem_destroy(&priv->dmawait); + + if (priv->dmach) + { + sam_dmafree(priv->dmach); + priv->dmach = NULL; + } +#endif + + sem_destroy(&priv->exclsem); + return NULL; +} +#endif /* CONFIG_SAMV7_QSPI */ diff --git a/arch/arm/src/samv7/sam_qspi.h b/arch/arm/src/samv7/sam_qspi.h new file mode 100644 index 00000000000..85d2e57d659 --- /dev/null +++ b/arch/arm/src/samv7/sam_qspi.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * arch/arm/src/samv7/sam_qspi.h + * + * Copyright (C) 2015 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_SAMV7_SAM_QSPI_H +#define __ARCH_ARM_SRC_SAMV7_SAM_QSPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "chip.h" +#include "sam_config.h" + +#ifdef CONFIG_SAMV7_QSPI + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: sam_qspi_initialize + * + * Description: + * Initialize the selected QSPI port in master mode + * + * Input Parameter: + * intf - Interface number(must be zero) + * + * Returned Value: + * Valid SPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct qspi_dev_s; +FAR struct qspi_dev_s *sam_qspi_initialize(int intf); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_SAMV7_QSPI */ +#endif /* __ARCH_ARM_SRC_SAMV7_SAM_QSPI_H */ diff --git a/arch/arm/src/samv7/sam_spi.c b/arch/arm/src/samv7/sam_spi.c index 1fc521d2d24..702e8ad779c 100644 --- a/arch/arm/src/samv7/sam_spi.c +++ b/arch/arm/src/samv7/sam_spi.c @@ -69,7 +69,7 @@ #include "chip/sam_spi.h" #include "chip/sam_pinmap.h" -#if defined(CONFIG_SAMV7_SPI0) || defined(CONFIG_SAMV7_SPI1) +#ifdef CONFIG_SAMV7_SPI_MASTER /**************************************************************************** * Pre-processor Definitions @@ -86,13 +86,13 @@ #ifdef CONFIG_SAMV7_SPI_DMA -# if defined(CONFIG_SAMV7_SPI0) && defined(CONFIG_SAMV7_DMAC0) +# if defined(CONFIG_SAMV7_SPI0_MASTER) && defined(CONFIG_SAMV7_DMAC0) # define SAMV7_SPI0_DMA true # else # define SAMV7_SPI0_DMA false # endif -# if defined(CONFIG_SAMV7_SPI1) && defined(CONFIG_SAMV7_DMAC1) +# if defined(CONFIG_SAMV7_SPI1_MASTER) && defined(CONFIG_SAMV7_DMAC1) # define SAMV7_SPI1_DMA true # else # define SAMV7_SPI1_DMA false @@ -118,7 +118,7 @@ #define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS) /* Debug *******************************************************************/ -/* Check if SPI debut is enabled (non-standard.. no support in +/* Check if SPI debug is enabled (non-standard.. no support in * include/debug.h */ @@ -170,7 +170,7 @@ struct sam_spics_s #endif uint8_t nbits; /* Width of word in bits (8 to 16) */ -#if defined(CONFIG_SAMV7_SPI0) || defined(CONFIG_SAMV7_SPI1) +#if defined(CONFIG_SAMV7_SPI0_MASTER) || defined(CONFIG_SAMV7_SPI1_MASTER) uint8_t spino; /* SPI controller number (0 or 1) */ #endif uint8_t cs; /* Chip select number */ @@ -196,7 +196,7 @@ struct sam_spics_s typedef void (*select_t)(enum spi_dev_e devid, bool selected); -/* Chip select register offsetrs */ +/* Chip select register offsets */ /* The overall state of one SPI controller */ @@ -273,7 +273,7 @@ static inline uintptr_t spi_regaddr(struct sam_spics_s *spics, unsigned int offset); #endif -/* SPI methods */ +/* SPI master methods */ #ifndef CONFIG_SPI_OWNBUS static int spi_lock(struct spi_dev_s *dev, bool lock); @@ -309,7 +309,7 @@ static const uint8_t g_csroffset[4] = SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR3_OFFSET }; -#ifdef CONFIG_SAMV7_SPI0 +#ifdef CONFIG_SAMV7_SPI0_MASTER /* SPI0 driver operations */ static const struct spi_ops_s g_spi0ops = @@ -348,7 +348,7 @@ static struct sam_spidev_s g_spi0dev = }; #endif -#ifdef CONFIG_SAMV7_SPI1 +#ifdef CONFIG_SAMV7_SPI1_MASTER /* SPI1 driver operations */ static const struct spi_ops_s g_spi1ops = @@ -541,9 +541,9 @@ static void spi_dumpregs(struct sam_spidev_s *spi, const char *msg) static inline struct sam_spidev_s *spi_device(struct sam_spics_s *spics) { -#if defined(CONFIG_SAMV7_SPI0) && defined(CONFIG_SAMV7_SPI1) +#if defined(CONFIG_SAMV7_SPI0_MASTER) && defined(CONFIG_SAMV7_SPI1_MASTER) return spics->spino ? &g_spi1dev : &g_spi0dev; -#elif defined(CONFIG_SAMV7_SPI0) +#elif defined(CONFIG_SAMV7_SPI0_MASTER) return &g_spi0dev; #else return &g_spi1dev; @@ -1726,7 +1726,7 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer, size_t nwords) * Name: up_spiinitialize * * Description: - * Initialize the selected SPI port + * Initialize the selected SPI port in master mode * * Input Parameter: * cs - Chip select number (identifying the "logical" SPI port) @@ -1736,10 +1736,10 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer, size_t nwords) * ****************************************************************************/ -struct spi_dev_s *up_spiinitialize(int port) +FAR struct spi_dev_s *up_spiinitialize(int port) { - struct sam_spidev_s *spi; - struct sam_spics_s *spics; + FAR struct sam_spidev_s *spi; + FAR struct sam_spics_s *spics; int csno = (port & __SPI_CS_MASK) >> __SPI_CS_SHIFT; int spino = (port & __SPI_SPI_MASK) >> __SPI_SPI_SHIFT; irqstate_t flags; @@ -1753,9 +1753,9 @@ struct spi_dev_s *up_spiinitialize(int port) spivdbg("port: %d csno: %d spino: %d\n", port, csno, spino); DEBUGASSERT(csno >= 0 && csno <= SAM_SPI_NCS); -#if defined(CONFIG_SAMV7_SPI0) && defined(CONFIG_SAMV7_SPI1) +#if defined(CONFIG_SAMV7_SPI0_MASTER) && defined(CONFIG_SAMV7_SPI1_MASTER) DEBUGASSERT(spino >= 0 && spino <= 1); -#elif defined(CONFIG_SAMV7_SPI0) +#elif defined(CONFIG_SAMV7_SPI0_MASTER) DEBUGASSERT(spino == 0); #else DEBUGASSERT(spino == 1); @@ -1812,9 +1812,9 @@ struct spi_dev_s *up_spiinitialize(int port) /* Select the SPI operations */ -#if defined(CONFIG_SAMV7_SPI0) && defined(CONFIG_SAMV7_SPI1) +#if defined(CONFIG_SAMV7_SPI0_MASTER) && defined(CONFIG_SAMV7_SPI1_MASTER) spics->spidev.ops = spino ? &g_spi1ops : &g_spi0ops; -#elif defined(CONFIG_SAMV7_SPI0) +#elif defined(CONFIG_SAMV7_SPI0_MASTER) spics->spidev.ops = &g_spi0ops; #else spics->spidev.ops = &g_spi1ops; @@ -1823,7 +1823,7 @@ struct spi_dev_s *up_spiinitialize(int port) /* Save the chip select and SPI controller numbers */ spics->cs = csno; -#if defined(CONFIG_SAMV7_SPI0) || defined(CONFIG_SAMV7_SPI1) +#if defined(CONFIG_SAMV7_SPI0_MASTER) || defined(CONFIG_SAMV7_SPI1_MASTER) spics->spino = spino; #endif @@ -1838,10 +1838,10 @@ struct spi_dev_s *up_spiinitialize(int port) /* Enable clocking to the SPI block */ flags = irqsave(); -#if defined(CONFIG_SAMV7_SPI0) && defined(CONFIG_SAMV7_SPI1) +#if defined(CONFIG_SAMV7_SPI0_MASTER) && defined(CONFIG_SAMV7_SPI1_MASTER) if (spino == 0) #endif -#if defined(CONFIG_SAMV7_SPI0) +#if defined(CONFIG_SAMV7_SPI0_MASTER) { sam_spi0_enableclk(); @@ -1854,10 +1854,10 @@ struct spi_dev_s *up_spiinitialize(int port) sam_configgpio(GPIO_SPI0_SPCK); } #endif -#if defined(CONFIG_SAMV7_SPI0) && defined(CONFIG_SAMV7_SPI1) +#if defined(CONFIG_SAMV7_SPI0_MASTER) && defined(CONFIG_SAMV7_SPI1_MASTER) else #endif -#if defined(CONFIG_SAMV7_SPI1) +#if defined(CONFIG_SAMV7_SPI1_MASTER) { sam_spi1_enableclk(); @@ -1938,4 +1938,4 @@ struct spi_dev_s *up_spiinitialize(int port) return &spics->spidev; } -#endif /* CONFIG_SAMV7_SPI0 || CONFIG_SAMV7_SPI1 */ +#endif /* CONFIG_SAMV7_SPI_MASTER */ diff --git a/arch/arm/src/samv7/sam_spi.h b/arch/arm/src/samv7/sam_spi.h index 47afad02fd9..cf8732059f4 100644 --- a/arch/arm/src/samv7/sam_spi.h +++ b/arch/arm/src/samv7/sam_spi.h @@ -46,6 +46,9 @@ #include #include "chip.h" +#include "sam_config.h" + +#ifdef CONFIG_SAMV7_SPI /**************************************************************************** * Pre-processor Definitions @@ -108,6 +111,43 @@ extern "C" * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: up_spiinitialize + * + * Description: + * Initialize the selected SPI port in master mode + * + * Input Parameter: + * cs - Chip select number (identifying the "logical" SPI port) + * + * Returned Value: + * Valid SPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +#if 0 /* Prototyped in include/nuttx/spi/spi.h */ +FAR struct spi_dev_s *up_spiinitialize(int port) +#endif + +/**************************************************************************** + * Name: up_spi_slave_initialize + * + * Description: + * Initialize the selected SPI port in slave mode. + * + * Input Parameter: + * port - Chip select number identifying the "logical" SPI port. Includes + * encoded port and chip select information. + * + * Returned Value: + * Valid SPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +#if 0 /* Prototyped in include/nuttx/spi/slave.h */ +FAR struct spi_sctrlr_s *up_spi_slave_initialize(int port); +#endif + /**************************************************************************** * Name: sam_spi[0|1]select, sam_spi[0|1]status, and sam_spi[0|1]cmddata * @@ -115,7 +155,7 @@ extern "C" * These external functions must be provided by board-specific logic. * They include: * - * o sam_spi[0|1]select is a functions tomanage the board-specific chip + * o sam_spi[0|1]select is a functions to manage the board-specific chip * selects * o sam_spi[0|1]status and sam_spi[0|1]cmddata: Implementations of the * status and cmddata methods of the SPI interface defined by struct @@ -142,9 +182,8 @@ extern "C" * ****************************************************************************/ -#ifdef CONFIG_SAMV7_SPI0 -struct spi_dev_s; -enum spi_dev_e; +struct spi_dev_s; /* Forward reference */ +enum spi_dev_e; /* Forward reference */ /**************************************************************************** * Name: sam_spi[0|1]select @@ -172,10 +211,10 @@ enum spi_dev_e; * ****************************************************************************/ -#ifdef CONFIG_SAMV7_SPI0 +#ifdef CONFIG_SAMV7_SPI0_MASTER void sam_spi0select(enum spi_dev_e devid, bool selected); #endif -#ifdef CONFIG_SAMV7_SPI1 +#ifdef CONFIG_SAMV7_SPI1_MASTER void sam_spi1select(enum spi_dev_e devid, bool selected); #endif @@ -226,14 +265,13 @@ uint8_t sam_spi1status(FAR struct spi_dev_s *dev, enum spi_dev_e devid); ****************************************************************************/ #ifdef CONFIG_SPI_CMDDATA -#ifdef CONFIG_SAMV7_SPI0 +#ifdef CONFIG_SAMV7_SPI0_MASTER int sam_spi0cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd); #endif -#ifdef CONFIG_SAMV7_SPI1 +#ifdef CONFIG_SAMV7_SPI1_MASTER int sam_spi1cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd); #endif -#endif -#endif /* CONFIG_SAMV7_SPI0 */ +#endif /* CONFIG_SPI_CMDDATA */ #undef EXTERN #if defined(__cplusplus) @@ -241,4 +279,5 @@ int sam_spi1cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd); #endif #endif /* __ASSEMBLY__ */ +#endif /* CONFIG_SAMV7_SPI */ #endif /* __ARCH_ARM_SRC_SAMV7_SAM_SPI_H */ diff --git a/arch/arm/src/samv7/sam_spi_slave.c b/arch/arm/src/samv7/sam_spi_slave.c new file mode 100644 index 00000000000..71e54057df1 --- /dev/null +++ b/arch/arm/src/samv7/sam_spi_slave.c @@ -0,0 +1,1286 @@ +/**************************************************************************** + * arch/arm/src/samv7/sam_spi_slave.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Authors: 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 + +#include +#include +#include +#include + +#include "up_arch.h" + +#include "sam_config.h" +#include "sam_gpio.h" +#include "sam_periphclks.h" +#include "sam_spi.h" + +#include "chip/sam_spi.h" +#include "chip/sam_pinmap.h" +#include + +#ifdef CONFIG_SAMV7_SPI_SLAVE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_SAMV7_SPI_SLAVE_QSIZE +# define CONFIG_SAMV7_SPI_SLAVE_QSIZE 8 +#endif + +/* Debug *******************************************************************/ +/* Check if SPI debug is enabled (non-standard.. no support in + * include/debug.h + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_SPI +#endif + +#ifdef CONFIG_DEBUG_SPI +# define spidbg lldbg +# ifdef CONFIG_DEBUG_VERBOSE +# define spivdbg lldbg +# else +# define spivdbg(x...) +# endif +#else +# define spidbg(x...) +# define spivdbg(x...) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The overall state of one SPI controller */ + +struct sam_spidev_s +{ + struct spi_sctrlr_s sctrlr; /* Externally visible part of the SPI slave + * controller interface */ + struct spi_sdev_s *sdev; /* Bound SPI slave device interface */ + xcpt_t handler; /* SPI interrupt handler */ + uint32_t base; /* SPI controller register base address */ + sem_t spisem; /* Assures mutually exclusive access to SPI */ + uint16_t outval; /* Default shift-out value */ + uint16_t irq; /* SPI IRQ number */ + uint8_t mode; /* Mode 0,1,2,3 */ + uint8_t nbits; /* Width of word in bits (8 to 16) */ + uint8_t spino; /* SPI controller number (0 or 1) */ + bool initialized; /* True: Controller has been initialized */ + bool nss; /* True: Chip selected */ + + /* Output queue */ + + uint8_t head; /* Location of next value */ + uint8_t tail; /* Index of first value */ + + uint16_t outq[CONFIG_SAMV7_SPI_SLAVE_QSIZE]; + + /* Debug stuff */ + +#ifdef CONFIG_SAMV7_SPI_REGDEBUG + bool wrlast; /* Last was a write */ + uint32_t addresslast; /* Last address */ + uint32_t valuelast; /* Last value */ + int ntimes; /* Number of times */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Helpers */ + +#ifdef CONFIG_SAMV7_SPI_REGDEBUG +static bool spi_checkreg(struct sam_spidev_s *priv, bool wr, + uint32_t value, uint32_t address); +#else +# define spi_checkreg(priv,wr,value,address) (false) +#endif + +static uint32_t spi_getreg(struct sam_spidev_s *priv, + unsigned int offset); +static void spi_putreg(struct sam_spidev_s *priv, uint32_t value, + unsigned int offset); + +#if defined(CONFIG_DEBUG_SPI) && defined(CONFIG_DEBUG_VERBOSE) +static void spi_dumpregs(struct sam_spidev_s *priv, const char *msg); +#else +# define spi_dumpregs(priv,msg) +#endif + +static void spi_semtake(struct sam_spidev_s *priv); +#define spi_semgive(priv) (sem_post(&(priv)->spisem)) + +/* Interrupt Handling */ + +static int spi_interrupt(struct sam_spidev_s *priv); +#ifdef CONFIG_SAMV7_SPI0_SLAVE +static int spi0_interrupt(int irq, void *context); +#endif +#ifdef CONFIG_SAMV7_SPI1_SLAVE +static int spi1_interrupt(int irq, void *context); +#endif + +/* SPI Helpers */ + +static uint16_t spi_dequeue(struct sam_spidev_s *priv); +static void spi_setmode(struct sam_spidev_s *priv, + enum spi_smode_e mode); +static void spi_setbits(struct sam_spidev_s *priv, + int nbits); + +/* SPI slave controller methods */ + +static void spi_bind(struct spi_sctrlr_s *sctrlr, + struct spi_sdev_s *sdev, enum spi_smode_e mode, + int nbits); +static void spi_unbind(struct spi_sctrlr_s *sctrlr); +static int spi_enqueue(struct spi_sctrlr_s *sctrlr, uint16_t data); +static bool spi_qfull(struct spi_sctrlr_s *sctrlr); +static void spi_qflush(struct spi_sctrlr_s *sctrlr); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This array maps chip select numbers (0-3) to CSR register offsets */ + +static const uint8_t g_csroffset[4] = +{ + SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR1_OFFSET, + SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR3_OFFSET +}; + +/* SPI slave controller driver operations */ + +static const struct spi_sctrlrops_s g_sctrlr_ops = +{ + .bind = spi_bind, + .unbind = spi_unbind, + .enqueue = spi_enqueue, + .qfull = spi_qfull, + .qflush = spi_qflush, +}; + +#ifdef CONFIG_SAMV7_SPI0_SLAVE +/* This is the overall state of the SPI0 controller */ + +static struct sam_spidev_s g_spi0_sctrlr; +#endif + +#ifdef CONFIG_SAMV7_SPI1_SLAVE +/* This is the overall state of the SPI0 controller */ + +static struct sam_spidev_s g_spi1_sctrlr; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_checkreg + * + * Description: + * Check if the current register access is a duplicate of the preceding. + * + * Input Parameters: + * value - 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_SAMV7_SPI_REGDEBUG +static bool spi_checkreg(struct sam_spidev_s *priv, bool wr, uint32_t value, + uint32_t address) +{ + if (wr == priv->wrlast && /* Same kind of access? */ + value == priv->valuelast && /* Same value? */ + address == priv->addresslast) /* 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 */ + + lldbg("...[Repeats %d times]...\n", priv->ntimes); + } + + /* Save information about the new access */ + + priv->wrlast = wr; + priv->valuelast = value; + priv->addresslast = address; + priv->ntimes = 0; + } + + /* Return true if this is the first time that we have done this operation */ + + return true; +} +#endif + +/**************************************************************************** + * Name: spi_getreg + * + * Description: + * Read an SPI register + * + ****************************************************************************/ + +static uint32_t spi_getreg(struct sam_spidev_s *priv, unsigned int offset) +{ + uint32_t address = priv->base + offset; + uint32_t value = getreg32(address); + +#ifdef CONFIG_SAMV7_SPI_REGDEBUG + if (spi_checkreg(priv, false, value, address)) + { + lldbg("%08x->%08x\n", address, value); + } +#endif + + return value; +} + +/**************************************************************************** + * Name: spi_putreg + * + * Description: + * Write a value to an SPI register + * + ****************************************************************************/ + +static void spi_putreg(struct sam_spidev_s *priv, uint32_t value, + unsigned int offset) +{ + uint32_t address = priv->base + offset; + +#ifdef CONFIG_SAMV7_SPI_REGDEBUG + if (spi_checkreg(priv, true, value, address)) + { + lldbg("%08x<-%08x\n", address, value); + } +#endif + + putreg32(value, address); +} + +/**************************************************************************** + * Name: spi_dumpregs + * + * Description: + * Dump the contents of all SPI registers + * + * Input Parameters: + * priv - The SPI controller to dump + * msg - Message to print before the register data + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_SPI) && defined(CONFIG_DEBUG_VERBOSE) +static void spi_dumpregs(struct sam_spidev_s *priv, const char *msg) +{ + spivdbg("%s:\n", msg); + spivdbg(" MR:%08x SR:%08x IMR:%08x\n", + getreg32(priv->base + SAM_SPI_MR_OFFSET), + getreg32(priv->base + SAM_SPI_SR_OFFSET), + getreg32(priv->base + SAM_SPI_IMR_OFFSET)); + spivdbg(" CSR0:%08x CSR1:%08x CSR2:%08x CSR3:%08x\n", + getreg32(priv->base + SAM_SPI_CSR0_OFFSET), + getreg32(priv->base + SAM_SPI_CSR1_OFFSET), + getreg32(priv->base + SAM_SPI_CSR2_OFFSET), + getreg32(priv->base + SAM_SPI_CSR3_OFFSET)); + spivdbg(" WPCR:%08x WPSR:%08x\n", + getreg32(priv->base + SAM_SPI_WPCR_OFFSET), + getreg32(priv->base + SAM_SPI_WPSR_OFFSET)); +} +#endif + +/**************************************************************************** + * Name: spi_semtake + * + * Description: + * Take the semaphore that enforces mutually exclusive access to SPI + * resources, handling any exceptional conditions + * + * Input Parameters: + * priv - A reference to the MCAN peripheral state + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void spi_semtake(struct sam_spidev_s *priv) +{ + int ret; + + /* Wait until we successfully get the semaphore. EINTR is the only + * expected 'failure' (meaning that the wait for the semaphore was + * interrupted by a signal. + */ + + do + { + ret = sem_wait(&priv->spisem); + DEBUGASSERT(ret == 0 || errno == EINTR); + } + while (ret < 0); +} + +/**************************************************************************** + * Name: spi_interrupt + * + * Description: + * Common SPI interrupt handler + * + * Input Parameters: + * priv - SPI controller CS state + * + * Returned Value: + * Standard interrupt return value. + * + ****************************************************************************/ + +static int spi_interrupt(struct sam_spidev_s *priv) +{ + uint32_t sr; + uint32_t imr; + uint32_t pending; + uint32_t regval; + + /* We loop because the TDRE interrupt will probably immediately follow the + * RDRF interrupt and we might be able to catch it in this handler + * execution. + */ + + for (;;) + { + /* Get the current set of pending/enabled interrupts */ + + sr = spi_getreg(priv, SAM_SPI_SR_OFFSET); + imr = spi_getreg(priv, SAM_SPI_IMR_OFFSET); + pending = sr & imr; + + /* Return from the interrupt handler when all pending interrupts have + * been processed. + */ + + if (pending == 0) + { + return OK; + } + + /* TThe SPI waits until NSS goes active before receiving the serial + * clock from an external master. When NSS falls, the clock is + * validated and the data is loaded in the SPI_RDR depending on the + * BITS field configured in the SPI_CSR0. These bits are processed + * following a phase and a polarity defined respectively by the NCPHA + * and CPOL bits in the SPI_CSR0. + * + * When all bits are processed, the received data is transferred in + * the SPI_RDR and the RDRF bit rises. If the SPI_RDR has not been + * read before new data is received, the Overrun Error Status (OVRES) + * bit in the SPI_SR is set. As long as this flag is set, data is + * loaded in the SPI_RDR. The user must read SPI_SR to clear the OVRES + * bit. + */ + +#ifdef CONFIG_DEBUG_SPI + /* Check the RX data overflow condition */ + + if ((pending & SPI_INT_OVRES) != 0) + { + /* If debug is enabled, report any overrun errors */ + + spidbg("Error: Overrun (OVRES): %08x\n", pending); + + /* OVRES was cleared by the status read. */ + } +#endif + + /* Check for the availability of RX data */ + + if ((pending & SPI_INT_RDRF) != 0) + { + uint16_t data; + + /* We get no indication of the falling edge of NSS. But if we are + * here then it must have fallen. + */ + + if (priv->nss) + { + priv->nss = false; + SPI_SDEV_SELECT(priv->sdev, true); + } + + /* Read the RDR to get the data and to clear the pending RDRF + * interrupt. + */ + + regval = spi_getreg(priv, SAM_SPI_RDR_OFFSET); + data = (uint16_t)((regval & SPI_RDR_RD_MASK) >> SPI_RDR_RD_SHIFT); + + /* Enable TXDR/OVRE interrupts */ + + regval = (SPI_INT_TDRE | SPI_INT_UNDES); + spi_putreg(priv, regval, SAM_SPI_IER_OFFSET); + + /* Report the receipt of data to the SPI device driver */ + + SPI_SDEV_RECEIVE(priv->sdev, data); + } + + /* When a transfer starts, the data shifted out is the data present + * in the Shift register. If no data has been written in the SPI_TDR, + * the last data received is transferred. If no data has been received + * since the last reset, all bits are transmitted low, as the Shift + * register resets to 0. + * + * When a first data is written in the SPI_TDR, it is transferred + * immediately in the Shift register and the TDRE flag rises. If new + * data is written, it remains in the SPI_TDR until a transfer occurs, + * i.e., NSS falls and there is a valid clock on the SPCK pin. When + * the transfer occurs, the last data written in the SPI_TDR is + * transferred in the Shift register and the TDRE flag rises. This + * enables frequent updates of critical variables with single transfers. + * + * Then, new data is loaded in the Shift register from the SPI_TDR. If + * no character is ready to be transmitted, i.e., no character has been + * written in the SPI_TDR since the last load from the SPI_TDR to the + * Shift register, the SPI_TDR is retransmitted. In this case the + * Underrun Error Status Flag (UNDES) is set in the SPI_SR. + */ + +#ifdef CONFIG_DEBUG_SPI + /* Check the TX data underflow condition */ + + if ((pending & SPI_INT_UNDES) != 0) + { + /* If debug is enabled, report any overrun errors */ + + spidbg("Error: Underrun (UNDEX): %08x\n", pending); + + /* UNDES was cleared by the status read. */ + } +#endif + + /* Output the next TX data */ + + if ((pending & SPI_INT_TDRE) != 0) + { + /* Get the next output value and write it to the TDR + * The TDRE interrupt is cleared by writing to the from RDR. + */ + + regval = spi_dequeue(priv); + spi_putreg(priv, regval, SAM_SPI_TDR_OFFSET); + } + + /* The SPI slave hardware provides only an event when NSS rises + * which may or many not happen at the end of a transfer. NSSR was + * cleared by the status read. + */ + + if ((pending & SPI_INT_NSSR) != 0) + { + /* Disable further TXDR/OVRE interrupts */ + + regval = (SPI_INT_TDRE | SPI_INT_UNDES); + spi_putreg(priv, regval, SAM_SPI_IDR_OFFSET); + + /* Report the state change to the SPI device driver */ + + priv->nss = true; + SPI_SDEV_SELECT(priv->sdev, false); + } + } + + return OK; +} + +/**************************************************************************** + * Name: spi0_interrupt + * + * Description: + * SPI0 interrupt handler + * + * Input Parameters: + * Standard interrupt input parameters + * + * Returned Value: + * Standard interrupt return value. + * + ****************************************************************************/ + +#ifdef CONFIG_SAMV7_SPI0_SLAVE +static int spi0_interrupt(int irq, void *context) +{ + return spi_interrupt(&g_spi0_sctrlr); +} +#endif + +/**************************************************************************** + * Name: spi1_interrupt + * + * Description: + * SPI1 interrupt handler + * + * Input Parameters: + * Standard interrupt input parameters + * + * Returned Value: + * Standard interrupt return value. + * + ****************************************************************************/ + +#ifdef CONFIG_SAMV7_SPI1_SLAVE +static int spi1_interrupt(int irq, void *context) +{ + return spi_interrupt(&g_spi1_sctrlr); +} +#endif + +/**************************************************************************** + * Name: spi_dequeue + * + * Description: + * Return the next queued output value. If nothing is in the output queue, + * then return the last value obtained from getdata(); + * + * Input Parameters: + * priv - SPI controller CS state + * + * Assumptions: + * Called only from the SPI interrupt handler so all interrupts are + * disabled. + * + ****************************************************************************/ + +static uint16_t spi_dequeue(struct sam_spidev_s *priv) +{ + uint32_t regval; + uint16_t ret; + int next; + + /* Is the queue empty? */ + + if (priv->head != priv->tail) + { + /* No, take the oldest value from the tail of the cicular buffer */ + + ret = priv->outq[priv->tail]; + + /* Update the tail index, handling wraparound */ + + next = priv->tail + 1; + if (next >= CONFIG_SAMV7_SPI_SLAVE_QSIZE) + { + next = 0; + } + + priv->tail = next; + + /* If the queue is empty Disable further TXDR/OVRE interrupts until + * spi_enqueue() is called or until we received another command. We + * do this only for the case where NSS is non-functional (tied to + * ground) and we need to end transfers in some fashion. + */ + + if (priv->head == next) + { + regval = (SPI_INT_TDRE | SPI_INT_UNDES); + spi_putreg(priv, regval, SAM_SPI_IDR_OFFSET); + } + } + else + { + /* Yes, return the last value we got from the getdata() method */ + + ret = priv->outval; + + /* Disable further TXDR/OVRE interrupts until spi_enqueue() is called. */ + + regval = (SPI_INT_TDRE | SPI_INT_UNDES); + spi_putreg(priv, regval, SAM_SPI_IDR_OFFSET); + } + + return ret; +} + +/**************************************************************************** + * Name: spi_setmode + * + * Description: + * Set the SPI mode. See enum spi_smode_e for mode definitions + * + * Input Parameters: + * priv - SPI device data structure + * mode - The SPI mode requested + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void spi_setmode(struct sam_spidev_s *priv, enum spi_smode_e mode) +{ + uint32_t regval; + + spivdbg("mode=%d\n", mode); + + /* Has the mode changed? */ + + if (mode != priv->mode) + { + /* Yes... Set the mode appropriately: + * + * SPI CPOL NCPHA + * MODE + * 0 0 1 + * 1 0 0 + * 2 1 1 + * 3 1 0 + */ + + regval = spi_getreg(priv, SAM_SPI_CSR0_OFFSET); + regval &= ~(SPI_CSR_CPOL | SPI_CSR_NCPHA); + + switch (mode) + { + case SPISLAVE_MODE0: /* CPOL=0; NCPHA=1 */ + regval |= SPI_CSR_NCPHA; + break; + + case SPISLAVE_MODE1: /* CPOL=0; NCPHA=0 */ + break; + + case SPISLAVE_MODE2: /* CPOL=1; NCPHA=1 */ + regval |= (SPI_CSR_CPOL | SPI_CSR_NCPHA); + break; + + case SPISLAVE_MODE3: /* CPOL=1; NCPHA=0 */ + regval |= SPI_CSR_CPOL; + break; + + default: + DEBUGASSERT(FALSE); + return; + } + + spi_putreg(priv, regval, SAM_SPI_CSR0_OFFSET); + spivdbg("csr0=%08x\n", regval); + + /* Save the mode so that subsequent re-configurations will be faster */ + + priv->mode = mode; + } +} + +/**************************************************************************** + * Name: spi_setbits + * + * Description: + * Set the number if bits per word. + * + * Input Parameters: + * priv - SPI device data structure + * nbits - The number of bits requests + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void spi_setbits(struct sam_spidev_s *priv, int nbits) +{ + uint32_t regval; + + spivdbg("nbits=%d\n", nbits); + DEBUGASSERT(priv && nbits > 7 && nbits < 17); + + /* Has the number of bits changed? */ + + if (nbits != priv->nbits) + { + /* Yes... Set number of bits appropriately */ + + regval = spi_getreg(priv, SAM_SPI_CSR0_OFFSET); + regval &= ~SPI_CSR_BITS_MASK; + regval |= SPI_CSR_BITS(nbits); + spi_putreg(priv, regval, SAM_SPI_CSR0_OFFSET); + + spivdbg("csr0=%08x\n", regval); + + /* Save the selection so the subsequence re-configurations will be faster */ + + priv->nbits = nbits; + } +} + +/**************************************************************************** + * Name: spi_bind + * + * Description: + * Bind the SPI slave device interface to the SPI slave controller + * interface and configure the SPI interface. Upon return, the SPI + * slave controller driver is fully operational and ready to perform + * transfers. + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * sdev - SPI slave device interface instance + * mode - The SPI mode requested + * nbits - The number of bits requests. + * If value is greater > 0 then it implies MSB first + * If value is below < 0, then it implies LSB first with -nbits + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void spi_bind(struct spi_sctrlr_s *sctrlr, + struct spi_sdev_s *sdev, enum spi_smode_e mode, + int nbits) +{ + struct sam_spidev_s *priv = (struct sam_spidev_s *)sctrlr; + uint32_t regval; + + spivdbg("sdev=%p mode=%d nbits=%d\n", sdv, mode, nbits); + + DEBUGASSERT(priv != NULL && priv->sdev == NULL && sdev != NULL); + + /* Get exclusive access to the SPI device */ + + spi_semtake(priv); + + /* Bind the SPI slave device interface instance to the SPI slave + * controller interface. + */ + + priv->sdev = sdev; + + /* Call the slaved device's select() and cmddata() methods to indicate + * the initial state of the chip select and command/data discretes. + * + * NOTE: Unless we reconfigure the NSS GPIO pin, it may not be possible + * to read the NSS pin value (I haven't actually tried just reading it). + * And, since the is no interrupt on the falling edge of NSS, we get no + * notification when we are selected... not until the arrival of data. + * + * REVISIT: A board-level interface would be required in order to support + * the Command/Data indication (not yet impklemented). + */ + + SPI_SDEV_SELECT(sdev, false); +#warning Missing logic + SPI_SDEV_CMDDATA(sdev, false); + + /* Discard any queued data */ + + priv->head = 0; + priv->tail = 0; + + /* Call the slave device's getdata() method to get the value that will + * be shifted out the SPI clock is detected. + */ + + priv->outval = SPI_SDEV_GETDATA(sdev); + spi_putreg(priv, priv->outval, SAM_SPI_TDR_OFFSET); + + /* Setup to begin normal SPI operation */ + + spi_setmode(priv, mode); + spi_setbits(priv, nbits); + + /* Clear pending interrupts by reading the SPI Status Register */ + + regval = spi_getreg(priv, SAM_SPI_SR_OFFSET); + UNUSED(regval); + + /* Enable SPI interrupts (already enabled at the NVIC): + * + * Data Transfer: + * SPI_INT_RDRF - Receive Data Register Full Interrupt + * SPI_INT_TDRE - Transmit Data Register Empty Interrupt + * SPI_INT_NSSR - NSS Rising Interrupt + * + * Transfer Errors (for DEBUG purposes only): + * SPI_INT_OVRES - Overrun Error Interrupt + * SPI_INT_UNDES - Underrun Error Status Interrupt (slave) + * + * Not Used: + * SPI_INT_MODF - Mode Fault Error Interrupt + * SPI_INT_TXEMPTY - Transmission Registers Empty Interrupt + * + * TX interrupts (SPI_INT_TDRE and SPI_INT_UNDES) are not enabled until + * the transfer of data actually starts. + */ + + regval = (SPI_INT_RDRF | SPI_INT_NSSR); +#ifdef CONFIG_DEBUG_SPI + regval |= SPI_INT_OVRES; +#endif + + spi_putreg(priv, regval, SAM_SPI_IER_OFFSET); + + spi_semgive(priv); +} + +/**************************************************************************** + * Name: spi_unbind + * + * Description: + * Un-bind the SPI slave device interface from the SPI slave controller + * interface. Reset the SPI interface and restore the SPI slave + * controller driver to its initial state, + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void spi_unbind(struct spi_sctrlr_s *sctrlr) +{ + struct sam_spidev_s *priv = (struct sam_spidev_s *)sctrlr; + + DEBUGASSERT(priv != NULL); + spivdbg("Unbinding %p\n", priv->sdev); + + DEBUGASSERT(priv->sdev != NULL); + + /* Get exclusive access to the SPI device */ + + spi_semtake(priv); + + /* Disable SPI interrupts (still enabled at the NVIC) */ + + spi_putreg(priv, SPI_INT_ALL, SAM_SPI_IDR_OFFSET); + + /* Unbind the SPI slave interface */ + + priv->sdev = NULL; + + /* Disable the SPI peripheral */ + + spi_putreg(priv, SPI_CR_SPIDIS, SAM_SPI_CR_OFFSET); + + /* Execute a software reset of the SPI (twice) */ + + spi_putreg(priv, SPI_CR_SWRST, SAM_SPI_CR_OFFSET); + spi_putreg(priv, SPI_CR_SWRST, SAM_SPI_CR_OFFSET); + + spi_semgive(priv); +} + +/**************************************************************************** + * Name: spi_enqueue + * + * Description: + * Enqueue the next value to be shifted out from the interface. This adds + * the word the controller driver for a subsequent transfer but has no + * effect on anyin-process or currently "committed" transfers + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * data - Command/data mode data value to be shifted out. The width of + * the data must be the same as the nbits parameter previously + * provided to the bind() methods. + * + * Returned Value: + * Zero if the word was successfully queue; A negated errno valid is + * returned on any failure to enqueue the word (such as if the queue is + * full). + * + ****************************************************************************/ + +static int spi_enqueue(struct spi_sctrlr_s *sctrlr, uint16_t data) +{ + struct sam_spidev_s *priv = (struct sam_spidev_s *)sctrlr; + irqstate_t flags; + uint32_t regval; + int next; + int ret; + + spivdbg("data=%04x\n", data); + DEBUGASSERT(priv != NULL && priv->sdev != NULL); + + /* Get exclusive access to the SPI device */ + + spi_semtake(priv); + + /* Check if this word would overflow the circular buffer + * + * Interrupts are disabled briefly. + */ + + flags = irqsave(); + next = priv->head + 1; + if (next >= CONFIG_SAMV7_SPI_SLAVE_QSIZE) + { + next = 0; + } + + if (next == priv->tail) + { + ret = -ENOSPC; + } + else + { + /* Save this new word as the next word to shifted out. The current + * word written to the TX data registers is "committed" and will not + * be overwritten. + */ + + priv->outq[priv->head] = data; + priv->head = next; + ret = OK; + + /* Enable TX interrupts if we have begun the transfer */ + + if (!priv->nss) + { + /* Enable TXDR/OVRE interrupts */ + + regval = (SPI_INT_TDRE | SPI_INT_UNDES); + spi_putreg(priv, regval, SAM_SPI_IER_OFFSET); + } + } + + irqrestore(flags); + spi_semgive(priv); + return ret; +} + +/**************************************************************************** + * Name: spi_qfull + * + * Description: + * Return true if the queue is full or false if there is space to add an + * additional word to the queue. + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * + * Returned Value: + * true if the output wueue is full + * + ****************************************************************************/ + +static bool spi_qfull(struct spi_sctrlr_s *sctrlr) +{ + struct sam_spidev_s *priv = (struct sam_spidev_s *)sctrlr; + irqstate_t flags; + int next; + bool ret; + + DEBUGASSERT(priv != NULL && priv->sdev != NULL); + + /* Get exclusive access to the SPI device */ + + spi_semtake(priv); + + /* Check if another word would overflow the circular buffer + * + * Interrupts are disabled briefly. + */ + + flags = irqsave(); + next = priv->head + 1; + if (next >= CONFIG_SAMV7_SPI_SLAVE_QSIZE) + { + next = 0; + } + + ret = (next == priv->tail); + irqrestore(flags); + spi_semgive(priv); + return ret; +} + +/**************************************************************************** + * Name: spi_qflush + * + * Description: + * Discard all saved values in the output queue. On return from this + * function the output queue will be empty. Any in-progress or otherwise + * "committed" output values may not be flushed. + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void spi_qflush(struct spi_sctrlr_s *sctrlr) +{ + struct sam_spidev_s *priv = (struct sam_spidev_s *)sctrlr; + irqstate_t flags; + + spivdbg("data=%04x\n", data); + + DEBUGASSERT(priv != NULL && priv->sdev != NULL); + + /* Get exclusive access to the SPI device */ + + spi_semtake(priv); + + /* Mark the buffer empty, momentarily disabling interrupts */ + + flags = irqsave(); + priv->head = 0; + priv->tail = 0; + irqrestore(flags); + spi_semgive(priv); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sam_spi_slave_initialize + * + * Description: + * Initialize the selected SPI port in slave mode. + * + * Input Parameter: + * port - Chip select number identifying the "logical" SPI port. Includes + * encoded port and chip select information. + * + * Returned Value: + * Valid SPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct spi_sctrlr_s *sam_spi_slave_initialize(int port) +{ + struct sam_spidev_s *priv; + int spino = (port & __SPI_SPI_MASK) >> __SPI_SPI_SHIFT; + irqstate_t flags; + uint32_t regval; + + /* The support SAM parts have only a single SPI port */ + + spivdbg("port: %d spino: %d\n", port, spino); + +#if defined(CONFIG_SAMV7_SPI0_SLAVE) && defined(CONFIG_SAMV7_SPI1_SLAVE) + DEBUGASSERT(spino >= 0 && spino <= 1); +#elif defined(CONFIG_SAMV7_SPI0_SLAVE) + DEBUGASSERT(spino == 0); +#else + DEBUGASSERT(spino == 1); +#endif + + /* Allocate a new state structure for this chip select. NOTE that there + * is no protection if the same chip select is used in two different + * chip select structures. + */ + + priv = (struct sam_spidev_s *)zalloc(sizeof(struct sam_spidev_s)); + if (!priv) + { + spidbg("ERROR: Failed to allocate a chip select structure\n"); + return NULL; + } + + /* Set up the initial state for this chip select structure. Other fields + * were zeroed by zalloc(). + */ + + /* Initialize the SPI operations */ + + priv->sctrlr.ops = &g_sctrlr_ops; + + /* Save the SPI controller number */ + + priv->spino = spino; + + /* Has the SPI hardware been initialized? */ + + if (!priv->initialized) + { + /* Enable clocking to the SPI block */ + + flags = irqsave(); +#if defined(CONFIG_SAMV7_SPI0_SLAVE) && defined(CONFIG_SAMV7_SPI1_SLAVE) + if (spino == 0) +#endif +#if defined(CONFIG_SAMV7_SPI0_SLAVE) + { + /* Set the SPI0 register base address and interrupt information */ + + priv->base = SAM_SPI0_BASE, + priv->irq = SAM_IRQ_SPI0; + priv->handler = spi0_interrupt; + + /* Enable peripheral clocking to SPI0 */ + + sam_spi0_enableclk(); + + /* Configure multiplexed pins as connected on the board. */ + + sam_configgpio(GPIO_SPI0_MISO); /* Output */ + sam_configgpio(GPIO_SPI0_MOSI); /* Input */ + sam_configgpio(GPIO_SPI0_SPCK); /* Drives slave */ + sam_configgpio(GPIO_SPI0_NSS); /* aka NPCS0 */ + } +#endif +#if defined(CONFIG_SAMV7_SPI0_SLAVE) && defined(CONFIG_SAMV7_SPI1_SLAVE) + else +#endif +#if defined(CONFIG_SAMV7_SPI1_SLAVE) + { + /* Set the SPI1 register base address and interrupt information */ + + priv->base = SAM_SPI1_BASE, + priv->irq = SAM_IRQ_SPI1; + priv->handler = spi1_interrupt; + + /* Enable peripheral clocking to SPI1 */ + + sam_spi1_enableclk(); + + /* Configure multiplexed pins as connected on the board. */ + + sam_configgpio(GPIO_SPI1_MISO); /* Output */ + sam_configgpio(GPIO_SPI1_MOSI); /* Input */ + sam_configgpio(GPIO_SPI1_SPCK); /* Drives slave */ + sam_configgpio(GPIO_SPI0_NSS); /* aka NPCS0 */ + } +#endif + + /* Disable the SPI peripheral */ + + spi_putreg(priv, SPI_CR_SPIDIS, SAM_SPI_CR_OFFSET); + + /* Execute a software reset of the SPI (twice) */ + + spi_putreg(priv, SPI_CR_SWRST, SAM_SPI_CR_OFFSET); + spi_putreg(priv, SPI_CR_SWRST, SAM_SPI_CR_OFFSET); + irqrestore(flags); + + /* Configure the SPI mode register */ + + spi_putreg(priv, SPI_MR_SLAVE | SPI_MR_MODFDIS, SAM_SPI_MR_OFFSET); + + /* And enable the SPI */ + + spi_putreg(priv, SPI_CR_SPIEN, SAM_SPI_CR_OFFSET); + up_mdelay(20); + + /* Flush any pending interrupts/transfers */ + + (void)spi_getreg(priv, SAM_SPI_SR_OFFSET); + (void)spi_getreg(priv, SAM_SPI_RDR_OFFSET); + + /* Initialize the SPI semaphore that enforces mutually exclusive + * access to the SPI registers. + */ + + sem_init(&priv->spisem, 0, 1); + priv->nss = true; + priv->initialized = true; + + /* Disable all SPI interrupts at the SPI peripheral */ + + spi_putreg(priv, SPI_INT_ALL, SAM_SPI_IDR_OFFSET); + + /* Attach and enable interrupts at the NVIC */ + + DEBUGVERIFY(irq_attach(priv->irq, priv->handler)); + up_enable_irq(priv->irq); + + spi_dumpregs(priv, "After initialization"); + } + + /* Set to mode=0 and nbits=8 */ + + regval = spi_getreg(priv, SAM_SPI_CSR0_OFFSET); + regval &= ~(SPI_CSR_CPOL | SPI_CSR_NCPHA | SPI_CSR_BITS_MASK); + regval |= (SPI_CSR_NCPHA | SPI_CSR_BITS(8)); + spi_putreg(priv, regval, SAM_SPI_CSR0_OFFSET); + + priv->nbits = 8; + spivdbg("csr[offset=%02x]=%08x\n", offset, regval); + + return &priv->sctrlr; +} +#endif /* CONFIG_SAMV7_SPI_SLAVE */ diff --git a/arch/arm/src/samv7/sam_usbdevhs.c b/arch/arm/src/samv7/sam_usbdevhs.c index e6c20e11ea5..d912c400e29 100644 --- a/arch/arm/src/samv7/sam_usbdevhs.c +++ b/arch/arm/src/samv7/sam_usbdevhs.c @@ -72,8 +72,10 @@ #include "up_internal.h" #include "cache.h" +#include "chip.h" #include "sam_periphclks.h" #include "chip/sam_usbhs.h" +#include "sam_clockconfig.h" #include "sam_usbdev.h" #if defined(CONFIG_USBDEV) && defined(CONFIG_SAMV7_USBDEVHS) @@ -105,7 +107,6 @@ /* Not yet supported */ #undef CONFIG_SAMV7_USBDEVHS_SCATTERGATHER -#undef CONFIG_SAMV7_USBDEVHS_LOWPOWER /* Driver Definitions *******************************************************/ /* Initial interrupt mask: Reset + Suspend + Correct Transfer */ @@ -146,6 +147,36 @@ #define sam_rqempty(q) ((q)->head == NULL) #define sam_rqpeek(q) ((q)->head) +/* Buffer Alignment ********************************************************* + * + * DMA buffers be aligned the 8-byte (2 word boundaries). However, if the + * data cache is enabled the a higher level of alignment is required. That + * is because the data will need to be invalidated and that cache + * invalidation will occur in multiples of full cache lines. + */ + +#ifdef CONFIG_ARMV7M_DCACHE +/* Align to the cache line size which we assume is >= 8 */ + +# define USBHS_ALIGN ARMV7M_DCACHE_LINESIZE +# define USBHS_ALIGN_MASK (USBHS_ALIGN-1) +# define USBHS_ALIGN_DOWN(n) ((n) & ~USBHS_ALIGN_MASK) +# define USBHS_ALIGN_UP(n) (((n) + USBHS_ALIGN_MASK) & ~USBHS_ALIGN_MASK) + +# ifndef CONFIG_ARMV7M_DCACHE_WRITETHROUGH +# warning !!! This driver will not work without CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y!!! +# endif + +#else +/* Use the minimum alignment requirement */ + +# define USBHS_ALIGN 8 +# define USBHS_ALIGN_MASK 7 +# define USBHS_ALIGN_DOWN(n) ((n) & ~7) +# define USBHS_ALIGN_UP(n) (((n) + 7) & ~7) + +#endif + /* USB trace ****************************************************************/ /* Trace error codes */ @@ -174,11 +205,10 @@ #define SAM_TRACEERR_EPRESERVE 0x0017 #define SAM_TRACEERR_NCFGOK 0x0018 #define SAM_TRACEERR_INVALIDCTRLREQ 0x0019 -#define SAM_TRACEERR_INVALIDPARMS 0x001a -#define SAM_TRACEERR_IRQREGISTRATION 0x001b -#define SAM_TRACEERR_NOTCONFIGURED 0x001c -#define SAM_TRACEERR_REQABORTED 0x001d -#define SAM_TRACEERR_TXINERR 0x001e +#define SAM_TRACEERR_IRQREGISTRATION 0x001a +#define SAM_TRACEERR_NOTCONFIGURED 0x001b +#define SAM_TRACEERR_REQABORTED 0x001c +#define SAM_TRACEERR_TXINERR 0x001d /* Trace interrupt codes */ @@ -191,32 +221,35 @@ #define SAM_TRACEINTID_DMAEOB 0x0007 #define SAM_TRACEINTID_DMAEOC 0x0008 #define SAM_TRACEINTID_ENDRESET 0x0009 -#define SAM_TRACEINTID_EP 0x0001 +#define SAM_TRACEINTID_EP 0x000a #define SAM_TRACEINTID_EP0SETUPIN 0x000b #define SAM_TRACEINTID_EP0SETUPOUT 0x000c #define SAM_TRACEINTID_EP0SETUPSETADDRESS 0x000d -#define SAM_TRACEINTID_EPGETSTATUS 0x000e -#define SAM_TRACEINTID_EPINQEMPTY 0x000f -#define SAM_TRACEINTID_EPOUTQEMPTY 0x0010 -#define SAM_TRACEINTID_GETCONFIG 0x0011 -#define SAM_TRACEINTID_GETSETDESC 0x0012 -#define SAM_TRACEINTID_GETSETIF 0x0013 -#define SAM_TRACEINTID_GETSTATUS 0x0014 -#define SAM_TRACEINTID_IFGETSTATUS 0x0015 -#define SAM_TRACEINTID_INTERRUPT 0x0016 -#define SAM_TRACEINTID_INTSOF 0x0017 -#define SAM_TRACEINTID_INTMSOF 0x0018 -#define SAM_TRACEINTID_NOSTDREQ 0x0019 -#define SAM_TRACEINTID_PENDING 0x001a -#define SAM_TRACEINTID_RXRDY 0x001b -#define SAM_TRACEINTID_RXSETUP 0x001c -#define SAM_TRACEINTID_SETCONFIG 0x001d -#define SAM_TRACEINTID_SETFEATURE 0x001e -#define SAM_TRACEINTID_STALLSNT 0x001f -#define SAM_TRACEINTID_SYNCHFRAME 0x0020 -#define SAM_TRACEINTID_TXINI 0x0021 -#define SAM_TRACEINTID_UPSTRRES 0x0022 -#define SAM_TRACEINTID_WAKEUP 0x0023 +#define SAM_TRACEINTID_EPDMAINT 0x000e +#define SAM_TRACEINTID_EPGETSTATUS 0x000f +#define SAM_TRACEINTID_EPINQEMPTY 0x0010 +#define SAM_TRACEINTID_EPINT 0x0011 +#define SAM_TRACEINTID_EPOUTQEMPTY 0x0012 +#define SAM_TRACEINTID_GETCONFIG 0x0013 +#define SAM_TRACEINTID_GETSETDESC 0x0014 +#define SAM_TRACEINTID_GETSETIF 0x0015 +#define SAM_TRACEINTID_GETSTATUS 0x0016 +#define SAM_TRACEINTID_IFGETSTATUS 0x0017 +#define SAM_TRACEINTID_INTERRUPT 0x0018 +#define SAM_TRACEINTID_INTSOF 0x0019 +#define SAM_TRACEINTID_INTMSOF 0x001a +#define SAM_TRACEINTID_NOSTDREQ 0x001b +#define SAM_TRACEINTID_PENDING 0x001c +#define SAM_TRACEINTID_RXRDY 0x001d +#define SAM_TRACEINTID_RXSETUP 0x001e +#define SAM_TRACEINTID_SETCONFIG 0x001f +#define SAM_TRACEINTID_SETFEATURE 0x0020 +#define SAM_TRACEINTID_SPEED 0x0021 +#define SAM_TRACEINTID_STALLSNT 0x0022 +#define SAM_TRACEINTID_SYNCHFRAME 0x0023 +#define SAM_TRACEINTID_TXINI 0x0024 +#define SAM_TRACEINTID_UPSTRRES 0x0025 +#define SAM_TRACEINTID_WAKEUP 0x0026 /* Ever-present MIN and MAX macros */ @@ -364,7 +397,6 @@ struct sam_usbdev_s struct usb_ctrlreq_s ctrl; /* Last EP0 request */ uint8_t devstate; /* State of the device (see enum sam_devstate_e) */ uint8_t prevstate; /* Previous state of the device before SUSPEND */ - uint8_t devaddr; /* Assigned device address */ uint8_t selfpowered:1; /* 1: Device is self powered */ uint16_t epavail; /* Bitset of available endpoints */ @@ -438,7 +470,7 @@ static inline void sam_req_abort(struct sam_ep_s *privep, struct sam_req_s *privreq, int16_t result); static void sam_req_complete(struct sam_ep_s *privep, int16_t result); -static void sam_ep_fifcon(unsigned int epno); +static void sam_ep_fifocon(unsigned int epno); static void sam_req_wrsetup(struct sam_usbdev_s *priv, struct sam_ep_s *privep, struct sam_req_s *privreq); static int sam_req_write(struct sam_usbdev_s *priv, @@ -455,9 +487,11 @@ static void sam_req_cancel(struct sam_ep_s *privep, int16_t status); /* Interrupt level processing ***********************************************/ static void sam_ep0_read(uint8_t *buffer, size_t buflen); -static void sam_ep0_wrstatus(const uint8_t *buffer, size_t buflen); +static void sam_ctrlep_write(struct sam_ep_s *privep, const uint8_t *buffer, + size_t buflen); +static void sam_ep_write(struct sam_ep_s *privep, const uint8_t *buffer, + size_t buflen); static void sam_ep0_dispatch(struct sam_usbdev_s *priv); -static void sam_setdevaddr(struct sam_usbdev_s *priv, uint8_t value); static void sam_ep0_setup(struct sam_usbdev_s *priv); #ifdef CONFIG_USBDEV_DMA static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno); @@ -568,14 +602,14 @@ static const struct usb_epdesc_s g_ep0desc = #ifdef CONFIG_SAMV7_USBDEVHS_SCATTERGATHER #ifdef CONFIG_SAMV7_USBDEVHS_PREALLOCATE -/* This is a properly aligned pool of preallocated DMA transfer desciptors */ +/* This is a properly aligned pool of preallocated DMA transfer descriptors */ static struct sam_dtd_s g_dtdpool[CONFIG_SAMV7_USBDEVHS_NDTDS] __attribute__ ((aligned(16))); #endif #endif -/* Device error strings that may be enabled for more desciptive USB trace +/* Device error strings that may be enabled for more descriptive USB trace * output. */ @@ -607,7 +641,6 @@ const struct trace_msg_t g_usb_trace_strings_deverror[] = TRACE_STR(SAM_TRACEERR_EPRESERVE), TRACE_STR(SAM_TRACEERR_NCFGOK), TRACE_STR(SAM_TRACEERR_INVALIDCTRLREQ), - TRACE_STR(SAM_TRACEERR_INVALIDPARMS), TRACE_STR(SAM_TRACEERR_IRQREGISTRATION), TRACE_STR(SAM_TRACEERR_NOTCONFIGURED), TRACE_STR(SAM_TRACEERR_REQABORTED), @@ -616,7 +649,7 @@ const struct trace_msg_t g_usb_trace_strings_deverror[] = }; #endif -/* Interrupt event strings that may be enabled for more desciptive USB trace +/* Interrupt event strings that may be enabled for more descriptive USB trace * output. */ @@ -636,8 +669,10 @@ const struct trace_msg_t g_usb_trace_strings_intdecode[] = TRACE_STR(SAM_TRACEINTID_EP0SETUPIN), TRACE_STR(SAM_TRACEINTID_EP0SETUPOUT), TRACE_STR(SAM_TRACEINTID_EP0SETUPSETADDRESS), + TRACE_STR(SAM_TRACEINTID_EPDMAINT), TRACE_STR(SAM_TRACEINTID_EPGETSTATUS), TRACE_STR(SAM_TRACEINTID_EPINQEMPTY), + TRACE_STR(SAM_TRACEINTID_EPINT), TRACE_STR(SAM_TRACEINTID_EPOUTQEMPTY), TRACE_STR(SAM_TRACEINTID_GETCONFIG), TRACE_STR(SAM_TRACEINTID_GETSETDESC), @@ -653,6 +688,7 @@ const struct trace_msg_t g_usb_trace_strings_intdecode[] = TRACE_STR(SAM_TRACEINTID_RXSETUP), TRACE_STR(SAM_TRACEINTID_SETCONFIG), TRACE_STR(SAM_TRACEINTID_SETFEATURE), + TRACE_STR(SAM_TRACEINTID_SPEED), TRACE_STR(SAM_TRACEINTID_STALLSNT), TRACE_STR(SAM_TRACEINTID_SYNCHFRAME), TRACE_STR(SAM_TRACEINTID_TXINI), @@ -817,7 +853,7 @@ static void sam_dumpep(struct sam_usbdev_s *priv, int epno) lldbg("Global Register:\n"); lldbg(" CTRL: %08x\n", sam_getreg(SAM_USBHS_DEVCTRL)); - lldbg(" IISR: %08x\n", sam_getreg(SAM_USBHS_DEVISR)); + lldbg(" ISR: %08x\n", sam_getreg(SAM_USBHS_DEVISR)); lldbg(" IMR: %08x\n", sam_getreg(SAM_USBHS_DEVIMR)); lldbg(" EPT: %08x\n", sam_getreg(SAM_USBHS_DEVEPT)); lldbg(" FNUM: %08x\n", sam_getreg(SAM_USBHS_DEVFNUM)); @@ -1164,7 +1200,7 @@ static void sam_req_complete(struct sam_ep_s *privep, int16_t result) } /**************************************************************************** - * Name: sam_ep_fifcon + * Name: sam_ep_fifocon * * Description: * IN data has been loaded in the endpoint FIFO. Manage the endpoint to @@ -1173,7 +1209,7 @@ static void sam_req_complete(struct sam_ep_s *privep, int16_t result) * ****************************************************************************/ -static void sam_ep_fifcon(unsigned int epno) +static void sam_ep_fifocon(unsigned int epno) { /* Clear FIFOCON to indicate that the packet is ready to send (this works * even for zero length packets). We will get an TXIN interrupt with @@ -1207,21 +1243,16 @@ static void sam_req_wrsetup(struct sam_usbdev_s *priv, struct sam_ep_s *privep, struct sam_req_s *privreq) { + uint32_t regval; const uint8_t *buf; - uint8_t *fifo; uint8_t epno; + unsigned int eptype; int nbytes; /* Get the unadorned endpoint number */ epno = USB_EPNO(privep->ep.eplog); - /* Write access to the FIFO is not possible if FIFOCON is clear (meaning - * that a write is already in progress. - */ - - DEBUGASSERT((sam_getreg(SAM_USBHS_DEVEPTISR(epno)) & USBHS_DEVEPTINT_FIFOCONI) != 0); - /* Get the number of bytes remaining to be sent. */ DEBUGASSERT(privreq->req.xfrd < privreq->req.len); @@ -1242,35 +1273,25 @@ static void sam_req_wrsetup(struct sam_usbdev_s *priv, usbtrace(TRACE_WRITE(USB_EPNO(privep->ep.eplog)), nbytes); /* The new buffer pointer is the started of the buffer plus the number - * of bytes successfully transfered plus the number of bytes previously + * of bytes successfully transferred plus the number of bytes previously * "in-flight". */ buf = privreq->req.buf + privreq->req.xfrd; - /* Write packet in the FIFO buffer */ + /* How we send packets differs for control endpoints */ - fifo = (uint8_t *) - ((uint32_t *)SAM_USBHSRAM_BASE + (EPT_FIFO_SIZE * epno)); + regval = sam_getreg(SAM_USBHS_DEVEPTCFG(epno)); + eptype = regval & USBHS_DEVEPTCFG_EPTYPE_MASK; - for (; nbytes; nbytes--) + if (eptype == USBHS_DEVEPTCFG_EPTYPE_CTRL) { - *fifo++ = *buf++; + sam_ctrlep_write(privep, buf, nbytes); + } + else + { + sam_ep_write(privep, buf, nbytes); } - - MEMORY_SYNC(); - - /* Indicate that there is data in the TX packet memory. This will - * be cleared when the next data out interrupt is received. - */ - - privep->epstate = USBHS_EPSTATE_SENDING; - - /* Initiate the transfer and configure to receive the transfer complete - * interrupt. - */ - - sam_ep_fifcon(epno); } /**************************************************************************** @@ -1290,7 +1311,7 @@ static void sam_req_wrsetup(struct sam_usbdev_s *priv, * When a request is queued, the request 'len' is the number of bytes * to transfer and 'xfrd' and 'inflight' must be zero. * - * When this function starts a tranfer it will update the request + * When this function starts a transfer it will update the request * 'inflight' field to indicate the size of the transfer. * * When the transfer completes, the the 'inflight' field must hold the @@ -1410,8 +1431,8 @@ static int sam_req_write(struct sam_usbdev_s *priv, struct sam_ep_s *privep) /* If we get here, then we sent the last of the data on the * previous pass and we need to send the zero length packet now. * - * A Zero Length Packet can be sent by clearing just the FIFOCON flag - * in the USBHS_DEVTEPTIDRx register + * A Zero Length Packet can be sent by clearing just the FIFOCON + * flag in the USBHS_DEVTEPTIDRx register */ privep->epstate = USBHS_EPSTATE_SENDING; @@ -1423,7 +1444,7 @@ static int sam_req_write(struct sam_usbdev_s *priv, struct sam_ep_s *privep) * transfer complete interrupt. */ - sam_ep_fifcon(epno); + sam_ep_fifocon(epno); } /* If all of the bytes were sent (including any final zero length @@ -1547,7 +1568,7 @@ static void sam_req_rddisable(uint8_t epno) * - When receiving data via DMA, then data has already been transferred * and this function is called on the terminating event. The transfer * is complete and we just need to check for end of request events and - * if we need to setup the tranfer for the next request. + * if we need to setup the transfer for the next request. * - When receiving via the FIFO, the transfer is not complete. The * data is in the FIFO and must be transferred from the FIFO to the * request buffer. No setup is needed for the next transfer other than @@ -1647,10 +1668,17 @@ static int sam_req_read(struct sam_usbdev_s *priv, struct sam_ep_s *privep, if ((SAM_EPSET_DMA & SAM_EP_BIT(epno)) != 0) { - /* Set up the next DMA */ + /* Set up the next DMA. We will come through this logic path + * again with xrfd != 0 when the DMA completes. + */ sam_dma_rdsetup(priv, privep, privreq); } + + /* No DMA for this endpoint and we have an available, empty read + * request. We need to wait for data to become avaialable. + */ + else { /* Enable endpoint RXRDY_TXTK interrupts */ @@ -1700,6 +1728,7 @@ static int sam_req_read(struct sam_usbdev_s *priv, struct sam_ep_s *privep, static void sam_req_cancel(struct sam_ep_s *privep, int16_t result) { + uint32_t regval; uint8_t epno; /* Disable endpoint interrupts if not endpoint 0 */ @@ -1707,7 +1736,8 @@ static void sam_req_cancel(struct sam_ep_s *privep, int16_t result) epno = USB_EPNO(privep->ep.eplog); if (epno != 0) { - sam_putreg(USBHS_DEVINT_DMA(epno), SAM_USBHS_DEVIDR); + regval = USBHS_DEVINT_DMA(epno) | USBHS_DEVINT_PEP(epno); + sam_putreg(regval, SAM_USBHS_DEVIDR); } /* Then complete every queued request with the specified status */ @@ -1747,21 +1777,28 @@ static void sam_ep0_read(uint8_t *buffer, size_t buflen) } /**************************************************************************** - * Name: sam_ep0_wrstatus + * Name: sam_ctrlep_write * * Description: - * Process the next queued write request for an endpoint that does not - * support DMA. + * Process the next queued write request for a control endpoint. * ****************************************************************************/ -static void sam_ep0_wrstatus(const uint8_t *buffer, size_t buflen) +static void sam_ctrlep_write(struct sam_ep_s *privep, const uint8_t *buffer, + size_t buflen) { volatile uint8_t *fifo; + unsigned int epno; + + /* Get the endpoint number */ + + epno = USB_EPNO(privep->ep.eplog); /* Write packet in the FIFO buffer */ - fifo = (volatile uint8_t *)SAM_USBHSRAM_BASE; + fifo = (uint8_t *) + ((uint32_t *)SAM_USBHSRAM_BASE + (EPT_FIFO_SIZE * epno)); + for (; buflen > 0; buflen--) { *fifo++ = *buffer++; @@ -1769,11 +1806,78 @@ static void sam_ep0_wrstatus(const uint8_t *buffer, size_t buflen) MEMORY_SYNC(); + /* Indicate that there is data in the TX packet memory. This will + * be cleared when the next NAKIN interrupt is received. + */ + + privep->epstate = USBHS_EPSTATE_SENDING; + + /* The FIFO Control (USBHS_DEVEPTIMRx.FIFOCON) bit and the Read/Write + * Allowed (USBHS_DEVEPTISRx.RWALL) bit are irrelevant for control + * endpoints. The user never uses them on these endpoints. + */ + + /* USBHS_DEVEPTISRx.TXINI is cleared by software (by writing a one to + * the Transmitted IN Data Interrupt Clear bit (USBHS_DEVEPTIDRx.TXINIC) + * to acknowledge the interrupt, which has no effect on the endpoint + * FIFO. This acknowledges the interrupt and sends the packet. + */ + + sam_putreg(USBHS_DEVEPTINT_TXINI, SAM_USBHS_DEVEPTIDR(epno)); + + /* Clear the NAKIN bit to stop NAKing IN tokens from the host. We now + * have data ready to go. + */ + + sam_putreg((USBHS_DEVEPTINT_NAKINI | USBHS_DEVEPTINT_TXINI), + SAM_USBHS_DEVEPTICR(epno)); + + /* Enable the TXIN interrupt on the endpoint */ + + sam_putreg(USBHS_DEVEPTINT_TXINI, SAM_USBHS_DEVEPTIER(epno)); +} + +/**************************************************************************** + * Name: sam_ep_write + * + * Description: + * Process the next queued write request for a control endpoint. + * + ****************************************************************************/ + +static void sam_ep_write(struct sam_ep_s *privep, const uint8_t *buffer, + size_t buflen) +{ + volatile uint8_t *fifo; + unsigned int epno; + + /* Get the endpoint number */ + + epno = USB_EPNO(privep->ep.eplog); + + /* Write packet in the FIFO buffer */ + + fifo = (uint8_t *) + ((uint32_t *)SAM_USBHSRAM_BASE + (EPT_FIFO_SIZE * epno)); + + for (; buflen; buflen--) + { + *fifo++ = *buffer++; + } + + MEMORY_SYNC(); + + /* Indicate that there is data in the TX packet memory. This will + * be cleared when the next data out interrupt is received. + */ + + privep->epstate = USBHS_EPSTATE_SENDING; + /* Initiate the transfer and configure to receive the transfer complete * interrupt. */ - sam_ep_fifcon(EP0); + sam_ep_fifocon(epno); } /**************************************************************************** @@ -1820,41 +1924,6 @@ static void sam_ep0_dispatch(struct sam_usbdev_s *priv) } } -/**************************************************************************** - * Name: sam_setdevaddr - ****************************************************************************/ - -static void sam_setdevaddr(struct sam_usbdev_s *priv, uint8_t address) -{ - uint32_t regval; - - if (address) - { - /* Enable the address */ - - regval = sam_getreg(SAM_USBHS_DEVCTRL); - regval &= ~USBHS_DEVCTRL_UADD_MASK; - regval |= USBHS_DEVCTRL_UADD(address) | USBHS_DEVCTRL_ADDEN; - sam_putreg(regval, SAM_USBHS_DEVCTRL); - - /* Go to the addressed state */ - - priv->devstate = USBHS_DEVSTATE_ADDRESSED; - } - else - { - /* Disable address */ - - regval = sam_getreg(SAM_USBHS_DEVCTRL); - regval &= ~USBHS_DEVCTRL_ADDEN; - sam_putreg(regval, SAM_USBHS_DEVCTRL); - - /* Revert to the un-addressed, default state */ - - priv->devstate = USBHS_DEVSTATE_DEFAULT; - } -} - /**************************************************************************** * Name: sam_ep0_setup ****************************************************************************/ @@ -1868,6 +1937,7 @@ static void sam_ep0_setup(struct sam_usbdev_s *priv) union wb_u len; union wb_u response; enum sam_ep0setup_e ep0result; + uint32_t regval; uint8_t epno; int nbytes = 0; /* Assume zero-length packet */ int ret; @@ -2108,8 +2178,21 @@ static void sam_ep0_setup(struct sam_usbdev_s *priv) */ usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_EP0SETUPSETADDRESS), value.w); - priv->devaddr = value.w; - ep0result = USBHS_EP0SETUP_ADDRESS; + + /* Write this address to the USB Address (USBHS_DEVCTRL.UADD) field + * but do not yet enable (USBHS_DEVCTRL.ADDEN) so the actual address is + * still 0. + * + * USBHS_DEVCTRL.UADD and USBHS_DEVCTRL.ADDEN must not be written all + * at once. + */ + + regval = sam_getreg(SAM_USBHS_DEVCTRL); + regval &= ~(USBHS_DEVCTRL_UADD_MASK | USBHS_DEVCTRL_ADDEN); + regval |= USBHS_DEVCTRL_UADD(value.w); + sam_putreg(regval, SAM_USBHS_DEVCTRL); + + ep0result = USBHS_EP0SETUP_ADDRESS; } } break; @@ -2181,12 +2264,12 @@ static void sam_ep0_setup(struct sam_usbdev_s *priv) if ((priv->ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE && index.w == 0 && len.w == 0) { - /* The request seems valid... let the class implementation handle it. - * If the class implementation accespts it new configuration, it will - * call sam_ep_configure() to configure the endpoints. - */ + /* The request seems valid... let the class implementation handle it. + * If the class implementation accespts it new configuration, it will + * call sam_ep_configure() to configure the endpoints. + */ - sam_ep0_dispatch(priv); + sam_ep0_dispatch(priv); ep0result = USBHS_EP0SETUP_DISPATCHED; } else @@ -2284,8 +2367,8 @@ static void sam_ep0_setup(struct sam_usbdev_s *priv) { /* Send the response (might be a zero-length packet) */ + sam_ctrlep_write(ep0, response.b, nbytes); ep0->epstate = USBHS_EPSTATE_EP0STATUSIN; - sam_ep0_wrstatus(response.b, nbytes); } break; @@ -2293,8 +2376,8 @@ static void sam_ep0_setup(struct sam_usbdev_s *priv) { /* Send the response (might be a zero-length packet) */ + sam_ctrlep_write(ep0, response.b, nbytes); ep0->epstate = USBHS_EPSTATE_EP0ADDRESS; - sam_ep0_wrstatus(response.b, nbytes); } break; @@ -2359,7 +2442,7 @@ static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno) /* Get the result of the DMA operation */ dmastatus = sam_getreg(SAM_USBHS_DEVDMASTA(epno)); - uvdbg("DMA%d DMASTATUS: %08x\n", epno, dmastatus); + usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_EPDMAINT), dmastatus); /* Disable DMA interrupt to avoid receiving 2 (B_EN and TR_EN) */ @@ -2530,6 +2613,7 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno) /* Get the endpoint status */ eptisr = sam_getreg(SAM_USBHS_DEVEPTISR(epno)); + usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_EPINT), eptisr); /* Get the endpoint type */ @@ -2538,7 +2622,7 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno) /* IN packet sent */ - if ((eptisr & USBHS_DEVEPTINT_TXINI) == 0 && + if ((eptisr & USBHS_DEVEPTINT_TXINI) != 0 && (sam_getreg(SAM_USBHS_DEVEPTIMR(epno)) & USBHS_DEVEPTINT_TXINI) != 0) { usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_TXINI), (uint16_t)eptisr); @@ -2567,13 +2651,24 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno) else if (privep->epstate == USBHS_EPSTATE_EP0ADDRESS) { - usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_ADDRESSED), priv->devaddr); DEBUGASSERT(epno == EP0); - /* Set the device address */ + /* Enable the address previously set in the SETUP processing. + * USBHS_DEVCTRL.UADD and USBHS_DEVCTRL.ADDEN must not be written + * all at once. + */ + regval = sam_getreg(SAM_USBHS_DEVCTRL); + regval |= USBHS_DEVCTRL_ADDEN; + sam_putreg(regval, SAM_USBHS_DEVCTRL); + + usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_ADDRESSED), + (regval & USBHS_DEVCTRL_UADD_MASK) << USBHS_DEVCTRL_UADD_SHIFT); + + /* Go to the addressed state. EP0 is now IDLE. */ + + priv->devstate = USBHS_DEVSTATE_ADDRESSED; privep->epstate = USBHS_EPSTATE_IDLE; - sam_setdevaddr(priv, priv->devaddr); /* Acknowledge then disable the further TXIN interrupts on EP0. */ @@ -2832,14 +2927,14 @@ static int sam_usbhs_interrupt(int irq, void *context) sam_putreg(USBHS_DEVINT_SUSPD | USBHS_DEVINT_WAKEUP, SAM_USBHS_DEVICR); + /* Inform board logic that USB is suspended */ + + sam_suspend(priv); + /* Re-freeze the clock */ regval |= USBHS_CTRL_FRZCLK; sam_putreg(regval, SAM_USBHS_CTRL); - - /* Inform board logic that USB is suspended */ - - sam_suspend(priv); } /* SOF interrupt */ @@ -2901,26 +2996,55 @@ static int sam_usbhs_interrupt(int irq, void *context) * - The data toggle sequence of the default control endpoint is cleared. * - At the end of the reset process, the End of Reset (USBHS_DEVISR.EORST) * bit is set. + * - During a reset, the USBHS automatically switches to High-speed mode + * if the host is High-speed-capable (the reset is called High-speed + * reset). The user should observe the USBHS_SR.SPEED field to know + * the speed running at the end of the reset (USBHS_DEVISR.EORST = 1). */ if ((pending & USBHS_DEVINT_EORST) != 0) { - usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_ENDRESET), (uint16_t)pending); + /* Sample the USBHS SR register at the time of the EORST event. */ - /* Acknowledge the interrupt, clear pednding wakeup and suspend + regval = sam_getreg(SAM_USBHS_SR); + usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_ENDRESET), regval); + + /* Acknowledge the interrupt, clear pending wakeup and suspend * status as we.. */ - sam_putreg(USBHS_DEVINT_WAKEUP | USBHS_DEVINT_SUSPD | USBHS_DEVINT_EORST, + sam_putreg(USBHS_DEVINT_WAKEUP | USBHS_DEVINT_SUSPD | + USBHS_DEVINT_EORST, SAM_USBHS_DEVICR); /* Enable suspend interrupts */ sam_putreg(USBHS_DEVINT_SUSPD, SAM_USBHS_DEVIER); - /* Handle the reset */ + /* Handle the reset (will select full speed mode) */ sam_reset(priv); + + /* Get the correct speed mode reported by the hardware */ + + switch (regval & USBHS_SR_SPEED_MASK) + { + default: + case USBHS_SR_SPEED_FULL: + priv->usbdev.speed = USB_SPEED_FULL; + break; + + case USBHS_SR_SPEED_HIGH: + priv->usbdev.speed = USB_SPEED_HIGH; + break; + + case USBHS_SR_SPEED_LOW: + priv->usbdev.speed = USB_SPEED_LOW; + break; + } + + usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_SPEED), + priv->usbdev.speed); } /* Upstream resume */ @@ -2934,14 +3058,24 @@ static int sam_usbhs_interrupt(int irq, void *context) } #ifdef CONFIG_USBDEV_DMA - /* DMA interrupts */ + /* Endpoint DMA interrupts */ else if ((pending & USBHS_DEVINT_DMA_MASK) != 0) { + /* Each endpoint DMA ineterrupt is cleared when the + * USBHS_DEVDMASTATUSx interrupt source is cleared. + */ + + /* Process each pending endpoint DMA interrupt */ + for (i = 1; i <= SAM_USBHS_NDMACHANNELS; i++) { + /* Is there a DMA interrupt pending for endpoint i? */ + if ((pending & USBHS_DEVINT_DMA(i)) != 0) { + /* Yes.. process the endpoint i DMA interrupt */ + usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_DMA), (uint16_t)i); sam_dma_interrupt(priv, i); } @@ -2953,10 +3087,20 @@ static int sam_usbhs_interrupt(int irq, void *context) else if ((pending & USBHS_DEVINT_PEP_MASK) != 0) { + /* Each endpoint interrupt is cleared when the interrupt source + * is serviced. + */ + + /* Process each pending endpoint interrupt */ + for (i = 0; i < SAM_USBHS_NENDPOINTS; i++) { + /* Is there an interrupt pending for endpoint i? */ + if ((pending & USBHS_DEVINT_PEP(i)) != 0) { + /* Yes.. process the endpoint i interrupt */ + usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_EP), (uint16_t)i); sam_ep_interrupt(priv, i); } @@ -3080,7 +3224,7 @@ static void sam_ep_reset(struct sam_usbdev_s *priv, uint8_t epno) sam_putreg(USBHS_DEVINT_PEP(epno), SAM_USBHS_DEVIDR); - /* Cancel any queued requests. Since they are canceled with status + /* Cancel any queued requests. Since they are cancelled with status * -ESHUTDOWN, then will not be requeued until the configuration is reset. * NOTE: This should not be necessary... the CLASS_DISCONNECT above * should result in the class implementation calling sam_ep_disable @@ -3325,9 +3469,15 @@ static int sam_ep_configure_internal(struct sam_ep_s *privep, if (eptype == USB_EP_ATTR_XFER_CONTROL) { - sam_putreg(USBHS_DEVINT_PEP(epno), SAM_USBHS_DEVIDR); + sam_putreg(USBHS_DEVINT_PEP(epno), SAM_USBHS_DEVIDR); } + /* Enable the endpoint */ + + regval = sam_getreg(SAM_USBHS_DEVEPT); + regval |= USBHS_DEVEPT_EPEN(epno); + sam_putreg(regval, SAM_USBHS_DEVEPT); + /* Configure the endpoint */ regval = USBHS_DEVEPTCFG_ALLOC | @@ -3410,12 +3560,6 @@ static int sam_ep_configure_internal(struct sam_ep_s *privep, sam_putreg(regval, SAM_USBHS_DEVEPTIER(epno)); } - /* Enable the endpoint */ - - regval = sam_getreg(SAM_USBHS_DEVEPT); - regval |= USBHS_DEVEPT_EPEN(epno); - sam_putreg(regval, SAM_USBHS_DEVEPT); - /* If this is EP0, enable interrupts now */ if (eptype == USB_EP_ATTR_XFER_CONTROL) @@ -3519,14 +3663,7 @@ static int sam_ep_disable(struct usbdev_ep_s *ep) irqstate_t flags; uint8_t epno; -#ifdef CONFIG_DEBUG - if (!ep) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - ulldbg("ERROR: ep=%p\n", ep); - return -EINVAL; - } -#endif + DEBUGASSERT(ep != NULL); epno = USB_EPNO(ep->eplog); usbtrace(TRACE_EPDISABLE, epno); @@ -3556,13 +3693,7 @@ static struct usbdev_req_s *sam_ep_allocreq(struct usbdev_ep_s *ep) { struct sam_req_s *privreq; -#ifdef CONFIG_DEBUG - if (!ep) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return NULL; - } -#endif + DEBUGASSERT(ep != NULL); usbtrace(TRACE_EPALLOCREQ, USB_EPNO(ep->eplog)); privreq = (struct sam_req_s *)kmm_malloc(sizeof(struct sam_req_s)); @@ -3588,13 +3719,7 @@ static void sam_ep_freereq(struct usbdev_ep_s *ep, struct usbdev_req_s *req) { struct sam_req_s *privreq = (struct sam_req_s*)req; -#ifdef CONFIG_DEBUG - if (!ep || !req) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return; - } -#endif + DEBUGASSERT(ep != NULL && req != NULL); usbtrace(TRACE_EPFREEREQ, USB_EPNO(ep->eplog)); kmm_free(privreq); @@ -3611,9 +3736,9 @@ static void sam_ep_freereq(struct usbdev_ep_s *ep, struct usbdev_req_s *req) #ifdef CONFIG_USBDEV_DMA static void *sam_ep_allocbuffer(struct usbdev_ep_s *ep, uint16_t nbytes) { - /* There is not special buffer allocation requirement */ + /* Allocate properly aligned memory */ - return kumm_malloc(nbytes); + return kmm_memalign(USBHS_ALIGN, USBHS_ALIGN_UP(nbytes)); } #endif @@ -3628,7 +3753,7 @@ static void *sam_ep_allocbuffer(struct usbdev_ep_s *ep, uint16_t nbytes) #ifdef CONFIG_USBDEV_DMA static void sam_ep_freebuffer(struct usbdev_ep_s *ep, void *buf) { - /* There is not special buffer allocation requirement */ + /* There is no special buffer requirement to free aligned DMA buffers */ kumm_free(buf); } @@ -3651,26 +3776,10 @@ static int sam_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req) uint8_t epno; int ret = OK; -#ifdef CONFIG_DEBUG - if (!req || !req->callback || !req->buf || !ep) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - ulldbg("ERROR: req=%p callback=%p buf=%p ep=%p\n", req, req->callback, req->buf, ep); - return -EINVAL; - } -#endif - + DEBUGASSERT(ep != NULL && req != NULL && req->callback != NULL && req->buf != NULL); usbtrace(TRACE_EPSUBMIT, USB_EPNO(ep->eplog)); priv = privep->dev; - -#ifdef CONFIG_DEBUG - if (!priv->driver) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_NOTCONFIGURED), priv->usbdev.speed); - ulldbg("ERROR: driver=%p\n", priv->driver); - return -ESHUTDOWN; - } -#endif + DEBUGASSERT(priv->driver != NULL); /* Handle the request from the class driver */ @@ -3743,13 +3852,7 @@ static int sam_ep_cancel(struct usbdev_ep_s *ep, struct usbdev_req_s *req) struct sam_ep_s *privep = (struct sam_ep_s *)ep; irqstate_t flags; -#ifdef CONFIG_DEBUG - if (!ep || !req) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return -EINVAL; - } -#endif + DEBUGASSERT(ep != NULL && req != NULL); usbtrace(TRACE_EPCANCEL, USB_EPNO(ep->eplog)); flags = irqsave(); @@ -3771,13 +3874,7 @@ static int sam_ep_stall(struct usbdev_ep_s *ep, bool resume) uint32_t regval; irqstate_t flags; -#ifdef CONFIG_DEBUG - if (!ep) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return -EINVAL; - } -#endif + DEBUGASSERT(ep != NULL); /* Check that endpoint is in Idle state */ @@ -3935,13 +4032,7 @@ static struct usbdev_ep_s *sam_allocep(struct usbdev_s *dev, uint8_t epno, uint16_t epset = SAM_EPSET_NOTEP0; usbtrace(TRACE_DEVALLOCEP, (uint16_t)epno); -#ifdef CONFIG_DEBUG - if (!dev) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return NULL; - } -#endif + DEBUGASSERT(dev != NULL); /* Ignore any direction bits in the logical address */ @@ -3997,13 +4088,8 @@ static void sam_freeep(struct usbdev_s *dev, struct usbdev_ep_s *ep) struct sam_usbdev_s *priv; struct sam_ep_s *privep; -#ifdef CONFIG_DEBUG - if (!dev || !ep) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return; - } -#endif + DEBUGASSERT(dev != NULL && ep != NULL); + priv = (struct sam_usbdev_s *)dev; privep = (struct sam_ep_s *)ep; usbtrace(TRACE_DEVFREEEP, (uint16_t)USB_EPNO(ep->eplog)); @@ -4029,13 +4115,7 @@ static int sam_getframe(struct usbdev_s *dev) uint32_t regval; uint16_t frameno; -#ifdef CONFIG_DEBUG - if (!dev) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return -EINVAL; - } -#endif + DEBUGASSERT(dev != NULL); /* Return the last frame number detected by the hardware */ @@ -4061,13 +4141,7 @@ static int sam_wakeup(struct usbdev_s *dev) uint32_t regval; usbtrace(TRACE_DEVWAKEUP, 0); -#ifdef CONFIG_DEBUG - if (!dev) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return -EINVAL; - } -#endif + DEBUGASSERT(dev != NULL); /* Resume normal operation */ @@ -4106,14 +4180,7 @@ static int sam_selfpowered(struct usbdev_s *dev, bool selfpowered) struct sam_usbdev_s *priv = (struct sam_usbdev_s *)dev; usbtrace(TRACE_DEVSELFPOWERED, (uint16_t)selfpowered); - -#ifdef CONFIG_DEBUG - if (!dev) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return -ENODEV; - } -#endif + DEBUGASSERT(dev != NULL); priv->selfpowered = selfpowered; return OK; @@ -4153,7 +4220,9 @@ static int sam_pullup(FAR struct usbdev_s *dev, bool enable) regval &= ~USBHS_CTRL_FRZCLK; sam_putreg(regval, SAM_USBHS_CTRL); - /* DETACH=0: USBHS is attached. Pulls up the DP line */ + /* DETACH=0: USBHS is attached. ARMs the USBHS to pull up the DP line + * when the USBHS is no longer suspended. + */ regval = sam_getreg(SAM_USBHS_DEVCTRL); regval &= ~USBHS_DEVCTRL_DETACH; @@ -4161,49 +4230,97 @@ static int sam_pullup(FAR struct usbdev_s *dev, bool enable) priv->usbdev.speed = USB_SPEED_FULL; - /* The next event that we expect to see is a reset from the connected - * host. When a USB reset is detected on the USB line, the following - * operations are performed by the controller: + /* There are several possibilities: * - * - All endpoints are disabled, except the default control endpoint. - * - The default control endpoint is reset - * - The data toggle sequence of the default control endpoint is cleared. - * - At the end of the reset process, the End of Reset (USBHS_DEVISR.EORST) - * bit is set. - * - * The class implementation should not call this method with - * enable == true until is is fully initialized and ready to accept - * connections. - * - * If there is no host connected (no bus activity), then we might - * get a SUSPend interrupt instead of a End of Reset. In the case, we - * would like to keep the clock frozen until the host is connected. - * - * The strategy here was taken from the SAMV7 sample code: It will - * force a SUSPend event. Then disable clocking. We will take the - * SUSPend interrupt (because it is already pending), but after the - * clock is frozen, only a WAKEUP interrupt can be received. + * 1. The device may not be plugged into a host. In that case, the + * hardware will be in a suspended state. When an idle USB bus state + * has been detected for 3 ms , the controller sets the Suspend + * (USBHS_DEVISR.SUSP) interrupt bit. + * 2. We may have been suspended but a WAKEUP event has already occurred. + * The USBHS_DEVISR.WAKEUP interrupt bit is set when a non-idle event + * is detected, it can occur whether the controller is in the Suspend + * mode or not. The USBHS_DEVISR.SUSP and USBHS_DEVISR.WAKEUP interrupts + * are thus independent, except that one bit is cleared when the other is set. + * 3. Because we have already enabled the pull-up, that event may have already + * have been reset by the host. */ - /* Enable expected interrupts */ + regval = sam_getreg(SAM_USBHS_DEVISR); + if ((regval & USBHS_DEVINT_SUSPD) == 0) + { + /* If the USBHS detects activity on the BUS, then it will not be + * suspended. In that case, next event that we expect to see is a + * reset from the connected host. When a USB reset is detected on + * the USB line, the following operations are performed by the + * controller: + * + * - All endpoints are disabled, except the default control + * endpoint. + * - The default control endpoint is reset + * - The data toggle sequence of the default control endpoint is + * cleared. + * - At the end of the reset process, the End of Reset + * (USBHS_DEVISR.EORST) bit is set. + * - During a reset, the USBHS automatically switches to High- + * speed mode if the host is High-speed-capable (the reset is + * called High-speed reset). The user should observe the + * USBHS_SR.SPEED field to know the speed running at the end + * of the reset (USBHS_DEVISR.EORST = 1). + * + * The class implementation should not call this method with + * enable == true until is is fully initialized and ready to + * accept connections. + */ - sam_putreg(USBHS_DEVINT_EORST | USBHS_DEVINT_WAKEUP | USBHS_DEVINT_SUSPD, - SAM_USBHS_DEVIER); + /* Enable expected interrupts */ - /* Clear pending interrupt interrupts */ + sam_putreg(USBHS_DEVINT_EORST | USBHS_DEVINT_EORSM | + USBHS_DEVINT_SUSPD, + SAM_USBHS_DEVIER); - sam_putreg(USBHS_DEVINT_EORST | USBHS_DEVINT_SUSPD, SAM_USBHS_DEVICR); + /* Leave the clock unfrozen */ + } + else + { + /* If there is no host connected (no bus activity), then we + * might get a SUSPend interrupt instead of a End of Reset. In + * the case, we would like to keep the clock frozen until the + * host is connected. + * + * The strategy here was taken from the SAMV7 sample code: It + * will force a SUSPend event. Then disable clocking. We will + * take the SUSPend interrupt (because it is already pending), + * but after the clock is frozen, only a WAKEUP interrupt can be + * received. + */ - /* Force the first suspend event */ + /* Enable wakeup interrupts */ - sam_putreg(USBHS_DEVINT_SUSPD, SAM_USBHS_DEVIFR); - sam_putreg(USBHS_DEVINT_WAKEUP, SAM_USBHS_DEVICR); + sam_putreg(USBHS_DEVINT_WAKEUP | USBHS_DEVINT_EORSM, + SAM_USBHS_DEVIER); - /* Refreeze the clock and wait for the wakeup event */ + /* Enable expected interrupts */ - regval = sam_getreg(SAM_USBHS_CTRL); - regval |= USBHS_CTRL_FRZCLK; - sam_putreg(regval, SAM_USBHS_CTRL); + sam_putreg(USBHS_DEVINT_EORST | USBHS_DEVINT_WAKEUP | + USBHS_DEVINT_SUSPD, + SAM_USBHS_DEVIER); + + /* Clear pending interrupts */ + + sam_putreg(USBHS_DEVINT_EORST | USBHS_DEVINT_SUSPD, + SAM_USBHS_DEVICR); + + /* Force the first suspend event */ + + sam_putreg(USBHS_DEVINT_SUSPD, SAM_USBHS_DEVIFR); + sam_putreg(USBHS_DEVINT_WAKEUP, SAM_USBHS_DEVICR); + + /* Refreeze the clock and wait for the wakeup event */ + + regval = sam_getreg(SAM_USBHS_CTRL); + regval |= USBHS_CTRL_FRZCLK; + sam_putreg(regval, SAM_USBHS_CTRL); + } } else { @@ -4262,13 +4379,17 @@ static void sam_reset(struct sam_usbdev_s *priv) CLASS_DISCONNECT(priv->driver, &priv->usbdev); /* The device enters the Default state */ + /* Disable the device address */ - priv->devaddr = 0; - sam_setdevaddr(priv, 0); + regval = sam_getreg(SAM_USBHS_DEVCTRL); + regval &= ~(USBHS_DEVCTRL_UADD_MASK | USBHS_DEVCTRL_ADDEN); + sam_putreg(regval, SAM_USBHS_DEVCTRL); + + /* Revert to the un-addressed, default state */ priv->devstate = USBHS_DEVSTATE_DEFAULT; - /* Reset and disable all endpoints other. Then re-configure EP0 */ + /* Reset and disable all endpoints. Then re-configure EP0 */ sam_epset_reset(priv, SAM_EPSET_ALL); sam_ep0_configure(priv); @@ -4325,6 +4446,10 @@ static void sam_hw_setup(struct sam_usbdev_s *priv) regval &= ~USBHS_CTRL_USBE; sam_putreg(regval, SAM_USBHS_CTRL); + /* Configure USBHS pins. Nothing needs to be done: HDM and HDP are the + * primary pin functions and there are no alternatives. + */ + /* Enable clocking to the USBHS peripheral. * * The clock for the USBHS bus interface is generated by the Power @@ -4346,7 +4471,7 @@ static void sam_hw_setup(struct sam_usbdev_s *priv) * 3. Enable the UPLL 480 MHz. * 4. Wait for the UPLL 480 MHz to be considered as locked by the PMC. * - * Steps 1,3, and 4 were performed in sam_clockconfig.c. + * Steps 3 and 4 are performed in sam_usbclock.c. */ /* Enable the USBHS peripheral clock (PMC_PCER) */ @@ -4363,9 +4488,16 @@ static void sam_hw_setup(struct sam_usbdev_s *priv) regval |= USBHS_CTRL_USBE; sam_putreg(regval, SAM_USBHS_CTRL); + regval &= ~USBHS_CTRL_UIDE; + sam_putreg(regval, SAM_USBHS_CTRL); + regval &= ~USBHS_CTRL_FRZCLK; sam_putreg(regval, SAM_USBHS_CTRL); + /* Enable the UPLL */ + + sam_usbclock(); + /* Select High Speed or force Full Speed */ regval = sam_getreg(SAM_USBHS_DEVCTRL); @@ -4692,21 +4824,12 @@ int usbdev_register(struct usbdevclass_driver_s *driver) int ret; usbtrace(TRACE_DEVREGISTER, 0); - -#ifdef CONFIG_DEBUG - if (!driver || !driver->ops->bind || !driver->ops->unbind || - !driver->ops->disconnect || !driver->ops->setup) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return -EINVAL; - } - - if (priv->driver) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_DRIVER), 0); - return -EBUSY; - } -#endif + DEBUGASSERT(driver != NULL && + driver->ops->bind != NULL && + driver->ops->unbind != NULL && + driver->ops->disconnect != NULL && + driver->ops->setup != NULL); + DEBUGASSERT(priv->driver == NULL); /* First hook up the driver */ @@ -4746,14 +4869,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver) irqstate_t flags; usbtrace(TRACE_DEVUNREGISTER, 0); - -#ifdef CONFIG_DEBUG - if (driver != priv->driver) - { - usbtrace(TRACE_DEVERROR(SAM_TRACEERR_INVALIDPARMS), 0); - return -EINVAL; - } -#endif + DEBUGASSERT(driver == priv->driver); /* Reset the hardware and cancel all requests. All requests must be * canceled while the class driver is still bound. diff --git a/arch/arm/src/samv7/sam_xdmac.h b/arch/arm/src/samv7/sam_xdmac.h index 68c99bdbe14..d11913f3cf4 100644 --- a/arch/arm/src/samv7/sam_xdmac.h +++ b/arch/arm/src/samv7/sam_xdmac.h @@ -101,7 +101,9 @@ # define DMACH_FLAG_PERIPHPID(n) ((uint32_t)(n) << DMACH_FLAG_PERIPHPID_SHIFT) # define DMACH_FLAG_PERIPHPID_MAX DMACH_FLAG_PERIPHPID_MASK #define DMACH_FLAG_PERIPHH2SEL (0) /* No HW handshaking */ -#define DMACH_FLAG_PERIPHISPERIPH (1 << 7) /* Bit 7: 0=memory; 1=peripheral */ +#define DMACH_FLAG_PERIPHIS_MASK (1 << 7) /* Bit 7: Peripheral type */ +# define DMACH_FLAG_PERIPHISPERIPH (1 << 7) /* Bit 7: 1 = Peripheral */ +# define DMACH_FLAG_PERIPHISMEMORY (0 << 7) /* Bit 7: 0 = Memory */ #define DMACH_FLAG_PERIPHAHB_MASK (1 << 8) /* Bit 8: Peripheral ABH layer 1 */ # define DMACH_FLAG_PERIPHAHB_AHB_IF0 (0) # define DMACH_FLAG_PERIPHAHB_AHB_IF1 DMACH_FLAG_PERIPHAHB_MASK diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index 47ed9d1fb63..be780bc43fd 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -460,6 +460,30 @@ config ARCH_CHIP_STM32F302VC select STM32_STM32F30XX select ARCH_HAVE_FPU +config ARCH_CHIP_STM32F303K6 + bool "STM32F303K6" + select ARCH_CORTEXM4 + select STM32_STM32F30XX + select ARCH_HAVE_FPU + +config ARCH_CHIP_STM32F303K8 + bool "STM32F303K8" + select ARCH_CORTEXM4 + select STM32_STM32F30XX + select ARCH_HAVE_FPU + +config ARCH_CHIP_STM32F303C6 + bool "STM32F303C6" + select ARCH_CORTEXM4 + select STM32_STM32F30XX + select ARCH_HAVE_FPU + +config ARCH_CHIP_STM32F303C8 + bool "STM32F303C8" + select ARCH_CORTEXM4 + select STM32_STM32F30XX + select ARCH_HAVE_FPU + config ARCH_CHIP_STM32F303CB bool "STM32F303CB" select ARCH_CORTEXM4 @@ -484,6 +508,18 @@ config ARCH_CHIP_STM32F303RC select STM32_STM32F30XX select ARCH_HAVE_FPU +config ARCH_CHIP_STM32F303RD + bool "STM32F303RD" + select ARCH_CORTEXM4 + select STM32_STM32F30XX + select ARCH_HAVE_FPU + +config ARCH_CHIP_STM32F303RE + bool "STM32F303RE" + select ARCH_CORTEXM4 + select STM32_STM32F30XX + select ARCH_HAVE_FPU + config ARCH_CHIP_STM32F303VB bool "STM32F303VB" select ARCH_CORTEXM4 @@ -743,6 +779,8 @@ config ARCH_CHIP_STM32F446M select STM32_STM32F40XX select STM32_STM32F446 select ARCH_HAVE_FPU + select STM32_HAVE_SAIPLL + select STM32_HAVE_I2SPLL config ARCH_CHIP_STM32F446R bool "STM32F446R" @@ -750,6 +788,8 @@ config ARCH_CHIP_STM32F446R select STM32_STM32F40XX select STM32_STM32F446 select ARCH_HAVE_FPU + select STM32_HAVE_SAIPLL + select STM32_HAVE_I2SPLL config ARCH_CHIP_STM32F446V bool "STM32F446V" @@ -757,6 +797,8 @@ config ARCH_CHIP_STM32F446V select STM32_STM32F40XX select STM32_STM32F446 select ARCH_HAVE_FPU + select STM32_HAVE_SAIPLL + select STM32_HAVE_I2SPLL config ARCH_CHIP_STM32F446Z bool "STM32F446Z" @@ -764,7 +806,8 @@ config ARCH_CHIP_STM32F446Z select STM32_STM32F40XX select STM32_STM32F446 select ARCH_HAVE_FPU - + select STM32_HAVE_SAIPLL + select STM32_HAVE_I2SPLL endchoice @@ -1346,6 +1389,14 @@ config STM32_HAVE_SPI6 bool default n +config STM32_HAVE_SAIPLL + bool + default n + +config STM32_HAVE_I2SPLL + bool + default n + # These are the peripheral selections proper config STM32_ADC1 @@ -2009,6 +2060,24 @@ config ARCH_BOARD_STM32_CUSTOM_CLOCKCONFIG ---help--- Enables special, board-specific STM32 clock configuration. +config STM32_SAIPLL + bool "SAIPLL" + default n + depends on STM32_HAVE_SAIPLL + ---help--- + The STM32F446 has a separate PLL for the SAI block. + Set this true and provide configuration parameters in + board.h to use this PLL. + +config STM32_I2SPLL + bool "I2SPLL" + default n + depends on STM32_HAVE_I2SPLL + ---help--- + The STM32F446 has a separate PLL for the I2S block. + Set this true and provide configuration parameters in + board.h to use this PLL. + config STM32_CCMEXCLUDE bool "Exclude CCM SRAM from the heap" default y if ARCH_DMA || ELF diff --git a/arch/arm/src/stm32/Make.defs b/arch/arm/src/stm32/Make.defs index 8f4e473f7a2..2bff63515ad 100644 --- a/arch/arm/src/stm32/Make.defs +++ b/arch/arm/src/stm32/Make.defs @@ -95,6 +95,8 @@ ifeq ($(CONFIG_ARCH_FPU),y) CMN_ASRCS += up_fpu.S ifneq ($(CONFIG_ARMV7M_CMNVECTOR),y) CMN_CSRCS += up_copyarmstate.c +else ifeq ($(CONFIG_ARMV7M_LAZYFPU),y) +CMN_CSRCS += up_copyarmstate.c endif endif diff --git a/arch/arm/src/stm32/chip/stm32_adc.h b/arch/arm/src/stm32/chip/stm32_adc.h index ecb16576a23..ea9579c3918 100644 --- a/arch/arm/src/stm32/chip/stm32_adc.h +++ b/arch/arm/src/stm32/chip/stm32_adc.h @@ -270,7 +270,7 @@ #ifdef CONFIG_STM32_STM32F10XX # define ADC_CR2_CAL (1 << 2) /* Bit 2: A/D Calibration */ -#elif CONFIG_STM32_STM32L15XX +#elif defined(CONFIG_STM32_STM32L15XX) # define ADC_CR2_CFG (1 << 2) /* Bit 2 : ADC configuration. This bit must be modified only when no * conversion is on going. This bit is available in high and medium+ * density devices only. diff --git a/arch/arm/src/stm32/chip/stm32f44xxx_otgfs.h b/arch/arm/src/stm32/chip/stm32f44xxx_otgfs.h new file mode 100644 index 00000000000..231c4b352c4 --- /dev/null +++ b/arch/arm/src/stm32/chip/stm32f44xxx_otgfs.h @@ -0,0 +1,1022 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32f44xxx_otgfs.h + * + * Copyright (C) 2015 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_STM32_CHIP_STM32F44XXX_OTGFS_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32F44XXX_OTGFS_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ +/* General definitions */ + +#define OTGFS_EPTYPE_CTRL (0) /* Control */ +#define OTGFS_EPTYPE_ISOC (1) /* Isochronous */ +#define OTGFS_EPTYPE_BULK (2) /* Bulk */ +#define OTGFS_EPTYPE_INTR (3) /* Interrupt */ + +#define OTGFS_PID_DATA0 (0) +#define OTGFS_PID_DATA2 (1) +#define OTGFS_PID_DATA1 (2) +#define OTGFS_PID_MDATA (3) /* Non-control */ +#define OTGFS_PID_SETUP (3) /* Control */ + +/* Register Offsets *********************************************************************************/ +/* Core global control and status registers */ + +#define STM32_OTGFS_GOTGCTL_OFFSET 0x0000 /* Control and status register */ +#define STM32_OTGFS_GOTGINT_OFFSET 0x0004 /* Interrupt register */ +#define STM32_OTGFS_GAHBCFG_OFFSET 0x0008 /* AHB configuration register */ +#define STM32_OTGFS_GUSBCFG_OFFSET 0x000c /* USB configuration register */ +#define STM32_OTGFS_GRSTCTL_OFFSET 0x0010 /* Reset register */ +#define STM32_OTGFS_GINTSTS_OFFSET 0x0014 /* Core interrupt register */ +#define STM32_OTGFS_GINTMSK_OFFSET 0x0018 /* Interrupt mask register */ +#define STM32_OTGFS_GRXSTSR_OFFSET 0x001c /* Receive status debug read/OTG status read register */ +#define STM32_OTGFS_GRXSTSP_OFFSET 0x0020 /* Receive status debug read/OTG status pop register */ +#define STM32_OTGFS_GRXFSIZ_OFFSET 0x0024 /* Receive FIFO size register */ +#define STM32_OTGFS_HNPTXFSIZ_OFFSET 0x0028 /* Host non-periodic transmit FIFO size register */ +#define STM32_OTGFS_DIEPTXF0_OFFSET 0x0028 /* Endpoint 0 Transmit FIFO size */ +#define STM32_OTGFS_HNPTXSTS_OFFSET 0x002c /* Non-periodic transmit FIFO/queue status register */ +#define STM32_OTGFS_GCCFG_OFFSET 0x0038 /* General core configuration register */ +#define STM32_OTGFS_CID_OFFSET 0x003c /* Core ID register */ +#define STM32_OTGFS_HPTXFSIZ_OFFSET 0x0100 /* Host periodic transmit FIFO size register */ + +#define STM32_OTGFS_DIEPTXF_OFFSET(n) (104+(((n)-1) << 2)) +#define STM32_OTGFS_DIEPTXF1_OFFSET 0x0104 /* Device IN endpoint transmit FIFO1 size register */ +#define STM32_OTGFS_DIEPTXF2_OFFSET 0x0108 /* Device IN endpoint transmit FIFO2 size register */ +#define STM32_OTGFS_DIEPTXF3_OFFSET 0x010c /* Device IN endpoint transmit FIFO3 size register */ + +/* Host-mode control and status registers */ + +#define STM32_OTGFS_HCFG_OFFSET 0x0400 /* Host configuration register */ +#define STM32_OTGFS_HFIR_OFFSET 0x0404 /* Host frame interval register */ +#define STM32_OTGFS_HFNUM_OFFSET 0x0408 /* Host frame number/frame time remaining register */ +#define STM32_OTGFS_HPTXSTS_OFFSET 0x0410 /* Host periodic transmit FIFO/queue status register */ +#define STM32_OTGFS_HAINT_OFFSET 0x0414 /* Host all channels interrupt register */ +#define STM32_OTGFS_HAINTMSK_OFFSET 0x0418 /* Host all channels interrupt mask register */ +#define STM32_OTGFS_HPRT_OFFSET 0x0440 /* Host port control and status register */ + +#define STM32_OTGFS_CHAN_OFFSET(n) (0x500 + ((n) << 5) +#define STM32_OTGFS_HCCHAR_CHOFFSET 0x0000 /* Host channel characteristics register */ +#define STM32_OTGFS_HCINT_CHOFFSET 0x0008 /* Host channel interrupt register */ +#define STM32_OTGFS_HCINTMSK_CHOFFSET 0x000c /* Host channel interrupt mask register */ +#define STM32_OTGFS_HCTSIZ_CHOFFSET 0x0010 /* Host channel interrupt register */ + +#define STM32_OTGFS_HCCHAR_OFFSET(n) (0x500 + ((n) << 5)) +#define STM32_OTGFS_HCCHAR0_OFFSET 0x0500 /* Host channel-0 characteristics register */ +#define STM32_OTGFS_HCCHAR1_OFFSET 0x0520 /* Host channel-1 characteristics register */ +#define STM32_OTGFS_HCCHAR2_OFFSET 0x0540 /* Host channel-2 characteristics register */ +#define STM32_OTGFS_HCCHAR3_OFFSET 0x0560 /* Host channel-3 characteristics register */ +#define STM32_OTGFS_HCCHAR4_OFFSET 0x0580 /* Host channel-4 characteristics register */ +#define STM32_OTGFS_HCCHAR5_OFFSET 0x05a0 /* Host channel-5 characteristics register */ +#define STM32_OTGFS_HCCHAR6_OFFSET 0x05c0 /* Host channel-6 characteristics register */ +#define STM32_OTGFS_HCCHAR7_OFFSET 0x05e0 /* Host channel-7 characteristics register */ + +#define STM32_OTGFS_HCINT_OFFSET(n) (0x508 + ((n) << 5)) +#define STM32_OTGFS_HCINT0_OFFSET 0x0508 /* Host channel-0 interrupt register */ +#define STM32_OTGFS_HCINT1_OFFSET 0x0528 /* Host channel-1 interrupt register */ +#define STM32_OTGFS_HCINT2_OFFSET 0x0548 /* Host channel-2 interrupt register */ +#define STM32_OTGFS_HCINT3_OFFSET 0x0568 /* Host channel-3 interrupt register */ +#define STM32_OTGFS_HCINT4_OFFSET 0x0588 /* Host channel-4 interrupt register */ +#define STM32_OTGFS_HCINT5_OFFSET 0x05a8 /* Host channel-5 interrupt register */ +#define STM32_OTGFS_HCINT6_OFFSET 0x05c8 /* Host channel-6 interrupt register */ +#define STM32_OTGFS_HCINT7_OFFSET 0x05e8 /* Host channel-7 interrupt register */ + +#define STM32_OTGFS_HCINTMSK_OFFSET(n) (0x50c + ((n) << 5)) +#define STM32_OTGFS_HCINTMSK0_OFFSET 0x050c /* Host channel-0 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK1_OFFSET 0x052c /* Host channel-1 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK2_OFFSET 0x054c /* Host channel-2 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK3_OFFSET 0x056c /* Host channel-3 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK4_OFFSET 0x058c /* Host channel-4 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK5_OFFSET 0x05ac /* Host channel-5 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK6_OFFSET 0x05cc /* Host channel-6 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK7_OFFSET 0x05ec /* Host channel-7 interrupt mask register */ + +#define STM32_OTGFS_HCTSIZ_OFFSET(n) (0x510 + ((n) << 5)) +#define STM32_OTGFS_HCTSIZ0_OFFSET 0x0510 /* Host channel-0 interrupt register */ +#define STM32_OTGFS_HCTSIZ1_OFFSET 0x0530 /* Host channel-1 interrupt register */ +#define STM32_OTGFS_HCTSIZ2_OFFSET 0x0550 /* Host channel-2 interrupt register */ +#define STM32_OTGFS_HCTSIZ3_OFFSET 0x0570 /* Host channel-3 interrupt register */ +#define STM32_OTGFS_HCTSIZ4_OFFSET 0x0590 /* Host channel-4 interrupt register */ +#define STM32_OTGFS_HCTSIZ5_OFFSET 0x05b0 /* Host channel-5 interrupt register */ +#define STM32_OTGFS_HCTSIZ6_OFFSET 0x05d0 /* Host channel-6 interrupt register */ +#define STM32_OTGFS_HCTSIZ7_OFFSET 0x05f0 /* Host channel-7 interrupt register */ + +/* Device-mode control and status registers */ + +#define STM32_OTGFS_DCFG_OFFSET 0x0800 /* Device configuration register */ +#define STM32_OTGFS_DCTL_OFFSET 0x0804 /* Device control register */ +#define STM32_OTGFS_DSTS_OFFSET 0x0808 /* Device status register */ +#define STM32_OTGFS_DIEPMSK_OFFSET 0x0810 /* Device IN endpoint common interrupt mask register */ +#define STM32_OTGFS_DOEPMSK_OFFSET 0x0814 /* Device OUT endpoint common interrupt mask register */ +#define STM32_OTGFS_DAINT_OFFSET 0x0818 /* Device all endpoints interrupt register */ +#define STM32_OTGFS_DAINTMSK_OFFSET 0x081c /* All endpoints interrupt mask register */ +#define STM32_OTGFS_DVBUSDIS_OFFSET 0x0828 /* Device VBUS discharge time register */ +#define STM32_OTGFS_DVBUSPULSE_OFFSET 0x082c /* Device VBUS pulsing time register */ +#define STM32_OTGFS_DIEPEMPMSK_OFFSET 0x0834 /* Device IN endpoint FIFO empty interrupt mask register */ + +#define STM32_OTGFS_DIEP_OFFSET(n) (0x0900 + ((n) << 5)) +#define STM32_OTGFS_DIEPCTL_EPOFFSET 0x0000 /* Device endpoint control register */ +#define STM32_OTGFS_DIEPINT_EPOFFSET 0x0008 /* Device endpoint interrupt register */ +#define STM32_OTGFS_DIEPTSIZ_EPOFFSET 0x0010 /* Device IN endpoint transfer size register */ +#define STM32_OTGFS_DTXFSTS_EPOFFSET 0x0018 /* Device IN endpoint transmit FIFO status register */ + +#define STM32_OTGFS_DIEPCTL_OFFSET(n) (0x0900 + ((n) << 5)) +#define STM32_OTGFS_DIEPCTL0_OFFSET 0x0900 /* Device control IN endpoint 0 control register */ +#define STM32_OTGFS_DIEPCTL1_OFFSET 0x0920 /* Device control IN endpoint 2 control register */ +#define STM32_OTGFS_DIEPCTL2_OFFSET 0x0940 /* Device control IN endpoint 3 control register */ +#define STM32_OTGFS_DIEPCTL3_OFFSET 0x0960 /* Device control IN endpoint 4 control register */ + +#define STM32_OTGFS_DIEPINT_OFFSET(n) (0x0908 + ((n) << 5)) +#define STM32_OTGFS_DIEPINT0_OFFSET 0x0908 /* Device endpoint-0 interrupt register */ +#define STM32_OTGFS_DIEPINT1_OFFSET 0x0928 /* Device endpoint-1 interrupt register */ +#define STM32_OTGFS_DIEPINT2_OFFSET 0x0948 /* Device endpoint-2 interrupt register */ +#define STM32_OTGFS_DIEPINT3_OFFSET 0x0968 /* Device endpoint-3 interrupt register */ + +#define STM32_OTGFS_DIEPTSIZ_OFFSET(n) (0x910 + ((n) << 5)) +#define STM32_OTGFS_DIEPTSIZ0_OFFSET 0x0910 /* Device IN endpoint 0 transfer size register */ +#define STM32_OTGFS_DIEPTSIZ1_OFFSET 0x0930 /* Device IN endpoint 1 transfer size register */ +#define STM32_OTGFS_DIEPTSIZ2_OFFSET 0x0950 /* Device IN endpoint 2 transfer size register */ +#define STM32_OTGFS_DIEPTSIZ3_OFFSET 0x0970 /* Device IN endpoint 3 transfer size register */ + +#define STM32_OTGFS_DTXFSTS_OFFSET(n) (0x0918 + ((n) << 5)) +#define STM32_OTGFS_DTXFSTS0_OFFSET 0x0918 /* Device OUT endpoint-0 TxFIFO status register */ +#define STM32_OTGFS_DTXFSTS1_OFFSET 0x0938 /* Device OUT endpoint-1 TxFIFO status register */ +#define STM32_OTGFS_DTXFSTS2_OFFSET 0x0958 /* Device OUT endpoint-2 TxFIFO status register */ +#define STM32_OTGFS_DTXFSTS3_OFFSET 0x0978 /* Device OUT endpoint-3 TxFIFO status register */ + +#define STM32_OTGFS_DOEP_OFFSET(n) (0x0b00 + ((n) << 5)) +#define STM32_OTGFS_DOEPCTL_EPOFFSET 0x0000 /* Device control OUT endpoint 0 control register */ +#define STM32_OTGFS_DOEPINT_EPOFFSET 0x0008 /* Device endpoint-x interrupt register */ + +#define STM32_OTGFS_DOEPCTL_OFFSET(n) (0x0b00 + ((n) << 5)) +#define STM32_OTGFS_DOEPCTL0_OFFSET 0x00b00 /* Device OUT endpoint 0 control register */ +#define STM32_OTGFS_DOEPCTL1_OFFSET 0x00b20 /* Device OUT endpoint 1 control register */ +#define STM32_OTGFS_DOEPCTL2_OFFSET 0x00b40 /* Device OUT endpoint 2 control register */ +#define STM32_OTGFS_DOEPCTL3_OFFSET 0x00b60 /* Device OUT endpoint 3 control register */ + +#define STM32_OTGFS_DOEPINT_OFFSET(n) (0x0b08 + ((n) << 5)) +#define STM32_OTGFS_DOEPINT0_OFFSET 0x00b08 /* Device endpoint-0 interrupt register */ +#define STM32_OTGFS_DOEPINT1_OFFSET 0x00b28 /* Device endpoint-1 interrupt register */ +#define STM32_OTGFS_DOEPINT2_OFFSET 0x00b48 /* Device endpoint-2 interrupt register */ +#define STM32_OTGFS_DOEPINT3_OFFSET 0x00b68 /* Device endpoint-3 interrupt register */ + +#define STM32_OTGFS_DOEPTSIZ_OFFSET(n) (0x0b10 + ((n) << 5)) +#define STM32_OTGFS_DOEPTSIZ0_OFFSET 0x00b10 /* Device OUT endpoint-0 transfer size register */ +#define STM32_OTGFS_DOEPTSIZ1_OFFSET 0x00b30 /* Device OUT endpoint-1 transfer size register */ +#define STM32_OTGFS_DOEPTSIZ2_OFFSET 0x00b50 /* Device OUT endpoint-2 transfer size register */ +#define STM32_OTGFS_DOEPTSIZ3_OFFSET 0x00b70 /* Device OUT endpoint-3 transfer size register */ + +/* Power and clock gating registers */ + +#define STM32_OTGFS_PCGCCTL_OFFSET 0x0e00 /* Power and clock gating control register */ + +/* Data FIFO (DFIFO) access registers */ + +#define STM32_OTGFS_DFIFO_DEP_OFFSET(n) (0x1000 + ((n) << 12)) +#define STM32_OTGFS_DFIFO_HCH_OFFSET(n) (0x1000 + ((n) << 12)) + +#define STM32_OTGFS_DFIFO_DEP0_OFFSET 0x1000 /* 0x1000-0x1ffc Device IN/OUT Endpoint 0 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH0_OFFSET 0x1000 /* 0x1000-0x1ffc Host OUT/IN Channel 0 DFIFO Read/Write Access */ + +#define STM32_OTGFS_DFIFO_DEP1_OFFSET 0x2000 /* 0x2000-0x2ffc Device IN/OUT Endpoint 1 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH1_OFFSET 0x2000 /* 0x2000-0x2ffc Host OUT/IN Channel 1 DFIFO Read/Write Access */ + +#define STM32_OTGFS_DFIFO_DEP2_OFFSET 0x3000 /* 0x3000-0x3ffc Device IN/OUT Endpoint 2 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH2_OFFSET 0x3000 /* 0x3000-0x3ffc Host OUT/IN Channel 2 DFIFO Read/Write Access */ + +#define STM32_OTGFS_DFIFO_DEP3_OFFSET 0x4000 /* 0x4000-0x4ffc Device IN/OUT Endpoint 3 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH3_OFFSET 0x4000 /* 0x4000-0x4ffc Host OUT/IN Channel 3 DFIFO Read/Write Access */ + +/* Register Addresses *******************************************************************************/ + +#define STM32_OTGFS_GOTGCTL (STM32_OTGFS_BASE+STM32_OTGFS_GOTGCTL_OFFSET) +#define STM32_OTGFS_GOTGINT (STM32_OTGFS_BASE+STM32_OTGFS_GOTGINT_OFFSET) +#define STM32_OTGFS_GAHBCFG (STM32_OTGFS_BASE+STM32_OTGFS_GAHBCFG_OFFSET) +#define STM32_OTGFS_GUSBCFG (STM32_OTGFS_BASE+STM32_OTGFS_GUSBCFG_OFFSET) +#define STM32_OTGFS_GRSTCTL (STM32_OTGFS_BASE+STM32_OTGFS_GRSTCTL_OFFSET) +#define STM32_OTGFS_GINTSTS (STM32_OTGFS_BASE+STM32_OTGFS_GINTSTS_OFFSET) +#define STM32_OTGFS_GINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_GINTMSK_OFFSET) +#define STM32_OTGFS_GRXSTSR (STM32_OTGFS_BASE+STM32_OTGFS_GRXSTSR_OFFSET) +#define STM32_OTGFS_GRXSTSP (STM32_OTGFS_BASE+STM32_OTGFS_GRXSTSP_OFFSET) +#define STM32_OTGFS_GRXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_GRXFSIZ_OFFSET) +#define STM32_OTGFS_HNPTXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_HNPTXFSIZ_OFFSET) +#define STM32_OTGFS_DIEPTXF0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF0_OFFSET) +#define STM32_OTGFS_HNPTXSTS (STM32_OTGFS_BASE+STM32_OTGFS_HNPTXSTS_OFFSET) +#define STM32_OTGFS_GCCFG (STM32_OTGFS_BASE+STM32_OTGFS_GCCFG_OFFSET) +#define STM32_OTGFS_CID (STM32_OTGFS_BASE+STM32_OTGFS_CID_OFFSET) +#define STM32_OTGFS_HPTXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_HPTXFSIZ_OFFSET) + +#define STM32_OTGFS_DIEPTXF(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF_OFFSET(n)) +#define STM32_OTGFS_DIEPTXF1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF1_OFFSET) +#define STM32_OTGFS_DIEPTXF2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF2_OFFSET) +#define STM32_OTGFS_DIEPTXF3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF3_OFFSET) + +/* Host-mode control and status registers */ + +#define STM32_OTGFS_HCFG (STM32_OTGFS_BASE+STM32_OTGFS_HCFG_OFFSET) +#define STM32_OTGFS_HFIR (STM32_OTGFS_BASE+STM32_OTGFS_HFIR_OFFSET) +#define STM32_OTGFS_HFNUM (STM32_OTGFS_BASE+STM32_OTGFS_HFNUM_OFFSET) +#define STM32_OTGFS_HPTXSTS (STM32_OTGFS_BASE+STM32_OTGFS_HPTXSTS_OFFSET) +#define STM32_OTGFS_HAINT (STM32_OTGFS_BASE+STM32_OTGFS_HAINT_OFFSET) +#define STM32_OTGFS_HAINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_HAINTMSK_OFFSET) +#define STM32_OTGFS_HPRT (STM32_OTGFS_BASE+STM32_OTGFS_HPRT_OFFSET) + +#define STM32_OTGFS_CHAN(n) (STM32_OTGFS_BASE+STM32_OTGFS_CHAN_OFFSET(n)) + +#define STM32_OTGFS_HCCHAR(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR_OFFSET(n)) +#define STM32_OTGFS_HCCHAR0 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR0_OFFSET) +#define STM32_OTGFS_HCCHAR1 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR1_OFFSET) +#define STM32_OTGFS_HCCHAR2 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR2_OFFSET) +#define STM32_OTGFS_HCCHAR3 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR3_OFFSET) +#define STM32_OTGFS_HCCHAR4 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR4_OFFSET) +#define STM32_OTGFS_HCCHAR5 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR5_OFFSET) +#define STM32_OTGFS_HCCHAR6 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR6_OFFSET) +#define STM32_OTGFS_HCCHAR7 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR7_OFFSET) + +#define STM32_OTGFS_HCINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCINT_OFFSET(n)) +#define STM32_OTGFS_HCINT0 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT0_OFFSET) +#define STM32_OTGFS_HCINT1 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT1_OFFSET) +#define STM32_OTGFS_HCINT2 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT2_OFFSET) +#define STM32_OTGFS_HCINT3 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT3_OFFSET) +#define STM32_OTGFS_HCINT4 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT4_OFFSET) +#define STM32_OTGFS_HCINT5 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT5_OFFSET) +#define STM32_OTGFS_HCINT6 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT6_OFFSET) +#define STM32_OTGFS_HCINT7 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT7_OFFSET) + +#define STM32_OTGFS_HCINTMSK(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK_OFFSET(n)) +#define STM32_OTGFS_HCINTMSK0 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK0_OFFSET) +#define STM32_OTGFS_HCINTMSK1 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK1_OFFSET) +#define STM32_OTGFS_HCINTMSK2 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK2_OFFSET) +#define STM32_OTGFS_HCINTMSK3 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK3_OFFSET) +#define STM32_OTGFS_HCINTMSK4 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK4_OFFSET) +#define STM32_OTGFS_HCINTMSK5 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK5_OFFSET) +#define STM32_OTGFS_HCINTMSK6 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK6_OFFSET) +#define STM32_OTGFS_HCINTMSK7 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK7_OFFSET)_ + +#define STM32_OTGFS_HCTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ_OFFSET(n)) +#define STM32_OTGFS_HCTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ0_OFFSET) +#define STM32_OTGFS_HCTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ1_OFFSET) +#define STM32_OTGFS_HCTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ2_OFFSET) +#define STM32_OTGFS_HCTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ3_OFFSET) +#define STM32_OTGFS_HCTSIZ4 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ4_OFFSET) +#define STM32_OTGFS_HCTSIZ5 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ5_OFFSET) +#define STM32_OTGFS_HCTSIZ6 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ6_OFFSET) +#define STM32_OTGFS_HCTSIZ7 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ7_OFFSET) + +/* Device-mode control and status registers */ + +#define STM32_OTGFS_DCFG (STM32_OTGFS_BASE+STM32_OTGFS_DCFG_OFFSET) +#define STM32_OTGFS_DCTL (STM32_OTGFS_BASE+STM32_OTGFS_DCTL_OFFSET) +#define STM32_OTGFS_DSTS (STM32_OTGFS_BASE+STM32_OTGFS_DSTS_OFFSET) +#define STM32_OTGFS_DIEPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DIEPMSK_OFFSET) +#define STM32_OTGFS_DOEPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DOEPMSK_OFFSET) +#define STM32_OTGFS_DAINT (STM32_OTGFS_BASE+STM32_OTGFS_DAINT_OFFSET) +#define STM32_OTGFS_DAINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_DAINTMSK_OFFSET) +#define STM32_OTGFS_DVBUSDIS (STM32_OTGFS_BASE+STM32_OTGFS_DVBUSDIS_OFFSET) +#define STM32_OTGFS_DVBUSPULSE (STM32_OTGFS_BASE+STM32_OTGFS_DVBUSPULSE_OFFSET) +#define STM32_OTGFS_DIEPEMPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DIEPEMPMSK_OFFSET) + +#define STM32_OTGFS_DIEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEP_OFFSET(n)) + +#define STM32_OTGFS_DIEPCTL(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL_OFFSET(n)) +#define STM32_OTGFS_DIEPCTL0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL0_OFFSET) +#define STM32_OTGFS_DIEPCTL1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL1_OFFSET) +#define STM32_OTGFS_DIEPCTL2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL2_OFFSET) +#define STM32_OTGFS_DIEPCTL3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL3_OFFSET) + +#define STM32_OTGFS_DIEPINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT_OFFSET(n)) +#define STM32_OTGFS_DIEPINT0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT0_OFFSET) +#define STM32_OTGFS_DIEPINT1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT1_OFFSET) +#define STM32_OTGFS_DIEPINT2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT2_OFFSET) +#define STM32_OTGFS_DIEPINT3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT3_OFFSET) + +#define STM32_OTGFS_DIEPTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ_OFFSET(n)) +#define STM32_OTGFS_DIEPTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ0_OFFSET) +#define STM32_OTGFS_DIEPTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ1_OFFSET) +#define STM32_OTGFS_DIEPTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ2_OFFSET) +#define STM32_OTGFS_DIEPTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ3_OFFSET) + +#define STM32_OTGFS_DTXFSTS(n) (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS_OFFSET(n)) +#define STM32_OTGFS_DTXFSTS0 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS0_OFFSET) +#define STM32_OTGFS_DTXFSTS1 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS1_OFFSET) +#define STM32_OTGFS_DTXFSTS2 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS2_OFFSET) +#define STM32_OTGFS_DTXFSTS3 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS3_OFFSET) + +#define STM32_OTGFS_DOEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEP_OFFSET(n)) + +#define STM32_OTGFS_DOEPCTL(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL_OFFSET(n)) +#define STM32_OTGFS_DOEPCTL0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL0_OFFSET) +#define STM32_OTGFS_DOEPCTL1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL1_OFFSET) +#define STM32_OTGFS_DOEPCTL2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL2_OFFSET) +#define STM32_OTGFS_DOEPCTL3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL3_OFFSET) + +#define STM32_OTGFS_DOEPINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT_OFFSET(n)) +#define STM32_OTGFS_DOEPINT0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT0_OFFSET) +#define STM32_OTGFS_DOEPINT1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT1_OFFSET) +#define STM32_OTGFS_DOEPINT2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT2_OFFSET) +#define STM32_OTGFS_DOEPINT3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT3_OFFSET) + +#define STM32_OTGFS_DOEPTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ_OFFSET(n)) +#define STM32_OTGFS_DOEPTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ0_OFFSET) +#define STM32_OTGFS_DOEPTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ1_OFFSET) +#define STM32_OTGFS_DOEPTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ2_OFFSET) +#define STM32_OTGFS_DOEPTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ3_OFFSET) + +/* Power and clock gating registers */ + +#define STM32_OTGFS_PCGCCTL (STM32_OTGFS_BASE+STM32_OTGFS_PCGCCTL_OFFSET) + +/* Data FIFO (DFIFO) access registers */ + +#define STM32_OTGFS_DFIFO_DEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP_OFFSET(n)) +#define STM32_OTGFS_DFIFO_HCH(n) (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH_OFFSET(n)) + +#define STM32_OTGFS_DFIFO_DEP0 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP0_OFFSET) +#define STM32_OTGFS_DFIFO_HCH0 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH0_OFFSET) + +#define STM32_OTGFS_DFIFO_DEP1 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP1_OFFSET) +#define STM32_OTGFS_DFIFO_HCH1 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH1_OFFSET) + +#define STM32_OTGFS_DFIFO_DEP2 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP2_OFFSET) +#define STM32_OTGFS_DFIFO_HCH2 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH2_OFFSET) + +#define STM32_OTGFS_DFIFO_DEP3 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP3_OFFSET) +#define STM32_OTGFS_DFIFO_HCH3 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH3_OFFSET) + +/* Register Bitfield Definitions ********************************************************************/ +/* Core global control and status registers */ + +/* Control and status register */ + +#define OTGFS_GOTGCTL_SRQSCS (1 << 0) /* Bit 0: Session request success */ +#define OTGFS_GOTGCTL_SRQ (1 << 1) /* Bit 1: Session request */ +#define OTGFS_GOTGCTL_VBVALOEN (1 << 2) /* Bit 2: VBUS valid override enable */ +#define OTGFS_GOTGCTL_VBVALOVAL (1 << 3) /* Bit 3: VBUS valid override value */ +#define OTGFS_GOTGCTL_AVALOEN (1 << 4) /* Bit 4: A-peripheral session valid override enable */ +#define OTGFS_GOTGCTL_AVALOVAL (1 << 5) /* Bit 5: A-peripheral session valid override value */ +#define OTGFS_GOTGCTL_BVALOEN (1 << 6) /* Bit 6: B-peripheral session valid override enable */ +#define OTGFS_GOTGCTL_BVALOVAL (1 << 7) /* Bit 7: B-peripheral session valid override value */ +#define OTGFS_GOTGCTL_HNGSCS (1 << 8) /* Bit 8: Host set HNP enable */ +#define OTGFS_GOTGCTL_HNPRQ (1 << 9) /* Bit 9: HNP request */ +#define OTGFS_GOTGCTL_HSHNPEN (1 << 10) /* Bit 10: host set HNP enable */ +#define OTGFS_GOTGCTL_DHNPEN (1 << 11) /* Bit 11: Device HNP enabled */ +#define OTGFS_GOTGCTL_EHEN (1 << 12) /* Bit 12: Embedded host enable */ + /* Bits 13-15: Reserved, must be kept at reset value */ +#define OTGFS_GOTGCTL_CIDSTS (1 << 16) /* Bit 16: Connector ID status */ +#define OTGFS_GOTGCTL_DBCT (1 << 17) /* Bit 17: Long/short debounce time */ +#define OTGFS_GOTGCTL_ASVLD (1 << 18) /* Bit 18: A-session valid */ +#define OTGFS_GOTGCTL_BSVLD (1 << 19) /* Bit 19: B-session valid */ +#define OTGFS_GOTGCTL_OTGVER (1 << 20) /* Bit 20: OTG version */ + /* Bits 21-31: Reserved, must be kept at reset value */ + +/* Interrupt register */ + /* Bits 1:0 Reserved, must be kept at reset value */ +#define OTGFS_GOTGINT_SEDET (1 << 2) /* Bit 2: Session end detected */ + /* Bits 3-7: Reserved, must be kept at reset value */ +#define OTGFS_GOTGINT_SRSSCHG (1 << 8) /* Bit 8: Session request success status change */ +#define OTGFS_GOTGINT_HNSSCHG (1 << 9) /* Bit 9: Host negotiation success status change */ + /* Bits 16:10 Reserved, must be kept at reset value */ +#define OTGFS_GOTGINT_HNGDET (1 << 17) /* Bit 17: Host negotiation detected */ +#define OTGFS_GOTGINT_ADTOCHG (1 << 18) /* Bit 18: A-device timeout change */ +#define OTGFS_GOTGINT_DBCDNE (1 << 19) /* Bit 19: Debounce done */ +#define OTGFS_GOTGINT_IDCHNG (1 << 20) /* Bit 20: Change in ID pin input value */ + /* Bits 21-31: Reserved, must be kept at reset value */ + +/* AHB configuration register */ + +#define OTGFS_GAHBCFG_GINTMSK (1 << 0) /* Bit 0: Global interrupt mask */ + /* Bits 1-6: Reserved, must be kept at reset value */ +#define OTGFS_GAHBCFG_TXFELVL (1 << 7) /* Bit 7: TxFIFO empty level */ +#define OTGFS_GAHBCFG_PTXFELVL (1 << 8) /* Bit 8: Periodic TxFIFO empty level */ + /* Bits 20-31: Reserved, must be kept at reset value */ +/* USB configuration register */ + +#define OTGFS_GUSBCFG_TOCAL_SHIFT (0) /* Bits 0-2: FS timeout calibration */ +#define OTGFS_GUSBCFG_TOCAL_MASK (7 << OTGFS_GUSBCFG_TOCAL_SHIFT) + /* Bits 3-5: Reserved, must be kept at reset value */ +#define OTGFS_GUSBCFG_PHYSEL (1 << 6) /* Bit 6: Full Speed serial transceiver select */ + /* Bit 7: Reserved, must be kept at reset value */ +#define OTGFS_GUSBCFG_SRPCAP (1 << 8) /* Bit 8: SRP-capable */ +#define OTGFS_GUSBCFG_HNPCAP (1 << 9) /* Bit 9: HNP-capable */ +#define OTGFS_GUSBCFG_TRDT_SHIFT (10) /* Bits 10-13: USB turnaround time */ +#define OTGFS_GUSBCFG_TRDT_MASK (15 << OTGFS_GUSBCFG_TRDT_SHIFT) +# define OTGFS_GUSBCFG_TRDT(n) ((n) << OTGFS_GUSBCFG_TRDT_SHIFT) + /* Bits 14-28: Reserved, must be kept at reset value */ +#define OTGFS_GUSBCFG_FHMOD (1 << 29) /* Bit 29: Force host mode */ +#define OTGFS_GUSBCFG_FDMOD (1 << 30) /* Bit 30: Force device mode */ +#define OTGFS_GUSBCFG_CTXPKT (1 << 31) /* Bit 31: Corrupt Tx packet */ + /* Bits 20-31: Reserved, must be kept at reset value */ +/* Reset register */ + +#define OTGFS_GRSTCTL_CSRST (1 << 0) /* Bit 0: Core soft reset */ +#define OTGFS_GRSTCTL_HSRST (1 << 1) /* Bit 1: HCLK soft reset */ +#define OTGFS_GRSTCTL_FCRST (1 << 2) /* Bit 2: Host frame counter reset */ + /* Bit 3 Reserved, must be kept at reset value */ +#define OTGFS_GRSTCTL_RXFFLSH (1 << 4) /* Bit 4: RxFIFO flush */ +#define OTGFS_GRSTCTL_TXFFLSH (1 << 5) /* Bit 5: TxFIFO flush */ +#define OTGFS_GRSTCTL_TXFNUM_SHIFT (6) /* Bits 6-10: TxFIFO number */ +#define OTGFS_GRSTCTL_TXFNUM_MASK (31 << OTGFS_GRSTCTL_TXFNUM_SHIFT) +# define OTGFS_GRSTCTL_TXFNUM_HNONPER (0 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Non-periodic TxFIFO flush in host mode */ +# define OTGFS_GRSTCTL_TXFNUM_HPER (1 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Periodic TxFIFO flush in host mode */ +# define OTGFS_GRSTCTL_TXFNUM_HALL (16 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Flush all the transmit FIFOs in host mode.*/ +# define OTGFS_GRSTCTL_TXFNUM_D(n) ((n) << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* TXFIFO n flush in device mode, n=0-15 */ +# define OTGFS_GRSTCTL_TXFNUM_DALL (16 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Flush all the transmit FIFOs in device mode.*/ + /* Bits 11-31: Reserved, must be kept at reset value */ +#define OTGFS_GRSTCTL_AHBIDL (1 << 31) /* Bit 31: AHB master idle */ + +/* Core interrupt and Interrupt mask registers */ + +#define OTGFS_GINTSTS_CMOD (1 << 0) /* Bit 0: Current mode of operation */ +# define OTGFS_GINTSTS_DEVMODE (0) +# define OTGFS_GINTSTS_HOSTMODE (OTGFS_GINTSTS_CMOD) +#define OTGFS_GINT_MMIS (1 << 1) /* Bit 1: Mode mismatch interrupt */ +#define OTGFS_GINT_OTG (1 << 2) /* Bit 2: OTG interrupt */ +#define OTGFS_GINT_SOF (1 << 3) /* Bit 3: Start of frame */ +#define OTGFS_GINT_RXFLVL (1 << 4) /* Bit 4: RxFIFO non-empty */ +#define OTGFS_GINT_NPTXFE (1 << 5) /* Bit 5: Non-periodic TxFIFO empty */ +#define OTGFS_GINT_GINAKEFF (1 << 6) /* Bit 6: Global IN non-periodic NAK effective */ +#define OTGFS_GINT_GONAKEFF (1 << 7) /* Bit 7: Global OUT NAK effective */ + /* Bits 8-9: Reserved, must be kept at reset value */ +#define OTGFS_GINT_ESUSP (1 << 10) /* Bit 10: Early suspend */ +#define OTGFS_GINT_USBSUSP (1 << 11) /* Bit 11: USB suspend */ +#define OTGFS_GINT_USBRST (1 << 12) /* Bit 12: USB reset */ +#define OTGFS_GINT_ENUMDNE (1 << 13) /* Bit 13: Enumeration done */ +#define OTGFS_GINT_ISOODRP (1 << 14) /* Bit 14: Isochronous OUT packet dropped interrupt */ +#define OTGFS_GINT_EOPF (1 << 15) /* Bit 15: End of periodic frame interrupt */ + /* Bits 16 Reserved, must be kept at reset value */ +#define OTGFS_GINTMSK_EPMISM (1 << 17) /* Bit 17: Endpoint mismatch interrupt mask */ +#define OTGFS_GINT_IEP (1 << 18) /* Bit 18: IN endpoint interrupt */ +#define OTGFS_GINT_OEP (1 << 19) /* Bit 19: OUT endpoint interrupt */ +#define OTGFS_GINT_IISOIXFR (1 << 20) /* Bit 20: Incomplete isochronous IN transfer */ +#define OTGFS_GINT_IISOOXFR (1 << 21) /* Bit 21: Incomplete isochronous OUT transfer (device) */ +#define OTGFS_GINT_IPXFR (1 << 21) /* Bit 21: Incomplete periodic transfer (host) */ + /* Bit 22: Reserved, must be kept at reset value */ +#define OTGFS_GINT_RSTDET (1 << 23) /* Bit 23: Reset detected interrupt */ +#define OTGFS_GINT_HPRT (1 << 24) /* Bit 24: Host port interrupt */ +#define OTGFS_GINT_HC (1 << 25) /* Bit 25: Host channels interrupt */ +#define OTGFS_GINT_PTXFE (1 << 26) /* Bit 26: Periodic TxFIFO empty */ +#define OTGFS_GINT_LPMINT (1 << 27) /* Bit 27: LPM interrupt */ +#define OTGFS_GINT_CIDSCHG (1 << 28) /* Bit 28: Connector ID status change */ +#define OTGFS_GINT_DISC (1 << 29) /* Bit 29: Disconnect detected interrupt */ +#define OTGFS_GINT_SRQ (1 << 30) /* Bit 30: Session request/new session detected interrupt */ +#define OTGFS_GINT_WKUP (1 << 31) /* Bit 31: Resume/remote wakeup detected interrupt */ + +/* Receive status debug read/OTG status read and pop registers (host mode) */ + +#define OTGFS_GRXSTSH_CHNUM_SHIFT (0) /* Bits 0-3: Channel number */ +#define OTGFS_GRXSTSH_CHNUM_MASK (15 << OTGFS_GRXSTSH_CHNUM_SHIFT) +#define OTGFS_GRXSTSH_BCNT_SHIFT (4) /* Bits 4-14: Byte count */ +#define OTGFS_GRXSTSH_BCNT_MASK (0x7ff << OTGFS_GRXSTSH_BCNT_SHIFT) +#define OTGFS_GRXSTSH_DPID_SHIFT (15) /* Bits 15-16: Data PID */ +#define OTGFS_GRXSTSH_DPID_MASK (3 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_DATA0 (0 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_DATA2 (1 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_DATA1 (2 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_MDATA (3 << OTGFS_GRXSTSH_DPID_SHIFT) +#define OTGFS_GRXSTSH_PKTSTS_SHIFT (17) /* Bits 17-20: Packet status */ +#define OTGFS_GRXSTSH_PKTSTS_MASK (15 << OTGFS_GRXSTSH_PKTSTS_SHIFT) +# define OTGFS_GRXSTSH_PKTSTS_INRECVD (2 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* IN data packet received */ +# define OTGFS_GRXSTSH_PKTSTS_INDONE (3 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* IN transfer completed */ +# define OTGFS_GRXSTSH_PKTSTS_DTOGERR (5 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* Data toggle error */ +# define OTGFS_GRXSTSH_PKTSTS_HALTED (7 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* Channel halted */ + /* Bits 21-31: Reserved, must be kept at reset value */ +/* Receive status debug read/OTG status read and pop registers (device mode) */ + +#define OTGFS_GRXSTSD_EPNUM_SHIFT (0) /* Bits 0-3: Endpoint number */ +#define OTGFS_GRXSTSD_EPNUM_MASK (15 << OTGFS_GRXSTSD_EPNUM_SHIFT) +#define OTGFS_GRXSTSD_BCNT_SHIFT (4) /* Bits 4-14: Byte count */ +#define OTGFS_GRXSTSD_BCNT_MASK (0x7ff << OTGFS_GRXSTSD_BCNT_SHIFT) +#define OTGFS_GRXSTSD_DPID_SHIFT (15) /* Bits 15-16: Data PID */ +#define OTGFS_GRXSTSD_DPID_MASK (3 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_DATA0 (0 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_DATA2 (1 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_DATA1 (2 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_MDATA (3 << OTGFS_GRXSTSD_DPID_SHIFT) +#define OTGFS_GRXSTSD_PKTSTS_SHIFT (17) /* Bits 17-20: Packet status */ +#define OTGFS_GRXSTSD_PKTSTS_MASK (15 << OTGFS_GRXSTSD_PKTSTS_SHIFT) +# define OTGFS_GRXSTSD_PKTSTS_OUTNAK (1 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* Global OUT NAK */ +# define OTGFS_GRXSTSD_PKTSTS_OUTRECVD (2 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* OUT data packet received */ +# define OTGFS_GRXSTSD_PKTSTS_OUTDONE (3 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* OUT transfer completed */ +# define OTGFS_GRXSTSD_PKTSTS_SETUPDONE (4 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* SETUP transaction completed */ +# define OTGFS_GRXSTSD_PKTSTS_SETUPRECVD (6 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* SETUP data packet received */ +#define OTGFS_GRXSTSD_FRMNUM_SHIFT (21) /* Bits 21-24: Frame number */ +#define OTGFS_GRXSTSD_FRMNUM_MASK (15 << OTGFS_GRXSTSD_FRMNUM_SHIFT) + /* Bits 25-31: Reserved, must be kept at reset value */ +/* Receive FIFO size register */ + +#define OTGFS_GRXFSIZ_MASK (0xffff) + +/* Host non-periodic transmit FIFO size register */ + +#define OTGFS_HNPTXFSIZ_NPTXFSA_SHIFT (0) /* Bits 0-15: Non-periodic transmit RAM start address */ +#define OTGFS_HNPTXFSIZ_NPTXFSA_MASK (0xffff << OTGFS_HNPTXFSIZ_NPTXFSA_SHIFT) +#define OTGFS_HNPTXFSIZ_NPTXFD_SHIFT (16) /* Bits 16-31: Non-periodic TxFIFO depth */ +#define OTGFS_HNPTXFSIZ_NPTXFD_MASK (0xffff << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT) +# define OTGFS_HNPTXFSIZ_NPTXFD_MIN (16 << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT) +# define OTGFS_HNPTXFSIZ_NPTXFD_MAX (256 << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT) + +/* Endpoint 0 Transmit FIFO size */ + +#define OTGFS_DIEPTXF0_TX0FD_SHIFT (0) /* Bits 0-15: Endpoint 0 transmit RAM start address */ +#define OTGFS_DIEPTXF0_TX0FD_MASK (0xffff << OTGFS_DIEPTXF0_TX0FD_SHIFT) +#define OTGFS_DIEPTXF0_TX0FSA_SHIFT (16) /* Bits 16-31: Endpoint 0 TxFIFO depth */ +#define OTGFS_DIEPTXF0_TX0FSA_MASK (0xffff << OTGFS_DIEPTXF0_TX0FSA_SHIFT) +# define OTGFS_DIEPTXF0_TX0FSA_MIN (16 << OTGFS_DIEPTXF0_TX0FSA_SHIFT) +# define OTGFS_DIEPTXF0_TX0FSA_MAX (256 << OTGFS_DIEPTXF0_TX0FSA_SHIFT) + +/* Non-periodic transmit FIFO/queue status register */ + +#define OTGFS_HNPTXSTS_NPTXFSAV_SHIFT (0) /* Bits 0-15: Non-periodic TxFIFO space available */ +#define OTGFS_HNPTXSTS_NPTXFSAV_MASK (0xffff << OTGFS_HNPTXSTS_NPTXFSAV_SHIFT) +# define OTGFS_HNPTXSTS_NPTXFSAV_FULL (0 << OTGFS_HNPTXSTS_NPTXFSAV_SHIFT) +#define OTGFS_HNPTXSTS_NPTQXSAV_SHIFT (16) /* Bits 16-23: Non-periodic transmit request queue space available */ +#define OTGFS_HNPTXSTS_NPTQXSAV_MASK (0xff << OTGFS_HNPTXSTS_NPTQXSAV_SHIFT) +# define OTGFS_HNPTXSTS_NPTQXSAV_FULL (0 << OTGFS_HNPTXSTS_NPTQXSAV_SHIFT) +#define OTGFS_HNPTXSTS_NPTXQTOP_SHIFT (24) /* Bits 24-30: Top of the non-periodic transmit request queue */ +#define OTGFS_HNPTXSTS_NPTXQTOP_MASK (0x7f << OTGFS_HNPTXSTS_NPTXQTOP_SHIFT) +# define OTGFS_HNPTXSTS_TERMINATE (1 << 24) /* Bit 24: Terminate (last entry for selected channel/endpoint) */ +# define OTGFS_HNPTXSTS_TYPE_SHIFT (25) /* Bits 25-26: Status */ +# define OTGFS_HNPTXSTS_TYPE_MASK (3 << OTGFS_HNPTXSTS_TYPE_SHIFT) +# define OTGFS_HNPTXSTS_TYPE_INOUT (0 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* IN/OUT token */ +# define OTGFS_HNPTXSTS_TYPE_ZLP (1 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* Zero-length transmit packet (device IN/host OUT) */ +# define OTGFS_HNPTXSTS_TYPE_HALT (3 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* Channel halt command */ +# define OTGFS_HNPTXSTS_CHNUM_SHIFT (27) /* Bits 27-30: Channel number */ +# define OTGFS_HNPTXSTS_CHNUM_MASK (15 << OTGFS_HNPTXSTS_CHNUM_SHIFT) +# define OTGFS_HNPTXSTS_EPNUM_SHIFT (27) /* Bits 27-30: Endpoint number */ +# define OTGFS_HNPTXSTS_EPNUM_MASK (15 << OTGFS_HNPTXSTS_EPNUM_SHIFT) + /* Bit 31 Reserved, must be kept at reset value */ +/* General core configuration register */ + /* Bits 15:0 Reserved, must be kept at reset value */ +#define OTGFS_GCCFG_PWRDWN (1 << 16) /* Bit 16: Power down */ + /* Bit 17 Reserved, must be kept at reset value */ + /* Bits 18:20 Reserved, must be kept at reset value */ +#define OTGFS_GCCFG_VBDEN (1 << 21) /* Bit 21: USB VBUS detection enable */ + /* Bits 22:31 Reserved, must be kept at reset value */ +/* Core ID register (32-bit product ID) */ + +/* Host periodic transmit FIFO size register */ + +#define OTGFS_HPTXFSIZ_PTXSA_SHIFT (0) /* Bits 0-15: Host periodic TxFIFO start address */ +#define OTGFS_HPTXFSIZ_PTXSA_MASK (0xffff << OTGFS_HPTXFSIZ_PTXSA_SHIFT) +#define OTGFS_HPTXFSIZ_PTXFD_SHIFT (16) /* Bits 16-31: Host periodic TxFIFO depth */ +#define OTGFS_HPTXFSIZ_PTXFD_MASK (0xffff << OTGFS_HPTXFSIZ_PTXFD_SHIFT) + +/* Device IN endpoint transmit FIFOn size register */ + +#define OTGFS_DIEPTXF_INEPTXSA_SHIFT (0) /* Bits 0-15: IN endpoint FIFOx transmit RAM start address */ +#define OTGFS_DIEPTXF_INEPTXSA_MASK (0xffff << OTGFS_DIEPTXF_INEPTXSA_SHIFT) +#define OTGFS_DIEPTXF_INEPTXFD_SHIFT (16) /* Bits 16-31: IN endpoint TxFIFO depth */ +#define OTGFS_DIEPTXF_INEPTXFD_MASK (0xffff << OTGFS_DIEPTXF_INEPTXFD_SHIFT) +# define OTGFS_DIEPTXF_INEPTXFD_MIN (16 << OTGFS_DIEPTXF_INEPTXFD_MASK) + +/* Host-mode control and status registers */ + +/* Host configuration register */ + +#define OTGFS_HCFG_FSLSPCS_SHIFT (0) /* Bits 0-1: FS/LS PHY clock select */ +#define OTGFS_HCFG_FSLSPCS_MASK (3 << OTGFS_HCFG_FSLSPCS_SHIFT) +# define OTGFS_HCFG_FSLSPCS_FS48MHz (1 << OTGFS_HCFG_FSLSPCS_SHIFT) /* FS host mode, PHY clock is running at 48 MHz */ +# define OTGFS_HCFG_FSLSPCS_LS48MHz (1 << OTGFS_HCFG_FSLSPCS_SHIFT) /* LS host mode, Select 48 MHz PHY clock frequency */ +# define OTGFS_HCFG_FSLSPCS_LS6MHz (2 << OTGFS_HCFG_FSLSPCS_SHIFT) /* LS host mode, Select 6 MHz PHY clock frequency */ +#define OTGFS_HCFG_FSLSS (1 << 2) /* Bit 2: FS- and LS-only support */ + /* Bits 31:3 Reserved, must be kept at reset value */ +/* Host frame interval register */ + +#define OTGFS_HFIR_MASK (0xffff) + +/* Host frame number/frame time remaining register */ + +#define OTGFS_HFNUM_FRNUM_SHIFT (0) /* Bits 0-15: Frame number */ +#define OTGFS_HFNUM_FRNUM_MASK (0xffff << OTGFS_HFNUM_FRNUM_SHIFT) +#define OTGFS_HFNUM_FTREM_SHIFT (16) /* Bits 16-31: Frame time remaining */ +#define OTGFS_HFNUM_FTREM_MASK (0xffff << OTGFS_HFNUM_FTREM_SHIFT) + +/* Host periodic transmit FIFO/queue status register */ + +#define OTGFS_HPTXSTS_PTXFSAVL_SHIFT (0) /* Bits 0-15: Periodic transmit data FIFO space available */ +#define OTGFS_HPTXSTS_PTXFSAVL_MASK (0xffff << OTGFS_HPTXSTS_PTXFSAVL_SHIFT) +# define OTGFS_HPTXSTS_PTXFSAVL_FULL (0 << OTGFS_HPTXSTS_PTXFSAVL_SHIFT) +#define OTGFS_HPTXSTS_PTXQSAV_SHIFT (16) /* Bits 16-23: Periodic transmit request queue space available */ +#define OTGFS_HPTXSTS_PTXQSAV_MASK (0xff << OTGFS_HPTXSTS_PTXQSAV_SHIFT) +# define OTGFS_HPTXSTS_PTXQSAV_FULL (0 << OTGFS_HPTXSTS_PTXQSAV_SHIFT) +#define OTGFS_HPTXSTS_PTXQTOP_SHIFT (24) /* Bits 24-31: Top of the periodic transmit request queue */ +#define OTGFS_HPTXSTS_PTXQTOP_MASK (0x7f << OTGFS_HPTXSTS_PTXQTOP_SHIFT) +# define OTGFS_HPTXSTS_TERMINATE (1 << 24) /* Bit 24: Terminate (last entry for selected channel/endpoint) */ +# define OTGFS_HPTXSTS_TYPE_SHIFT (25) /* Bits 25-26: Type */ +# define OTGFS_HPTXSTS_TYPE_MASK (3 << OTGFS_HPTXSTS_TYPE_SHIFT) +# define OTGFS_HPTXSTS_TYPE_INOUT (0 << OTGFS_HPTXSTS_TYPE_SHIFT) /* IN/OUT token */ +# define OTGFS_HPTXSTS_TYPE_ZLP (1 << OTGFS_HPTXSTS_TYPE_SHIFT) /* Zero-length transmit packet */ +# define OTGFS_HPTXSTS_TYPE_HALT (3 << OTGFS_HPTXSTS_TYPE_SHIFT) /* Disable channel command */ +# define OTGFS_HPTXSTS_EPNUM_SHIFT (27) /* Bits 27-30: Endpoint number */ +# define OTGFS_HPTXSTS_EPNUM_MASK (15 << OTGFS_HPTXSTS_EPNUM_SHIFT) +# define OTGFS_HPTXSTS_CHNUM_SHIFT (27) /* Bits 27-30: Channel number */ +# define OTGFS_HPTXSTS_CHNUM_MASK (15 << OTGFS_HPTXSTS_CHNUM_SHIFT) +# define OTGFS_HPTXSTS_ODD (1 << 24) /* Bit 31: Send in odd (vs even) frame */ + +/* Host all channels interrupt and all channels interrupt mask registers */ + +#define OTGFS_HAINT(n) (1 << (n)) /* Bits 15:0 HAINTM: Channel interrupt */ + +/* Host port control and status register */ + +#define OTGFS_HPRT_PCSTS (1 << 0) /* Bit 0: Port connect status */ +#define OTGFS_HPRT_PCDET (1 << 1) /* Bit 1: Port connect detected */ +#define OTGFS_HPRT_PENA (1 << 2) /* Bit 2: Port enable */ +#define OTGFS_HPRT_PENCHNG (1 << 3) /* Bit 3: Port enable/disable change */ +#define OTGFS_HPRT_POCA (1 << 4) /* Bit 4: Port overcurrent active */ +#define OTGFS_HPRT_POCCHNG (1 << 5) /* Bit 5: Port overcurrent change */ +#define OTGFS_HPRT_PRES (1 << 6) /* Bit 6: Port resume */ +#define OTGFS_HPRT_PSUSP (1 << 7) /* Bit 7: Port suspend */ +#define OTGFS_HPRT_PRST (1 << 8) /* Bit 8: Port reset */ + /* Bit 9: Reserved, must be kept at reset value */ +#define OTGFS_HPRT_PLSTS_SHIFT (10) /* Bits 10-11: Port line status */ +#define OTGFS_HPRT_PLSTS_MASK (3 << OTGFS_HPRT_PLSTS_SHIFT) +# define OTGFS_HPRT_PLSTS_DP (1 << 10) /* Bit 10: Logic level of OTG_FS_FS_DP */ +# define OTGFS_HPRT_PLSTS_DM (1 << 11) /* Bit 11: Logic level of OTG_FS_FS_DM */ +#define OTGFS_HPRT_PPWR (1 << 12) /* Bit 12: Port power */ +#define OTGFS_HPRT_PTCTL_SHIFT (13) /* Bits 13-16: Port test control */ +#define OTGFS_HPRT_PTCTL_MASK (15 << OTGFS_HPRT_PTCTL_SHIFT) +# define OTGFS_HPRT_PTCTL_DISABLED (0 << OTGFS_HPRT_PTCTL_SHIFT) /* Test mode disabled */ +# define OTGFS_HPRT_PTCTL_J (1 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_J mode */ +# define OTGFS_HPRT_PTCTL_L (2 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_K mode */ +# define OTGFS_HPRT_PTCTL_SE0_NAK (3 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_SE0_NAK mode */ +# define OTGFS_HPRT_PTCTL_PACKET (4 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_Packet mode */ +# define OTGFS_HPRT_PTCTL_FORCE (5 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_Force_Enable */ +#define OTGFS_HPRT_PSPD_SHIFT (17) /* Bits 17-18: Port speed */ +#define OTGFS_HPRT_PSPD_MASK (3 << OTGFS_HPRT_PSPD_SHIFT) +# define OTGFS_HPRT_PSPD_FS (1 << OTGFS_HPRT_PSPD_SHIFT) /* Full speed */ +# define OTGFS_HPRT_PSPD_LS (2 << OTGFS_HPRT_PSPD_SHIFT) /* Low speed */ + /* Bits 19-31: Reserved, must be kept at reset value */ + +/* Host channel-n characteristics register */ + +#define OTGFS_HCCHAR_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */ +#define OTGFS_HCCHAR_MPSIZ_MASK (0x7ff << OTGFS_HCCHAR_MPSIZ_SHIFT) +#define OTGFS_HCCHAR_EPNUM_SHIFT (11) /* Bits 11-14: Endpoint number */ +#define OTGFS_HCCHAR_EPNUM_MASK (15 << OTGFS_HCCHAR_EPNUM_SHIFT) +#define OTGFS_HCCHAR_EPDIR (1 << 15) /* Bit 15: Endpoint direction */ +# define OTGFS_HCCHAR_EPDIR_OUT (0) +# define OTGFS_HCCHAR_EPDIR_IN OTGFS_HCCHAR_EPDIR + /* Bit 16 Reserved, must be kept at reset value */ +#define OTGFS_HCCHAR_LSDEV (1 << 17) /* Bit 17: Low-speed device */ +#define OTGFS_HCCHAR_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_HCCHAR_EPTYP_MASK (3 << OTGFS_HCCHAR_EPTYP_SHIFT) +# define OTGFS_HCCHAR_EPTYP_CTRL (0 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Control */ +# define OTGFS_HCCHAR_EPTYP_ISOC (1 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Isochronous */ +# define OTGFS_HCCHAR_EPTYP_BULK (2 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Bulk */ +# define OTGFS_HCCHAR_EPTYP_INTR (3 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Interrupt */ +#define OTGFS_HCCHAR_MCNT_SHIFT (20) /* Bits 20-21: Multicount */ +#define OTGFS_HCCHAR_MCNT_MASK (3 << OTGFS_HCCHAR_MCNT_SHIFT) +#define OTGFS_HCCHAR_DAD_SHIFT (22) /* Bits 22-28: Device address */ +#define OTGFS_HCCHAR_DAD_MASK (0x7f << OTGFS_HCCHAR_DAD_SHIFT) +#define OTGFS_HCCHAR_ODDFRM (1 << 29) /* Bit 29: Odd frame */ +#define OTGFS_HCCHAR_CHDIS (1 << 30) /* Bit 30: Channel disable */ +#define OTGFS_HCCHAR_CHENA (1 << 31) /* Bit 31: Channel enable */ + +/* Host channel-n interrupt and Host channel-0 interrupt mask registers */ + +#define OTGFS_HCINT_XFRC (1 << 0) /* Bit 0: Transfer completed */ +#define OTGFS_HCINT_CHH (1 << 1) /* Bit 1: Channel halted */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_HCINT_STALL (1 << 3) /* Bit 3: STALL response received interrupt */ +#define OTGFS_HCINT_NAK (1 << 4) /* Bit 4: NAK response received interrupt */ +#define OTGFS_HCINT_ACK (1 << 5) /* Bit 5: ACK response received/transmitted interrupt */ +#define OTGFS_HCINT_NYET (1 << 6) /* Bit 6: Response received interrupt */ +#define OTGFS_HCINT_TXERR (1 << 7) /* Bit 7: Transaction error */ +#define OTGFS_HCINT_BBERR (1 << 8) /* Bit 8: Babble error */ +#define OTGFS_HCINT_FRMOR (1 << 9) /* Bit 9: Frame overrun */ +#define OTGFS_HCINT_DTERR (1 << 10) /* Bit 10: Data toggle error */ + /* Bits 11-31 Reserved, must be kept at reset value */ +/* Host channel-n interrupt register */ + +#define OTGFS_HCTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */ +#define OTGFS_HCTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_HCTSIZ_XFRSIZ_SHIFT) +#define OTGFS_HCTSIZ_PKTCNT_SHIFT (19) /* Bits 19-28: Packet count */ +#define OTGFS_HCTSIZ_PKTCNT_MASK (0x3ff << OTGFS_HCTSIZ_PKTCNT_SHIFT) +#define OTGFS_HCTSIZ_DPID_SHIFT (29) /* Bits 29-30: Data PID */ +#define OTGFS_HCTSIZ_DPID_MASK (3 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_DATA0 (0 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_DATA2 (1 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_DATA1 (2 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_MDATA (3 << OTGFS_HCTSIZ_DPID_SHIFT) /* Non-control */ +# define OTGFS_HCTSIZ_PID_SETUP (3 << OTGFS_HCTSIZ_DPID_SHIFT) /* Control */ + /* Bit 31 Reserved, must be kept at reset value */ +/* Device-mode control and status registers */ + +/* Device configuration register */ + +#define OTGFS_DCFG_DSPD_SHIFT (0) /* Bits 0-1: Device speed */ +#define OTGFS_DCFG_DSPD_MASK (3 << OTGFS_DCFG_DSPD_SHIFT) +# define OTGFS_DCFG_DSPD_FS (3 << OTGFS_DCFG_DSPD_SHIFT) /* Full speed */ +#define OTGFS_DCFG_NZLSOHSK (1 << 2) /* Bit 2: Non-zero-length status OUT handshake */ + /* Bit 3: Reserved, must be kept at reset value */ +#define OTGFS_DCFG_DAD_SHIFT (4) /* Bits 4-10: Device address */ +#define OTGFS_DCFG_DAD_MASK (0x7f << OTGFS_DCFG_DAD_SHIFT) +#define OTGFS_DCFG_PFIVL_SHIFT (11) /* Bits 11-12: Periodic frame interval */ +#define OTGFS_DCFG_PFIVL_MASK (3 << OTGFS_DCFG_PFIVL_SHIFT) +# define OTGFS_DCFG_PFIVL_80PCT (0 << OTGFS_DCFG_PFIVL_SHIFT) /* 80% of the frame interval */ +# define OTGFS_DCFG_PFIVL_85PCT (1 << OTGFS_DCFG_PFIVL_SHIFT) /* 85% of the frame interval */ +# define OTGFS_DCFG_PFIVL_90PCT (2 << OTGFS_DCFG_PFIVL_SHIFT) /* 90% of the frame interval */ +# define OTGFS_DCFG_PFIVL_95PCT (3 << OTGFS_DCFG_PFIVL_SHIFT) /* 95% of the frame interval */ + /* Bits 13-31 Reserved, must be kept at reset value */ +/* Device control register */ + +#define OTGFS_TESTMODE_DISABLED (0) /* Test mode disabled */ +#define OTGFS_TESTMODE_J (1) /* Test_J mode */ +#define OTGFS_TESTMODE_K (2) /* Test_K mode */ +#define OTGFS_TESTMODE_SE0_NAK (3) /* Test_SE0_NAK mode */ +#define OTGFS_TESTMODE_PACKET (4) /* Test_Packet mode */ +#define OTGFS_TESTMODE_FORCE (5) /* Test_Force_Enable */ + +#define OTGFS_DCTL_RWUSIG (1 << 0) /* Bit 0: Remote wakeup signaling */ +#define OTGFS_DCTL_SDIS (1 << 1) /* Bit 1: Soft disconnect */ +#define OTGFS_DCTL_GINSTS (1 << 2) /* Bit 2: Global IN NAK status */ +#define OTGFS_DCTL_GONSTS (1 << 3) /* Bit 3: Global OUT NAK status */ +#define OTGFS_DCTL_TCTL_SHIFT (4) /* Bits 4-6: Test control */ +#define OTGFS_DCTL_TCTL_MASK (7 << OTGFS_DCTL_TCTL_SHIFT) +# define OTGFS_DCTL_TCTL_DISABLED (0 << OTGFS_DCTL_TCTL_SHIFT) /* Test mode disabled */ +# define OTGFS_DCTL_TCTL_J (1 << OTGFS_DCTL_TCTL_SHIFT) /* Test_J mode */ +# define OTGFS_DCTL_TCTL_K (2 << OTGFS_DCTL_TCTL_SHIFT) /* Test_K mode */ +# define OTGFS_DCTL_TCTL_SE0_NAK (3 << OTGFS_DCTL_TCTL_SHIFT) /* Test_SE0_NAK mode */ +# define OTGFS_DCTL_TCTL_PACKET (4 << OTGFS_DCTL_TCTL_SHIFT) /* Test_Packet mode */ +# define OTGFS_DCTL_TCTL_FORCE (5 << OTGFS_DCTL_TCTL_SHIFT) /* Test_Force_Enable */ +#define OTGFS_DCTL_SGINAK (1 << 7) /* Bit 7: Set global IN NAK */ +#define OTGFS_DCTL_CGINAK (1 << 8) /* Bit 8: Clear global IN NAK */ +#define OTGFS_DCTL_SGONAK (1 << 9) /* Bit 9: Set global OUT NAK */ +#define OTGFS_DCTL_CGONAK (1 << 10) /* Bit 10: Clear global OUT NAK */ +#define OTGFS_DCTL_POPRGDNE (1 << 11) /* Bit 11: Power-on programming done */ + /* Bits 12-31: Reserved, must be kept at reset value */ +/* Device status register */ + +#define OTGFS_DSTS_SUSPSTS (1 << 0) /* Bit 0: Suspend status */ +#define OTGFS_DSTS_ENUMSPD_SHIFT (1) /* Bits 1-2: Enumerated speed */ +#define OTGFS_DSTS_ENUMSPD_MASK (3 << OTGFS_DSTS_ENUMSPD_SHIFT) +# define OTGFS_DSTS_ENUMSPD_FS (3 << OTGFS_DSTS_ENUMSPD_MASK) /* Full speed */ + /* Bits 4-7: Reserved, must be kept at reset value */ +#define OTGFS_DSTS_EERR (1 << 3) /* Bit 3: Erratic error */ +#define OTGFS_DSTS_SOFFN_SHIFT (8) /* Bits 8-21: Frame number of the received SOF */ +#define OTGFS_DSTS_SOFFN_MASK (0x3fff << OTGFS_DSTS_SOFFN_SHIFT) +#define OTGFS_DSTS_SOFFN0 (1 << 8) /* Bits 8: Frame number even/odd bit */ +#define OTGFS_DSTS_SOFFN_EVEN 0 +#define OTGFS_DSTS_SOFFN_ODD OTGFS_DSTS_SOFFN0 + /* Bits 22-31: Reserved, must be kept at reset value */ +/* Device IN endpoint common interrupt mask register */ + +#define OTGFS_DIEPMSK_XFRCM (1 << 0) /* Bit 0: Transfer completed interrupt mask */ +#define OTGFS_DIEPMSK_EPDM (1 << 1) /* Bit 1: Endpoint disabled interrupt mask */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DIEPMSK_TOM (1 << 3) /* Bit 3: Timeout condition mask (Non-isochronous endpoints) */ +#define OTGFS_DIEPMSK_ITTXFEMSK (1 << 4) /* Bit 4: IN token received when TxFIFO empty mask */ +#define OTGFS_DIEPMSK_INEPNMM (1 << 5) /* Bit 5: IN token received with EP mismatch mask */ +#define OTGFS_DIEPMSK_INEPNEM (1 << 6) /* Bit 6: IN endpoint NAK effective mask */ + /* Bits 7-31: Reserved, must be kept at reset value */ +/* Device OUT endpoint common interrupt mask register */ + +#define OTGFS_DOEPMSK_XFRCM (1 << 0) /* Bit 0: Transfer completed interrupt mask */ +#define OTGFS_DOEPMSK_EPDM (1 << 1) /* Bit 1: Endpoint disabled interrupt mask */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DOEPMSK_STUPM (1 << 3) /* Bit 3: SETUP phase done mask */ +#define OTGFS_DOEPMSK_OTEPDM (1 << 4) /* Bit 4: OUT token received when endpoint disabled mask */ + /* Bits 5-31: Reserved, must be kept at reset value */ +/* Device all endpoints interrupt and All endpoints interrupt mask registers */ + +#define OTGFS_DAINT_IEP_SHIFT (0) /* Bits 0-15: IN endpoint interrupt bits */ +#define OTGFS_DAINT_IEP_MASK (0xffff << OTGFS_DAINT_IEP_SHIFT) +# define OTGFS_DAINT_IEP(n) (1 << (n)) +#define OTGFS_DAINT_OEP_SHIFT (16) /* Bits 16-31: OUT endpoint interrupt bits */ +#define OTGFS_DAINT_OEP_MASK (0xffff << OTGFS_DAINT_OEP_SHIFT) +# define OTGFS_DAINT_OEP(n) (1 << ((n)+16)) + +/* Device VBUS discharge time register */ + +#define OTGFS_DVBUSDIS_MASK (0xffff) + +/* Device VBUS pulsing time register */ + +#define OTGFS_DVBUSPULSE_MASK (0xfff) + +/* Device IN endpoint FIFO empty interrupt mask register */ + +#define OTGFS_DIEPEMPMSK(n) (1 << (n)) + +/* Device control IN endpoint 0 control register */ + +#define OTGFS_DIEPCTL0_MPSIZ_SHIFT (0) /* Bits 0-1: Maximum packet size */ +#define OTGFS_DIEPCTL0_MPSIZ_MASK (3 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) +# define OTGFS_DIEPCTL0_MPSIZ_64 (0 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 64 bytes */ +# define OTGFS_DIEPCTL0_MPSIZ_32 (1 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 32 bytes */ +# define OTGFS_DIEPCTL0_MPSIZ_16 (2 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 16 bytes */ +# define OTGFS_DIEPCTL0_MPSIZ_8 (3 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 8 bytes */ + /* Bits 2-14: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ + /* Bit 16: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DIEPCTL0_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DIEPCTL0_EPTYP_MASK (3 << OTGFS_DIEPCTL0_EPTYP_SHIFT) +# define OTGFS_DIEPCTL0_EPTYP_CTRL (0 << OTGFS_DIEPCTL0_EPTYP_SHIFT) /* Control (hard-coded) */ + /* Bit 20: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_STALL (1 << 21) /* Bit 21: STALL handshake */ +#define OTGFS_DIEPCTL0_TXFNUM_SHIFT (22) /* Bits 22-25: TxFIFO number */ +#define OTGFS_DIEPCTL0_TXFNUM_MASK (15 << OTGFS_DIEPCTL0_TXFNUM_SHIFT) +#define OTGFS_DIEPCTL0_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DIEPCTL0_SNAK (1 << 27) /* Bit 27: Set NAK */ + /* Bits 28-29: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DIEPCTL0_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device control IN endpoint n control register */ + +#define OTGFS_DIEPCTL_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */ +#define OTGFS_DIEPCTL_MPSIZ_MASK (0x7ff << OTGFS_DIEPCTL_MPSIZ_SHIFT) + /* Bits 11-14: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ +#define OTGFS_DIEPCTL_EONUM (1 << 16) /* Bit 16: Even/odd frame */ +# define OTGFS_DIEPCTL_EVEN (0) +# define OTGFS_DIEPCTL_ODD OTGFS_DIEPCTL_EONUM +# define OTGFS_DIEPCTL_DATA0 (0) +# define OTGFS_DIEPCTL_DATA1 OTGFS_DIEPCTL_EONUM +#define OTGFS_DIEPCTL_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DIEPCTL_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DIEPCTL_EPTYP_MASK (3 << OTGFS_DIEPCTL_EPTYP_SHIFT) +# define OTGFS_DIEPCTL_EPTYP_CTRL (0 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Control */ +# define OTGFS_DIEPCTL_EPTYP_ISOC (1 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Isochronous */ +# define OTGFS_DIEPCTL_EPTYP_BULK (2 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Bulk */ +# define OTGFS_DIEPCTL_EPTYP_INTR (3 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Interrupt */ + /* Bit 20: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL_STALL (1 << 21) /* Bit 21: STALL handshake */ +#define OTGFS_DIEPCTL_TXFNUM_SHIFT (22) /* Bits 22-25: TxFIFO number */ +#define OTGFS_DIEPCTL_TXFNUM_MASK (15 << OTGFS_DIEPCTL_TXFNUM_SHIFT) +#define OTGFS_DIEPCTL_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DIEPCTL_SNAK (1 << 27) /* Bit 27: Set NAK */ +#define OTGFS_DIEPCTL_SD0PID (1 << 28) /* Bit 28: Set DATA0 PID (interrupt/bulk) */ +#define OTGFS_DIEPCTL_SEVNFRM (1 << 28) /* Bit 28: Set even frame (isochronous)) */ +#define OTGFS_DIEPCTL_SODDFRM (1 << 29) /* Bit 29: Set odd frame (isochronous) */ +#define OTGFS_DIEPCTL_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DIEPCTL_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device endpoint-n interrupt register */ + +#define OTGFS_DIEPINT_XFRC (1 << 0) /* Bit 0: Transfer completed interrupt */ +#define OTGFS_DIEPINT_EPDISD (1 << 1) /* Bit 1: Endpoint disabled interrupt */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DIEPINT_TOC (1 << 3) /* Bit 3: Timeout condition */ +#define OTGFS_DIEPINT_ITTXFE (1 << 4) /* Bit 4: IN token received when TxFIFO is empty */ + /* Bit 5: Reserved, must be kept at reset value */ +#define OTGFS_DIEPINT_INEPNE (1 << 6) /* Bit 6: IN endpoint NAK effective */ +#define OTGFS_DIEPINT_TXFE (1 << 7) /* Bit 7: Transmit FIFO empty */ + /* Bits 8-31: Reserved, must be kept at reset value */ +/* Device IN endpoint 0 transfer size register */ + +#define OTGFS_DIEPTSIZ0_XFRSIZ_SHIFT (0) /* Bits 0-6: Transfer size */ +#define OTGFS_DIEPTSIZ0_XFRSIZ_MASK (0x7f << OTGFS_DIEPTSIZ0_XFRSIZ_SHIFT) + /* Bits 7-18: Reserved, must be kept at reset value */ +#define OTGFS_DIEPTSIZ0_PKTCNT_SHIFT (19) /* Bits 19-20: Packet count */ +#define OTGFS_DIEPTSIZ0_PKTCNT_MASK (3 << OTGFS_DIEPTSIZ0_PKTCNT_SHIFT) + /* Bits 21-31: Reserved, must be kept at reset value */ +/* Device IN endpoint n transfer size register */ + +#define OTGFS_DIEPTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */ +#define OTGFS_DIEPTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_DIEPTSIZ_XFRSIZ_SHIFT) +#define OTGFS_DIEPTSIZ_PKTCNT_SHIFT (19) /* Bit 19-28: Packet count */ +#define OTGFS_DIEPTSIZ_PKTCNT_MASK (0x3ff << OTGFS_DIEPTSIZ_PKTCNT_SHIFT) +#define OTGFS_DIEPTSIZ_MCNT_SHIFT (29) /* Bits 29-30: Multi count */ +#define OTGFS_DIEPTSIZ_MCNT_MASK (3 << OTGFS_DIEPTSIZ_MCNT_SHIFT) + /* Bit 31: Reserved, must be kept at reset value */ +/* Device OUT endpoint TxFIFO status register */ + +#define OTGFS_DTXFSTS_MASK (0xffff) + +/* Device OUT endpoint 0 control register */ + +#define OTGFS_DOEPCTL0_MPSIZ_SHIFT (0) /* Bits 0-1: Maximum packet size */ +#define OTGFS_DOEPCTL0_MPSIZ_MASK (3 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) +# define OTGFS_DOEPCTL0_MPSIZ_64 (0 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 64 bytes */ +# define OTGFS_DOEPCTL0_MPSIZ_32 (1 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 32 bytes */ +# define OTGFS_DOEPCTL0_MPSIZ_16 (2 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 16 bytes */ +# define OTGFS_DOEPCTL0_MPSIZ_8 (3 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 8 bytes */ + /* Bits 2-14: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ + /* Bit 16: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DOEPCTL0_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DOEPCTL0_EPTYP_MASK (3 << OTGFS_DOEPCTL0_EPTYP_SHIFT) +# define OTGFS_DOEPCTL0_EPTYP_CTRL (0 << OTGFS_DOEPCTL0_EPTYP_SHIFT) /* Control (hard-coded) */ +#define OTGFS_DOEPCTL0_SNPM (1 << 20) /* Bit 20: Snoop mode */ +#define OTGFS_DOEPCTL0_STALL (1 << 21) /* Bit 21: STALL handshake */ + /* Bits 22-25: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DOEPCTL0_SNAK (1 << 27) /* Bit 27: Set NAK */ + /* Bits 28-29: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DOEPCTL0_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device OUT endpoint n control register */ + +#define OTGFS_DOEPCTL_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */ +#define OTGFS_DOEPCTL_MPSIZ_MASK (0x7ff << OTGFS_DOEPCTL_MPSIZ_SHIFT) + /* Bits 11-14: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ +#define OTGFS_DOEPCTL_DPID (1 << 16) /* Bit 16: Endpoint data PID (interrupt/buld) */ +# define OTGFS_DOEPCTL_DATA0 (0) +# define OTGFS_DOEPCTL_DATA1 OTGFS_DOEPCTL_DPID +#define OTGFS_DOEPCTL_EONUM (1 << 16) /* Bit 16: Even/odd frame (isochronous) */ +# define OTGFS_DOEPCTL_EVEN (0) +# define OTGFS_DOEPCTL_ODD OTGFS_DOEPCTL_EONUM +#define OTGFS_DOEPCTL_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DOEPCTL_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DOEPCTL_EPTYP_MASK (3 << OTGFS_DOEPCTL_EPTYP_SHIFT) +# define OTGFS_DOEPCTL_EPTYP_CTRL (0 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Control */ +# define OTGFS_DOEPCTL_EPTYP_ISOC (1 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Isochronous */ +# define OTGFS_DOEPCTL_EPTYP_BULK (2 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Bulk */ +# define OTGFS_DOEPCTL_EPTYP_INTR (3 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Interrupt */ +#define OTGFS_DOEPCTL_SNPM (1 << 20) /* Bit 20: Snoop mode */ +#define OTGFS_DOEPCTL_STALL (1 << 21) /* Bit 21: STALL handshake */ + /* Bits 22-25: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DOEPCTL_SNAK (1 << 27) /* Bit 27: Set NAK */ +#define OTGFS_DOEPCTL_SD0PID (1 << 28) /* Bit 28: Set DATA0 PID (interrupt/bulk) */ +#define OTGFS_DOEPCTL_SEVNFRM (1 << 28) /* Bit 28: Set even frame (isochronous) */ +#define OTGFS_DOEPCTL_SD1PID (1 << 29) /* Bit 29: Set DATA1 PID (interrupt/bulk) */ +#define OTGFS_DOEPCTL_SODDFRM (1 << 29) /* Bit 29: Set odd frame (isochronous */ +#define OTGFS_DOEPCTL_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DOEPCTL_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device endpoint-n interrupt register */ + +#define OTGFS_DOEPINT_XFRC (1 << 0) /* Bit 0: Transfer completed interrupt */ +#define OTGFS_DOEPINT_EPDISD (1 << 1) /* Bit 1: Endpoint disabled interrupt */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DOEPINT_SETUP (1 << 3) /* Bit 3: SETUP phase done */ +#define OTGFS_DOEPINT_OTEPDIS (1 << 4) /* Bit 4: OUT token received when endpoint disabled */ + /* Bit 5: Reserved, must be kept at reset value */ +#define OTGFS_DOEPINT_B2BSTUP (1 << 6) /* Bit 6: Back-to-back SETUP packets received */ + /* Bits 7-31: Reserved, must be kept at reset value */ +/* Device OUT endpoint-0 transfer size register */ + +#define OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT (0) /* Bits 0-6: Transfer size */ +#define OTGFS_DOEPTSIZ0_XFRSIZ_MASK (0x7f << OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT) + /* Bits 7-18: Reserved, must be kept at reset value */ +#define OTGFS_DOEPTSIZ0_PKTCNT (1 << 19) /* Bit 19 PKTCNT: Packet count */ + /* Bits 20-28: Reserved, must be kept at reset value */ +#define OTGFS_DOEPTSIZ0_STUPCNT_SHIFT (29) /* Bits 29-30: SETUP packet count */ +#define OTGFS_DOEPTSIZ0_STUPCNT_MASK (3 << OTGFS_DOEPTSIZ0_STUPCNT_SHIFT) + /* Bit 31: Reserved, must be kept at reset value */ +/* Device OUT endpoint-n transfer size register */ + +#define OTGFS_DOEPTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */ +#define OTGFS_DOEPTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_DOEPTSIZ_XFRSIZ_SHIFT) +#define OTGFS_DOEPTSIZ_PKTCNT_SHIFT (19) /* Bit 19-28: Packet count */ +#define OTGFS_DOEPTSIZ_PKTCNT_MASK (0x3ff << OTGFS_DOEPTSIZ_PKTCNT_SHIFT) +#define OTGFS_DOEPTSIZ_STUPCNT_SHIFT (29) /* Bits 29-30: SETUP packet count */ +#define OTGFS_DOEPTSIZ_STUPCNT_MASK (3 << OTGFS_DOEPTSIZ_STUPCNT_SHIFT) +#define OTGFS_DOEPTSIZ_RXDPID_SHIFT (29) /* Bits 29-30: Received data PID */ +#define OTGFS_DOEPTSIZ_RXDPID_MASK (3 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_DATA0 (0 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_DATA2 (1 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_DATA1 (2 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_MDATA (3 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) + /* Bit 31: Reserved, must be kept at reset value */ +/* Power and clock gating control register */ + +#define OTGFS_PCGCCTL_STPPCLK (1 << 0) /* Bit 0: Stop PHY clock */ +#define OTGFS_PCGCCTL_GATEHCLK (1 << 1) /* Bit 1: Gate HCLK */ + /* Bits 2-3: Reserved, must be kept at reset value */ +#define OTGFS_PCGCCTL_PHYSUSP (1 << 4) /* Bit 4: PHY Suspended */ + /* Bits 5-31: Reserved, must be kept at reset value */ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32F44XXX_OTGFS_H */ diff --git a/arch/arm/src/stm32/chip/stm32f44xxx_rcc.h b/arch/arm/src/stm32/chip/stm32f44xxx_rcc.h index 9328e62dd8f..61de03cfc7e 100644 --- a/arch/arm/src/stm32/chip/stm32f44xxx_rcc.h +++ b/arch/arm/src/stm32/chip/stm32f44xxx_rcc.h @@ -536,10 +536,10 @@ #define RCC_PLLI2SCFGR_PLLI2SN_SHIFT (6) /* Bits 6-14: PLLI2S N multiplication factor for VCO */ #define RCC_PLLI2SCFGR_PLLI2SN_MASK (0x1ff << RCC_PLLI2SCFGR_PLLI2SN_SHIFT) # define RCC_PLLI2SCFGR_PLLI2SN(n) ((n) << RCC_PLLI2SCFGR_PLLI2SN_SHIFT) - #define RCC_PLLI2SCFGR_PLLI2SP_SHIFT (16) /* Bits 16-17: PLLI2S division factor for SPDIF-Rx clock */ -#define RCC_PLLI2SCFGR_PLLI2SP_MASK (0x1ff << RCC_PLLI2SCFGR_PLLI2SP_SHIFT) -# define RCC_PLLI2SCFGR_PLLI2SP(n) ((n) << RCC_PLLI2SCFGR_PLLI2SP_SHIFT) +#define RCC_PLLI2SCFGR_PLLI2SP_MASK (0x3 << RCC_PLLI2SCFGR_PLLI2SP_SHIFT) + /* Set PLLI2S P to 2,4,6,8 */ +# define RCC_PLLI2SCFGR_PLLI2SP(n) (((((n)-2)/2) << RCC_PLLI2SCFGR_PLLI2SP_SHIFT) & RCC_PLLI2SCFGR_PLLI2SP_MASK) #define RCC_PLLI2SCFGR_PLLI2SQ_SHIFT (24) /* Bits 24-27: PLLI2S division factor for SAI1 clock*/ #define RCC_PLLI2SCFGR_PLLI2SQ_MASK (0xf << RCC_PLLI2SCFGR_PLLI2SQ_SHIFT) @@ -562,7 +562,8 @@ #define RCC_PLLSAICFGR_PLLSAIP_SHIFT (16) /* Bits 16-17: PLLSAI division factor for 48 MHz clock */ #define RCC_PLLSAICFGR_PLLSAIP_MASK (3 << RCC_PLLSAICFGR_PLLSAIP_SHIFT) -# define RCC_PLLSAICFGR_PLLSAIP(n) ((n) << RCC_PLLSAICFGR_PLLSAIP_SHIFT) + /* Set PLLSAI P to 2,4,6,8 */ +# define RCC_PLLSAICFGR_PLLSAIP(n) (((((n)-2)/2) << RCC_PLLSAICFGR_PLLSAIP_SHIFT) & RCC_PLLSAICFGR_PLLSAIP_MASK) #define RCC_PLLSAICFGR_PLLSAIQ_SHIFT (24) /* Bits 24-27: PLLSAI division factor for SAI clock */ #define RCC_PLLSAICFGR_PLLSAIQ_MASK (0x0F << RCC_PLLSAICFGR_PLLSAIQ_SHIFT) diff --git a/arch/arm/src/stm32/chip/stm32fxxxxx_otgfs.h b/arch/arm/src/stm32/chip/stm32fxxxxx_otgfs.h new file mode 100644 index 00000000000..d799b98738a --- /dev/null +++ b/arch/arm/src/stm32/chip/stm32fxxxxx_otgfs.h @@ -0,0 +1,1014 @@ +/**************************************************************************************************** + * arch/arm/src/stm32/chip/stm32fxxxxx_otgfs.h + * + * Copyright (C) 2012, 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_STM32_CHIP_STM32FXXXXX_OTGFS_H +#define __ARCH_ARM_SRC_STM32_CHIP_STM32FXXXXX_OTGFS_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ +/* General definitions */ + +#define OTGFS_EPTYPE_CTRL (0) /* Control */ +#define OTGFS_EPTYPE_ISOC (1) /* Isochronous */ +#define OTGFS_EPTYPE_BULK (2) /* Bulk */ +#define OTGFS_EPTYPE_INTR (3) /* Interrupt */ + +#define OTGFS_PID_DATA0 (0) +#define OTGFS_PID_DATA2 (1) +#define OTGFS_PID_DATA1 (2) +#define OTGFS_PID_MDATA (3) /* Non-control */ +#define OTGFS_PID_SETUP (3) /* Control */ + +/* Register Offsets *********************************************************************************/ +/* Core global control and status registers */ + +#define STM32_OTGFS_GOTGCTL_OFFSET 0x0000 /* Control and status register */ +#define STM32_OTGFS_GOTGINT_OFFSET 0x0004 /* Interrupt register */ +#define STM32_OTGFS_GAHBCFG_OFFSET 0x0008 /* AHB configuration register */ +#define STM32_OTGFS_GUSBCFG_OFFSET 0x000c /* USB configuration register */ +#define STM32_OTGFS_GRSTCTL_OFFSET 0x0010 /* Reset register */ +#define STM32_OTGFS_GINTSTS_OFFSET 0x0014 /* Core interrupt register */ +#define STM32_OTGFS_GINTMSK_OFFSET 0x0018 /* Interrupt mask register */ +#define STM32_OTGFS_GRXSTSR_OFFSET 0x001c /* Receive status debug read/OTG status read register */ +#define STM32_OTGFS_GRXSTSP_OFFSET 0x0020 /* Receive status debug read/OTG status pop register */ +#define STM32_OTGFS_GRXFSIZ_OFFSET 0x0024 /* Receive FIFO size register */ +#define STM32_OTGFS_HNPTXFSIZ_OFFSET 0x0028 /* Host non-periodic transmit FIFO size register */ +#define STM32_OTGFS_DIEPTXF0_OFFSET 0x0028 /* Endpoint 0 Transmit FIFO size */ +#define STM32_OTGFS_HNPTXSTS_OFFSET 0x002c /* Non-periodic transmit FIFO/queue status register */ +#define STM32_OTGFS_GCCFG_OFFSET 0x0038 /* General core configuration register */ +#define STM32_OTGFS_CID_OFFSET 0x003c /* Core ID register */ +#define STM32_OTGFS_HPTXFSIZ_OFFSET 0x0100 /* Host periodic transmit FIFO size register */ + +#define STM32_OTGFS_DIEPTXF_OFFSET(n) (104+(((n)-1) << 2)) +#define STM32_OTGFS_DIEPTXF1_OFFSET 0x0104 /* Device IN endpoint transmit FIFO1 size register */ +#define STM32_OTGFS_DIEPTXF2_OFFSET 0x0108 /* Device IN endpoint transmit FIFO2 size register */ +#define STM32_OTGFS_DIEPTXF3_OFFSET 0x010c /* Device IN endpoint transmit FIFO3 size register */ + +/* Host-mode control and status registers */ + +#define STM32_OTGFS_HCFG_OFFSET 0x0400 /* Host configuration register */ +#define STM32_OTGFS_HFIR_OFFSET 0x0404 /* Host frame interval register */ +#define STM32_OTGFS_HFNUM_OFFSET 0x0408 /* Host frame number/frame time remaining register */ +#define STM32_OTGFS_HPTXSTS_OFFSET 0x0410 /* Host periodic transmit FIFO/queue status register */ +#define STM32_OTGFS_HAINT_OFFSET 0x0414 /* Host all channels interrupt register */ +#define STM32_OTGFS_HAINTMSK_OFFSET 0x0418 /* Host all channels interrupt mask register */ +#define STM32_OTGFS_HPRT_OFFSET 0x0440 /* Host port control and status register */ + +#define STM32_OTGFS_CHAN_OFFSET(n) (0x500 + ((n) << 5) +#define STM32_OTGFS_HCCHAR_CHOFFSET 0x0000 /* Host channel characteristics register */ +#define STM32_OTGFS_HCINT_CHOFFSET 0x0008 /* Host channel interrupt register */ +#define STM32_OTGFS_HCINTMSK_CHOFFSET 0x000c /* Host channel interrupt mask register */ +#define STM32_OTGFS_HCTSIZ_CHOFFSET 0x0010 /* Host channel interrupt register */ + +#define STM32_OTGFS_HCCHAR_OFFSET(n) (0x500 + ((n) << 5)) +#define STM32_OTGFS_HCCHAR0_OFFSET 0x0500 /* Host channel-0 characteristics register */ +#define STM32_OTGFS_HCCHAR1_OFFSET 0x0520 /* Host channel-1 characteristics register */ +#define STM32_OTGFS_HCCHAR2_OFFSET 0x0540 /* Host channel-2 characteristics register */ +#define STM32_OTGFS_HCCHAR3_OFFSET 0x0560 /* Host channel-3 characteristics register */ +#define STM32_OTGFS_HCCHAR4_OFFSET 0x0580 /* Host channel-4 characteristics register */ +#define STM32_OTGFS_HCCHAR5_OFFSET 0x05a0 /* Host channel-5 characteristics register */ +#define STM32_OTGFS_HCCHAR6_OFFSET 0x05c0 /* Host channel-6 characteristics register */ +#define STM32_OTGFS_HCCHAR7_OFFSET 0x05e0 /* Host channel-7 characteristics register */ + +#define STM32_OTGFS_HCINT_OFFSET(n) (0x508 + ((n) << 5)) +#define STM32_OTGFS_HCINT0_OFFSET 0x0508 /* Host channel-0 interrupt register */ +#define STM32_OTGFS_HCINT1_OFFSET 0x0528 /* Host channel-1 interrupt register */ +#define STM32_OTGFS_HCINT2_OFFSET 0x0548 /* Host channel-2 interrupt register */ +#define STM32_OTGFS_HCINT3_OFFSET 0x0568 /* Host channel-3 interrupt register */ +#define STM32_OTGFS_HCINT4_OFFSET 0x0588 /* Host channel-4 interrupt register */ +#define STM32_OTGFS_HCINT5_OFFSET 0x05a8 /* Host channel-5 interrupt register */ +#define STM32_OTGFS_HCINT6_OFFSET 0x05c8 /* Host channel-6 interrupt register */ +#define STM32_OTGFS_HCINT7_OFFSET 0x05e8 /* Host channel-7 interrupt register */ + +#define STM32_OTGFS_HCINTMSK_OFFSET(n) (0x50c + ((n) << 5)) +#define STM32_OTGFS_HCINTMSK0_OFFSET 0x050c /* Host channel-0 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK1_OFFSET 0x052c /* Host channel-1 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK2_OFFSET 0x054c /* Host channel-2 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK3_OFFSET 0x056c /* Host channel-3 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK4_OFFSET 0x058c /* Host channel-4 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK5_OFFSET 0x05ac /* Host channel-5 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK6_OFFSET 0x05cc /* Host channel-6 interrupt mask register */ +#define STM32_OTGFS_HCINTMSK7_OFFSET 0x05ec /* Host channel-7 interrupt mask register */ + +#define STM32_OTGFS_HCTSIZ_OFFSET(n) (0x510 + ((n) << 5)) +#define STM32_OTGFS_HCTSIZ0_OFFSET 0x0510 /* Host channel-0 interrupt register */ +#define STM32_OTGFS_HCTSIZ1_OFFSET 0x0530 /* Host channel-1 interrupt register */ +#define STM32_OTGFS_HCTSIZ2_OFFSET 0x0550 /* Host channel-2 interrupt register */ +#define STM32_OTGFS_HCTSIZ3_OFFSET 0x0570 /* Host channel-3 interrupt register */ +#define STM32_OTGFS_HCTSIZ4_OFFSET 0x0590 /* Host channel-4 interrupt register */ +#define STM32_OTGFS_HCTSIZ5_OFFSET 0x05b0 /* Host channel-5 interrupt register */ +#define STM32_OTGFS_HCTSIZ6_OFFSET 0x05d0 /* Host channel-6 interrupt register */ +#define STM32_OTGFS_HCTSIZ7_OFFSET 0x05f0 /* Host channel-7 interrupt register */ + +/* Device-mode control and status registers */ + +#define STM32_OTGFS_DCFG_OFFSET 0x0800 /* Device configuration register */ +#define STM32_OTGFS_DCTL_OFFSET 0x0804 /* Device control register */ +#define STM32_OTGFS_DSTS_OFFSET 0x0808 /* Device status register */ +#define STM32_OTGFS_DIEPMSK_OFFSET 0x0810 /* Device IN endpoint common interrupt mask register */ +#define STM32_OTGFS_DOEPMSK_OFFSET 0x0814 /* Device OUT endpoint common interrupt mask register */ +#define STM32_OTGFS_DAINT_OFFSET 0x0818 /* Device all endpoints interrupt register */ +#define STM32_OTGFS_DAINTMSK_OFFSET 0x081c /* All endpoints interrupt mask register */ +#define STM32_OTGFS_DVBUSDIS_OFFSET 0x0828 /* Device VBUS discharge time register */ +#define STM32_OTGFS_DVBUSPULSE_OFFSET 0x082c /* Device VBUS pulsing time register */ +#define STM32_OTGFS_DIEPEMPMSK_OFFSET 0x0834 /* Device IN endpoint FIFO empty interrupt mask register */ + +#define STM32_OTGFS_DIEP_OFFSET(n) (0x0900 + ((n) << 5)) +#define STM32_OTGFS_DIEPCTL_EPOFFSET 0x0000 /* Device endpoint control register */ +#define STM32_OTGFS_DIEPINT_EPOFFSET 0x0008 /* Device endpoint interrupt register */ +#define STM32_OTGFS_DIEPTSIZ_EPOFFSET 0x0010 /* Device IN endpoint transfer size register */ +#define STM32_OTGFS_DTXFSTS_EPOFFSET 0x0018 /* Device IN endpoint transmit FIFO status register */ + +#define STM32_OTGFS_DIEPCTL_OFFSET(n) (0x0900 + ((n) << 5)) +#define STM32_OTGFS_DIEPCTL0_OFFSET 0x0900 /* Device control IN endpoint 0 control register */ +#define STM32_OTGFS_DIEPCTL1_OFFSET 0x0920 /* Device control IN endpoint 2 control register */ +#define STM32_OTGFS_DIEPCTL2_OFFSET 0x0940 /* Device control IN endpoint 3 control register */ +#define STM32_OTGFS_DIEPCTL3_OFFSET 0x0960 /* Device control IN endpoint 4 control register */ + +#define STM32_OTGFS_DIEPINT_OFFSET(n) (0x0908 + ((n) << 5)) +#define STM32_OTGFS_DIEPINT0_OFFSET 0x0908 /* Device endpoint-0 interrupt register */ +#define STM32_OTGFS_DIEPINT1_OFFSET 0x0928 /* Device endpoint-1 interrupt register */ +#define STM32_OTGFS_DIEPINT2_OFFSET 0x0948 /* Device endpoint-2 interrupt register */ +#define STM32_OTGFS_DIEPINT3_OFFSET 0x0968 /* Device endpoint-3 interrupt register */ + +#define STM32_OTGFS_DIEPTSIZ_OFFSET(n) (0x910 + ((n) << 5)) +#define STM32_OTGFS_DIEPTSIZ0_OFFSET 0x0910 /* Device IN endpoint 0 transfer size register */ +#define STM32_OTGFS_DIEPTSIZ1_OFFSET 0x0930 /* Device IN endpoint 1 transfer size register */ +#define STM32_OTGFS_DIEPTSIZ2_OFFSET 0x0950 /* Device IN endpoint 2 transfer size register */ +#define STM32_OTGFS_DIEPTSIZ3_OFFSET 0x0970 /* Device IN endpoint 3 transfer size register */ + +#define STM32_OTGFS_DTXFSTS_OFFSET(n) (0x0918 + ((n) << 5)) +#define STM32_OTGFS_DTXFSTS0_OFFSET 0x0918 /* Device OUT endpoint-0 TxFIFO status register */ +#define STM32_OTGFS_DTXFSTS1_OFFSET 0x0938 /* Device OUT endpoint-1 TxFIFO status register */ +#define STM32_OTGFS_DTXFSTS2_OFFSET 0x0958 /* Device OUT endpoint-2 TxFIFO status register */ +#define STM32_OTGFS_DTXFSTS3_OFFSET 0x0978 /* Device OUT endpoint-3 TxFIFO status register */ + +#define STM32_OTGFS_DOEP_OFFSET(n) (0x0b00 + ((n) << 5)) +#define STM32_OTGFS_DOEPCTL_EPOFFSET 0x0000 /* Device control OUT endpoint 0 control register */ +#define STM32_OTGFS_DOEPINT_EPOFFSET 0x0008 /* Device endpoint-x interrupt register */ + +#define STM32_OTGFS_DOEPCTL_OFFSET(n) (0x0b00 + ((n) << 5)) +#define STM32_OTGFS_DOEPCTL0_OFFSET 0x00b00 /* Device OUT endpoint 0 control register */ +#define STM32_OTGFS_DOEPCTL1_OFFSET 0x00b20 /* Device OUT endpoint 1 control register */ +#define STM32_OTGFS_DOEPCTL2_OFFSET 0x00b40 /* Device OUT endpoint 2 control register */ +#define STM32_OTGFS_DOEPCTL3_OFFSET 0x00b60 /* Device OUT endpoint 3 control register */ + +#define STM32_OTGFS_DOEPINT_OFFSET(n) (0x0b08 + ((n) << 5)) +#define STM32_OTGFS_DOEPINT0_OFFSET 0x00b08 /* Device endpoint-0 interrupt register */ +#define STM32_OTGFS_DOEPINT1_OFFSET 0x00b28 /* Device endpoint-1 interrupt register */ +#define STM32_OTGFS_DOEPINT2_OFFSET 0x00b48 /* Device endpoint-2 interrupt register */ +#define STM32_OTGFS_DOEPINT3_OFFSET 0x00b68 /* Device endpoint-3 interrupt register */ + +#define STM32_OTGFS_DOEPTSIZ_OFFSET(n) (0x0b10 + ((n) << 5)) +#define STM32_OTGFS_DOEPTSIZ0_OFFSET 0x00b10 /* Device OUT endpoint-0 transfer size register */ +#define STM32_OTGFS_DOEPTSIZ1_OFFSET 0x00b30 /* Device OUT endpoint-1 transfer size register */ +#define STM32_OTGFS_DOEPTSIZ2_OFFSET 0x00b50 /* Device OUT endpoint-2 transfer size register */ +#define STM32_OTGFS_DOEPTSIZ3_OFFSET 0x00b70 /* Device OUT endpoint-3 transfer size register */ + +/* Power and clock gating registers */ + +#define STM32_OTGFS_PCGCCTL_OFFSET 0x0e00 /* Power and clock gating control register */ + +/* Data FIFO (DFIFO) access registers */ + +#define STM32_OTGFS_DFIFO_DEP_OFFSET(n) (0x1000 + ((n) << 12)) +#define STM32_OTGFS_DFIFO_HCH_OFFSET(n) (0x1000 + ((n) << 12)) + +#define STM32_OTGFS_DFIFO_DEP0_OFFSET 0x1000 /* 0x1000-0x1ffc Device IN/OUT Endpoint 0 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH0_OFFSET 0x1000 /* 0x1000-0x1ffc Host OUT/IN Channel 0 DFIFO Read/Write Access */ + +#define STM32_OTGFS_DFIFO_DEP1_OFFSET 0x2000 /* 0x2000-0x2ffc Device IN/OUT Endpoint 1 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH1_OFFSET 0x2000 /* 0x2000-0x2ffc Host OUT/IN Channel 1 DFIFO Read/Write Access */ + +#define STM32_OTGFS_DFIFO_DEP2_OFFSET 0x3000 /* 0x3000-0x3ffc Device IN/OUT Endpoint 2 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH2_OFFSET 0x3000 /* 0x3000-0x3ffc Host OUT/IN Channel 2 DFIFO Read/Write Access */ + +#define STM32_OTGFS_DFIFO_DEP3_OFFSET 0x4000 /* 0x4000-0x4ffc Device IN/OUT Endpoint 3 DFIFO Write/Read Access */ +#define STM32_OTGFS_DFIFO_HCH3_OFFSET 0x4000 /* 0x4000-0x4ffc Host OUT/IN Channel 3 DFIFO Read/Write Access */ + +/* Register Addresses *******************************************************************************/ + +#define STM32_OTGFS_GOTGCTL (STM32_OTGFS_BASE+STM32_OTGFS_GOTGCTL_OFFSET) +#define STM32_OTGFS_GOTGINT (STM32_OTGFS_BASE+STM32_OTGFS_GOTGINT_OFFSET) +#define STM32_OTGFS_GAHBCFG (STM32_OTGFS_BASE+STM32_OTGFS_GAHBCFG_OFFSET) +#define STM32_OTGFS_GUSBCFG (STM32_OTGFS_BASE+STM32_OTGFS_GUSBCFG_OFFSET) +#define STM32_OTGFS_GRSTCTL (STM32_OTGFS_BASE+STM32_OTGFS_GRSTCTL_OFFSET) +#define STM32_OTGFS_GINTSTS (STM32_OTGFS_BASE+STM32_OTGFS_GINTSTS_OFFSET) +#define STM32_OTGFS_GINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_GINTMSK_OFFSET) +#define STM32_OTGFS_GRXSTSR (STM32_OTGFS_BASE+STM32_OTGFS_GRXSTSR_OFFSET) +#define STM32_OTGFS_GRXSTSP (STM32_OTGFS_BASE+STM32_OTGFS_GRXSTSP_OFFSET) +#define STM32_OTGFS_GRXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_GRXFSIZ_OFFSET) +#define STM32_OTGFS_HNPTXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_HNPTXFSIZ_OFFSET) +#define STM32_OTGFS_DIEPTXF0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF0_OFFSET) +#define STM32_OTGFS_HNPTXSTS (STM32_OTGFS_BASE+STM32_OTGFS_HNPTXSTS_OFFSET) +#define STM32_OTGFS_GCCFG (STM32_OTGFS_BASE+STM32_OTGFS_GCCFG_OFFSET) +#define STM32_OTGFS_CID (STM32_OTGFS_BASE+STM32_OTGFS_CID_OFFSET) +#define STM32_OTGFS_HPTXFSIZ (STM32_OTGFS_BASE+STM32_OTGFS_HPTXFSIZ_OFFSET) + +#define STM32_OTGFS_DIEPTXF(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF_OFFSET(n)) +#define STM32_OTGFS_DIEPTXF1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF1_OFFSET) +#define STM32_OTGFS_DIEPTXF2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF2_OFFSET) +#define STM32_OTGFS_DIEPTXF3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTXF3_OFFSET) + +/* Host-mode control and status registers */ + +#define STM32_OTGFS_HCFG (STM32_OTGFS_BASE+STM32_OTGFS_HCFG_OFFSET) +#define STM32_OTGFS_HFIR (STM32_OTGFS_BASE+STM32_OTGFS_HFIR_OFFSET) +#define STM32_OTGFS_HFNUM (STM32_OTGFS_BASE+STM32_OTGFS_HFNUM_OFFSET) +#define STM32_OTGFS_HPTXSTS (STM32_OTGFS_BASE+STM32_OTGFS_HPTXSTS_OFFSET) +#define STM32_OTGFS_HAINT (STM32_OTGFS_BASE+STM32_OTGFS_HAINT_OFFSET) +#define STM32_OTGFS_HAINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_HAINTMSK_OFFSET) +#define STM32_OTGFS_HPRT (STM32_OTGFS_BASE+STM32_OTGFS_HPRT_OFFSET) + +#define STM32_OTGFS_CHAN(n) (STM32_OTGFS_BASE+STM32_OTGFS_CHAN_OFFSET(n)) + +#define STM32_OTGFS_HCCHAR(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR_OFFSET(n)) +#define STM32_OTGFS_HCCHAR0 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR0_OFFSET) +#define STM32_OTGFS_HCCHAR1 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR1_OFFSET) +#define STM32_OTGFS_HCCHAR2 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR2_OFFSET) +#define STM32_OTGFS_HCCHAR3 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR3_OFFSET) +#define STM32_OTGFS_HCCHAR4 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR4_OFFSET) +#define STM32_OTGFS_HCCHAR5 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR5_OFFSET) +#define STM32_OTGFS_HCCHAR6 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR6_OFFSET) +#define STM32_OTGFS_HCCHAR7 (STM32_OTGFS_BASE+STM32_OTGFS_HCCHAR7_OFFSET) + +#define STM32_OTGFS_HCINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCINT_OFFSET(n)) +#define STM32_OTGFS_HCINT0 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT0_OFFSET) +#define STM32_OTGFS_HCINT1 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT1_OFFSET) +#define STM32_OTGFS_HCINT2 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT2_OFFSET) +#define STM32_OTGFS_HCINT3 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT3_OFFSET) +#define STM32_OTGFS_HCINT4 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT4_OFFSET) +#define STM32_OTGFS_HCINT5 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT5_OFFSET) +#define STM32_OTGFS_HCINT6 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT6_OFFSET) +#define STM32_OTGFS_HCINT7 (STM32_OTGFS_BASE+STM32_OTGFS_HCINT7_OFFSET) + +#define STM32_OTGFS_HCINTMSK(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK_OFFSET(n)) +#define STM32_OTGFS_HCINTMSK0 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK0_OFFSET) +#define STM32_OTGFS_HCINTMSK1 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK1_OFFSET) +#define STM32_OTGFS_HCINTMSK2 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK2_OFFSET) +#define STM32_OTGFS_HCINTMSK3 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK3_OFFSET) +#define STM32_OTGFS_HCINTMSK4 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK4_OFFSET) +#define STM32_OTGFS_HCINTMSK5 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK5_OFFSET) +#define STM32_OTGFS_HCINTMSK6 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK6_OFFSET) +#define STM32_OTGFS_HCINTMSK7 (STM32_OTGFS_BASE+STM32_OTGFS_HCINTMSK7_OFFSET)_ + +#define STM32_OTGFS_HCTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ_OFFSET(n)) +#define STM32_OTGFS_HCTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ0_OFFSET) +#define STM32_OTGFS_HCTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ1_OFFSET) +#define STM32_OTGFS_HCTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ2_OFFSET) +#define STM32_OTGFS_HCTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ3_OFFSET) +#define STM32_OTGFS_HCTSIZ4 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ4_OFFSET) +#define STM32_OTGFS_HCTSIZ5 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ5_OFFSET) +#define STM32_OTGFS_HCTSIZ6 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ6_OFFSET) +#define STM32_OTGFS_HCTSIZ7 (STM32_OTGFS_BASE+STM32_OTGFS_HCTSIZ7_OFFSET) + +/* Device-mode control and status registers */ + +#define STM32_OTGFS_DCFG (STM32_OTGFS_BASE+STM32_OTGFS_DCFG_OFFSET) +#define STM32_OTGFS_DCTL (STM32_OTGFS_BASE+STM32_OTGFS_DCTL_OFFSET) +#define STM32_OTGFS_DSTS (STM32_OTGFS_BASE+STM32_OTGFS_DSTS_OFFSET) +#define STM32_OTGFS_DIEPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DIEPMSK_OFFSET) +#define STM32_OTGFS_DOEPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DOEPMSK_OFFSET) +#define STM32_OTGFS_DAINT (STM32_OTGFS_BASE+STM32_OTGFS_DAINT_OFFSET) +#define STM32_OTGFS_DAINTMSK (STM32_OTGFS_BASE+STM32_OTGFS_DAINTMSK_OFFSET) +#define STM32_OTGFS_DVBUSDIS (STM32_OTGFS_BASE+STM32_OTGFS_DVBUSDIS_OFFSET) +#define STM32_OTGFS_DVBUSPULSE (STM32_OTGFS_BASE+STM32_OTGFS_DVBUSPULSE_OFFSET) +#define STM32_OTGFS_DIEPEMPMSK (STM32_OTGFS_BASE+STM32_OTGFS_DIEPEMPMSK_OFFSET) + +#define STM32_OTGFS_DIEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEP_OFFSET(n)) + +#define STM32_OTGFS_DIEPCTL(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL_OFFSET(n)) +#define STM32_OTGFS_DIEPCTL0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL0_OFFSET) +#define STM32_OTGFS_DIEPCTL1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL1_OFFSET) +#define STM32_OTGFS_DIEPCTL2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL2_OFFSET) +#define STM32_OTGFS_DIEPCTL3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPCTL3_OFFSET) + +#define STM32_OTGFS_DIEPINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT_OFFSET(n)) +#define STM32_OTGFS_DIEPINT0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT0_OFFSET) +#define STM32_OTGFS_DIEPINT1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT1_OFFSET) +#define STM32_OTGFS_DIEPINT2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT2_OFFSET) +#define STM32_OTGFS_DIEPINT3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPINT3_OFFSET) + +#define STM32_OTGFS_DIEPTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ_OFFSET(n)) +#define STM32_OTGFS_DIEPTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ0_OFFSET) +#define STM32_OTGFS_DIEPTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ1_OFFSET) +#define STM32_OTGFS_DIEPTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ2_OFFSET) +#define STM32_OTGFS_DIEPTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_DIEPTSIZ3_OFFSET) + +#define STM32_OTGFS_DTXFSTS(n) (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS_OFFSET(n)) +#define STM32_OTGFS_DTXFSTS0 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS0_OFFSET) +#define STM32_OTGFS_DTXFSTS1 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS1_OFFSET) +#define STM32_OTGFS_DTXFSTS2 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS2_OFFSET) +#define STM32_OTGFS_DTXFSTS3 (STM32_OTGFS_BASE+STM32_OTGFS_DTXFSTS3_OFFSET) + +#define STM32_OTGFS_DOEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEP_OFFSET(n)) + +#define STM32_OTGFS_DOEPCTL(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL_OFFSET(n)) +#define STM32_OTGFS_DOEPCTL0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL0_OFFSET) +#define STM32_OTGFS_DOEPCTL1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL1_OFFSET) +#define STM32_OTGFS_DOEPCTL2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL2_OFFSET) +#define STM32_OTGFS_DOEPCTL3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPCTL3_OFFSET) + +#define STM32_OTGFS_DOEPINT(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT_OFFSET(n)) +#define STM32_OTGFS_DOEPINT0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT0_OFFSET) +#define STM32_OTGFS_DOEPINT1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT1_OFFSET) +#define STM32_OTGFS_DOEPINT2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT2_OFFSET) +#define STM32_OTGFS_DOEPINT3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPINT3_OFFSET) + +#define STM32_OTGFS_DOEPTSIZ(n) (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ_OFFSET(n)) +#define STM32_OTGFS_DOEPTSIZ0 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ0_OFFSET) +#define STM32_OTGFS_DOEPTSIZ1 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ1_OFFSET) +#define STM32_OTGFS_DOEPTSIZ2 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ2_OFFSET) +#define STM32_OTGFS_DOEPTSIZ3 (STM32_OTGFS_BASE+STM32_OTGFS_DOEPTSIZ3_OFFSET) + +/* Power and clock gating registers */ + +#define STM32_OTGFS_PCGCCTL (STM32_OTGFS_BASE+STM32_OTGFS_PCGCCTL_OFFSET) + +/* Data FIFO (DFIFO) access registers */ + +#define STM32_OTGFS_DFIFO_DEP(n) (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP_OFFSET(n)) +#define STM32_OTGFS_DFIFO_HCH(n) (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH_OFFSET(n)) + +#define STM32_OTGFS_DFIFO_DEP0 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP0_OFFSET) +#define STM32_OTGFS_DFIFO_HCH0 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH0_OFFSET) + +#define STM32_OTGFS_DFIFO_DEP1 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP1_OFFSET) +#define STM32_OTGFS_DFIFO_HCH1 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH1_OFFSET) + +#define STM32_OTGFS_DFIFO_DEP2 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP2_OFFSET) +#define STM32_OTGFS_DFIFO_HCH2 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH2_OFFSET) + +#define STM32_OTGFS_DFIFO_DEP3 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_DEP3_OFFSET) +#define STM32_OTGFS_DFIFO_HCH3 (STM32_OTGFS_BASE+STM32_OTGFS_DFIFO_HCH3_OFFSET) + +/* Register Bitfield Definitions ********************************************************************/ +/* Core global control and status registers */ + +/* Control and status register */ + +#define OTGFS_GOTGCTL_SRQSCS (1 << 0) /* Bit 0: Session request success */ +#define OTGFS_GOTGCTL_SRQ (1 << 1) /* Bit 1: Session request */ + /* Bits 2-7 Reserved, must be kept at reset value */ +#define OTGFS_GOTGCTL_HNGSCS (1 << 8) /* Bit 8: Host negotiation success */ +#define OTGFS_GOTGCTL_HNPRQ (1 << 9) /* Bit 9: HNP request */ +#define OTGFS_GOTGCTL_HSHNPEN (1 << 10) /* Bit 10: host set HNP enable */ +#define OTGFS_GOTGCTL_DHNPEN (1 << 11) /* Bit 11: Device HNP enabled */ + /* Bits 12-15: Reserved, must be kept at reset value */ +#define OTGFS_GOTGCTL_CIDSTS (1 << 16) /* Bit 16: Connector ID status */ +#define OTGFS_GOTGCTL_DBCT (1 << 17) /* Bit 17: Long/short debounce time */ +#define OTGFS_GOTGCTL_ASVLD (1 << 18) /* Bit 18: A-session valid */ +#define OTGFS_GOTGCTL_BSVLD (1 << 19) /* Bit 19: B-session valid */ + /* Bits 20-31: Reserved, must be kept at reset value */ +/* Interrupt register */ + /* Bits 1:0 Reserved, must be kept at reset value */ +#define OTGFS_GOTGINT_SEDET (1 << 2) /* Bit 2: Session end detected */ + /* Bits 3-7: Reserved, must be kept at reset value */ +#define OTGFS_GOTGINT_SRSSCHG (1 << 8) /* Bit 8: Session request success status change */ +#define OTGFS_GOTGINT_HNSSCHG (1 << 9) /* Bit 9: Host negotiation success status change */ + /* Bits 16:10 Reserved, must be kept at reset value */ +#define OTGFS_GOTGINT_HNGDET (1 << 17) /* Bit 17: Host negotiation detected */ +#define OTGFS_GOTGINT_ADTOCHG (1 << 18) /* Bit 18: A-device timeout change */ +#define OTGFS_GOTGINT_DBCDNE (1 << 19) /* Bit 19: Debounce done */ + /* Bits 20-31: Reserved, must be kept at reset value */ + +/* AHB configuration register */ + +#define OTGFS_GAHBCFG_GINTMSK (1 << 0) /* Bit 0: Global interrupt mask */ + /* Bits 1-6: Reserved, must be kept at reset value */ +#define OTGFS_GAHBCFG_TXFELVL (1 << 7) /* Bit 7: TxFIFO empty level */ +#define OTGFS_GAHBCFG_PTXFELVL (1 << 8) /* Bit 8: Periodic TxFIFO empty level */ + /* Bits 20-31: Reserved, must be kept at reset value */ +/* USB configuration register */ + +#define OTGFS_GUSBCFG_TOCAL_SHIFT (0) /* Bits 0-2: FS timeout calibration */ +#define OTGFS_GUSBCFG_TOCAL_MASK (7 << OTGFS_GUSBCFG_TOCAL_SHIFT) + /* Bits 3-5: Reserved, must be kept at reset value */ +#define OTGFS_GUSBCFG_PHYSEL (1 << 6) /* Bit 6: Full Speed serial transceiver select */ + /* Bit 7: Reserved, must be kept at reset value */ +#define OTGFS_GUSBCFG_SRPCAP (1 << 8) /* Bit 8: SRP-capable */ +#define OTGFS_GUSBCFG_HNPCAP (1 << 9) /* Bit 9: HNP-capable */ +#define OTGFS_GUSBCFG_TRDT_SHIFT (10) /* Bits 10-13: USB turnaround time */ +#define OTGFS_GUSBCFG_TRDT_MASK (15 << OTGFS_GUSBCFG_TRDT_SHIFT) +# define OTGFS_GUSBCFG_TRDT(n) ((n) << OTGFS_GUSBCFG_TRDT_SHIFT) + /* Bits 14-28: Reserved, must be kept at reset value */ +#define OTGFS_GUSBCFG_FHMOD (1 << 29) /* Bit 29: Force host mode */ +#define OTGFS_GUSBCFG_FDMOD (1 << 30) /* Bit 30: Force device mode */ +#define OTGFS_GUSBCFG_CTXPKT (1 << 31) /* Bit 31: Corrupt Tx packet */ + /* Bits 20-31: Reserved, must be kept at reset value */ +/* Reset register */ + +#define OTGFS_GRSTCTL_CSRST (1 << 0) /* Bit 0: Core soft reset */ +#define OTGFS_GRSTCTL_HSRST (1 << 1) /* Bit 1: HCLK soft reset */ +#define OTGFS_GRSTCTL_FCRST (1 << 2) /* Bit 2: Host frame counter reset */ + /* Bit 3 Reserved, must be kept at reset value */ +#define OTGFS_GRSTCTL_RXFFLSH (1 << 4) /* Bit 4: RxFIFO flush */ +#define OTGFS_GRSTCTL_TXFFLSH (1 << 5) /* Bit 5: TxFIFO flush */ +#define OTGFS_GRSTCTL_TXFNUM_SHIFT (6) /* Bits 6-10: TxFIFO number */ +#define OTGFS_GRSTCTL_TXFNUM_MASK (31 << OTGFS_GRSTCTL_TXFNUM_SHIFT) +# define OTGFS_GRSTCTL_TXFNUM_HNONPER (0 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Non-periodic TxFIFO flush in host mode */ +# define OTGFS_GRSTCTL_TXFNUM_HPER (1 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Periodic TxFIFO flush in host mode */ +# define OTGFS_GRSTCTL_TXFNUM_HALL (16 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Flush all the transmit FIFOs in host mode.*/ +# define OTGFS_GRSTCTL_TXFNUM_D(n) ((n) << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* TXFIFO n flush in device mode, n=0-15 */ +# define OTGFS_GRSTCTL_TXFNUM_DALL (16 << OTGFS_GRSTCTL_TXFNUM_SHIFT) /* Flush all the transmit FIFOs in device mode.*/ + /* Bits 11-31: Reserved, must be kept at reset value */ +#define OTGFS_GRSTCTL_AHBIDL (1 << 31) /* Bit 31: AHB master idle */ + +/* Core interrupt and Interrupt mask registers */ + +#define OTGFS_GINTSTS_CMOD (1 << 0) /* Bit 0: Current mode of operation */ +# define OTGFS_GINTSTS_DEVMODE (0) +# define OTGFS_GINTSTS_HOSTMODE (OTGFS_GINTSTS_CMOD) +#define OTGFS_GINT_MMIS (1 << 1) /* Bit 1: Mode mismatch interrupt */ +#define OTGFS_GINT_OTG (1 << 2) /* Bit 2: OTG interrupt */ +#define OTGFS_GINT_SOF (1 << 3) /* Bit 3: Start of frame */ +#define OTGFS_GINT_RXFLVL (1 << 4) /* Bit 4: RxFIFO non-empty */ +#define OTGFS_GINT_NPTXFE (1 << 5) /* Bit 5: Non-periodic TxFIFO empty */ +#define OTGFS_GINT_GINAKEFF (1 << 6) /* Bit 6: Global IN non-periodic NAK effective */ +#define OTGFS_GINT_GONAKEFF (1 << 7) /* Bit 7: Global OUT NAK effective */ + /* Bits 8-9: Reserved, must be kept at reset value */ +#define OTGFS_GINT_ESUSP (1 << 10) /* Bit 10: Early suspend */ +#define OTGFS_GINT_USBSUSP (1 << 11) /* Bit 11: USB suspend */ +#define OTGFS_GINT_USBRST (1 << 12) /* Bit 12: USB reset */ +#define OTGFS_GINT_ENUMDNE (1 << 13) /* Bit 13: Enumeration done */ +#define OTGFS_GINT_ISOODRP (1 << 14) /* Bit 14: Isochronous OUT packet dropped interrupt */ +#define OTGFS_GINT_EOPF (1 << 15) /* Bit 15: End of periodic frame interrupt */ + /* Bits 16 Reserved, must be kept at reset value */ +#define OTGFS_GINTMSK_EPMISM (1 << 17) /* Bit 17: Endpoint mismatch interrupt mask */ +#define OTGFS_GINT_IEP (1 << 18) /* Bit 18: IN endpoint interrupt */ +#define OTGFS_GINT_OEP (1 << 19) /* Bit 19: OUT endpoint interrupt */ +#define OTGFS_GINT_IISOIXFR (1 << 20) /* Bit 20: Incomplete isochronous IN transfer */ +#define OTGFS_GINT_IISOOXFR (1 << 21) /* Bit 21: Incomplete isochronous OUT transfer (device) */ +#define OTGFS_GINT_IPXFR (1 << 21) /* Bit 21: Incomplete periodic transfer (host) */ + /* Bits 22-23: Reserved, must be kept at reset value */ +#define OTGFS_GINT_HPRT (1 << 24) /* Bit 24: Host port interrupt */ +#define OTGFS_GINT_HC (1 << 25) /* Bit 25: Host channels interrupt */ +#define OTGFS_GINT_PTXFE (1 << 26) /* Bit 26: Periodic TxFIFO empty */ + /* Bit 27 Reserved, must be kept at reset value */ +#define OTGFS_GINT_CIDSCHG (1 << 28) /* Bit 28: Connector ID status change */ +#define OTGFS_GINT_DISC (1 << 29) /* Bit 29: Disconnect detected interrupt */ +#define OTGFS_GINT_SRQ (1 << 30) /* Bit 30: Session request/new session detected interrupt */ +#define OTGFS_GINT_WKUP (1 << 31) /* Bit 31: Resume/remote wakeup detected interrupt */ + +/* Receive status debug read/OTG status read and pop registers (host mode) */ + +#define OTGFS_GRXSTSH_CHNUM_SHIFT (0) /* Bits 0-3: Channel number */ +#define OTGFS_GRXSTSH_CHNUM_MASK (15 << OTGFS_GRXSTSH_CHNUM_SHIFT) +#define OTGFS_GRXSTSH_BCNT_SHIFT (4) /* Bits 4-14: Byte count */ +#define OTGFS_GRXSTSH_BCNT_MASK (0x7ff << OTGFS_GRXSTSH_BCNT_SHIFT) +#define OTGFS_GRXSTSH_DPID_SHIFT (15) /* Bits 15-16: Data PID */ +#define OTGFS_GRXSTSH_DPID_MASK (3 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_DATA0 (0 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_DATA2 (1 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_DATA1 (2 << OTGFS_GRXSTSH_DPID_SHIFT) +# define OTGFS_GRXSTSH_DPID_MDATA (3 << OTGFS_GRXSTSH_DPID_SHIFT) +#define OTGFS_GRXSTSH_PKTSTS_SHIFT (17) /* Bits 17-20: Packet status */ +#define OTGFS_GRXSTSH_PKTSTS_MASK (15 << OTGFS_GRXSTSH_PKTSTS_SHIFT) +# define OTGFS_GRXSTSH_PKTSTS_INRECVD (2 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* IN data packet received */ +# define OTGFS_GRXSTSH_PKTSTS_INDONE (3 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* IN transfer completed */ +# define OTGFS_GRXSTSH_PKTSTS_DTOGERR (5 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* Data toggle error */ +# define OTGFS_GRXSTSH_PKTSTS_HALTED (7 << OTGFS_GRXSTSH_PKTSTS_SHIFT) /* Channel halted */ + /* Bits 21-31: Reserved, must be kept at reset value */ +/* Receive status debug read/OTG status read and pop registers (device mode) */ + +#define OTGFS_GRXSTSD_EPNUM_SHIFT (0) /* Bits 0-3: Endpoint number */ +#define OTGFS_GRXSTSD_EPNUM_MASK (15 << OTGFS_GRXSTSD_EPNUM_SHIFT) +#define OTGFS_GRXSTSD_BCNT_SHIFT (4) /* Bits 4-14: Byte count */ +#define OTGFS_GRXSTSD_BCNT_MASK (0x7ff << OTGFS_GRXSTSD_BCNT_SHIFT) +#define OTGFS_GRXSTSD_DPID_SHIFT (15) /* Bits 15-16: Data PID */ +#define OTGFS_GRXSTSD_DPID_MASK (3 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_DATA0 (0 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_DATA2 (1 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_DATA1 (2 << OTGFS_GRXSTSD_DPID_SHIFT) +# define OTGFS_GRXSTSD_DPID_MDATA (3 << OTGFS_GRXSTSD_DPID_SHIFT) +#define OTGFS_GRXSTSD_PKTSTS_SHIFT (17) /* Bits 17-20: Packet status */ +#define OTGFS_GRXSTSD_PKTSTS_MASK (15 << OTGFS_GRXSTSD_PKTSTS_SHIFT) +# define OTGFS_GRXSTSD_PKTSTS_OUTNAK (1 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* Global OUT NAK */ +# define OTGFS_GRXSTSD_PKTSTS_OUTRECVD (2 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* OUT data packet received */ +# define OTGFS_GRXSTSD_PKTSTS_OUTDONE (3 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* OUT transfer completed */ +# define OTGFS_GRXSTSD_PKTSTS_SETUPDONE (4 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* SETUP transaction completed */ +# define OTGFS_GRXSTSD_PKTSTS_SETUPRECVD (6 << OTGFS_GRXSTSD_PKTSTS_SHIFT) /* SETUP data packet received */ +#define OTGFS_GRXSTSD_FRMNUM_SHIFT (21) /* Bits 21-24: Frame number */ +#define OTGFS_GRXSTSD_FRMNUM_MASK (15 << OTGFS_GRXSTSD_FRMNUM_SHIFT) + /* Bits 25-31: Reserved, must be kept at reset value */ +/* Receive FIFO size register */ + +#define OTGFS_GRXFSIZ_MASK (0xffff) + +/* Host non-periodic transmit FIFO size register */ + +#define OTGFS_HNPTXFSIZ_NPTXFSA_SHIFT (0) /* Bits 0-15: Non-periodic transmit RAM start address */ +#define OTGFS_HNPTXFSIZ_NPTXFSA_MASK (0xffff << OTGFS_HNPTXFSIZ_NPTXFSA_SHIFT) +#define OTGFS_HNPTXFSIZ_NPTXFD_SHIFT (16) /* Bits 16-31: Non-periodic TxFIFO depth */ +#define OTGFS_HNPTXFSIZ_NPTXFD_MASK (0xffff << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT) +# define OTGFS_HNPTXFSIZ_NPTXFD_MIN (16 << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT) +# define OTGFS_HNPTXFSIZ_NPTXFD_MAX (256 << OTGFS_HNPTXFSIZ_NPTXFD_SHIFT) + +/* Endpoint 0 Transmit FIFO size */ + +#define OTGFS_DIEPTXF0_TX0FD_SHIFT (0) /* Bits 0-15: Endpoint 0 transmit RAM start address */ +#define OTGFS_DIEPTXF0_TX0FD_MASK (0xffff << OTGFS_DIEPTXF0_TX0FD_SHIFT) +#define OTGFS_DIEPTXF0_TX0FSA_SHIFT (16) /* Bits 16-31: Endpoint 0 TxFIFO depth */ +#define OTGFS_DIEPTXF0_TX0FSA_MASK (0xffff << OTGFS_DIEPTXF0_TX0FSA_SHIFT) +# define OTGFS_DIEPTXF0_TX0FSA_MIN (16 << OTGFS_DIEPTXF0_TX0FSA_SHIFT) +# define OTGFS_DIEPTXF0_TX0FSA_MAX (256 << OTGFS_DIEPTXF0_TX0FSA_SHIFT) + +/* Non-periodic transmit FIFO/queue status register */ + +#define OTGFS_HNPTXSTS_NPTXFSAV_SHIFT (0) /* Bits 0-15: Non-periodic TxFIFO space available */ +#define OTGFS_HNPTXSTS_NPTXFSAV_MASK (0xffff << OTGFS_HNPTXSTS_NPTXFSAV_SHIFT) +# define OTGFS_HNPTXSTS_NPTXFSAV_FULL (0 << OTGFS_HNPTXSTS_NPTXFSAV_SHIFT) +#define OTGFS_HNPTXSTS_NPTQXSAV_SHIFT (16) /* Bits 16-23: Non-periodic transmit request queue space available */ +#define OTGFS_HNPTXSTS_NPTQXSAV_MASK (0xff << OTGFS_HNPTXSTS_NPTQXSAV_SHIFT) +# define OTGFS_HNPTXSTS_NPTQXSAV_FULL (0 << OTGFS_HNPTXSTS_NPTQXSAV_SHIFT) +#define OTGFS_HNPTXSTS_NPTXQTOP_SHIFT (24) /* Bits 24-30: Top of the non-periodic transmit request queue */ +#define OTGFS_HNPTXSTS_NPTXQTOP_MASK (0x7f << OTGFS_HNPTXSTS_NPTXQTOP_SHIFT) +# define OTGFS_HNPTXSTS_TERMINATE (1 << 24) /* Bit 24: Terminate (last entry for selected channel/endpoint) */ +# define OTGFS_HNPTXSTS_TYPE_SHIFT (25) /* Bits 25-26: Status */ +# define OTGFS_HNPTXSTS_TYPE_MASK (3 << OTGFS_HNPTXSTS_TYPE_SHIFT) +# define OTGFS_HNPTXSTS_TYPE_INOUT (0 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* IN/OUT token */ +# define OTGFS_HNPTXSTS_TYPE_ZLP (1 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* Zero-length transmit packet (device IN/host OUT) */ +# define OTGFS_HNPTXSTS_TYPE_HALT (3 << OTGFS_HNPTXSTS_TYPE_SHIFT) /* Channel halt command */ +# define OTGFS_HNPTXSTS_CHNUM_SHIFT (27) /* Bits 27-30: Channel number */ +# define OTGFS_HNPTXSTS_CHNUM_MASK (15 << OTGFS_HNPTXSTS_CHNUM_SHIFT) +# define OTGFS_HNPTXSTS_EPNUM_SHIFT (27) /* Bits 27-30: Endpoint number */ +# define OTGFS_HNPTXSTS_EPNUM_MASK (15 << OTGFS_HNPTXSTS_EPNUM_SHIFT) + /* Bit 31 Reserved, must be kept at reset value */ +/* General core configuration register */ + /* Bits 15:0 Reserved, must be kept at reset value */ +#define OTGFS_GCCFG_PWRDWN (1 << 16) /* Bit 16: Power down */ + /* Bit 17 Reserved, must be kept at reset value */ +#define OTGFS_GCCFG_VBUSASEN (1 << 18) /* Bit 18: Enable the VBUS sensing “A” device */ +#define OTGFS_GCCFG_VBUSBSEN (1 << 19) /* Bit 19: Enable the VBUS sensing “B” device */ +#define OTGFS_GCCFG_SOFOUTEN (1 << 20) /* Bit 20: SOF output enable */ +#define OTGFS_GCCFG_NOVBUSSENS (1 << 21) /* Bit 21: VBUS sensing disable option */ + /* Bits 31:22 Reserved, must be kept at reset value */ +/* Core ID register (32-bit product ID) */ + +/* Host periodic transmit FIFO size register */ + +#define OTGFS_HPTXFSIZ_PTXSA_SHIFT (0) /* Bits 0-15: Host periodic TxFIFO start address */ +#define OTGFS_HPTXFSIZ_PTXSA_MASK (0xffff << OTGFS_HPTXFSIZ_PTXSA_SHIFT) +#define OTGFS_HPTXFSIZ_PTXFD_SHIFT (16) /* Bits 16-31: Host periodic TxFIFO depth */ +#define OTGFS_HPTXFSIZ_PTXFD_MASK (0xffff << OTGFS_HPTXFSIZ_PTXFD_SHIFT) + +/* Device IN endpoint transmit FIFOn size register */ + +#define OTGFS_DIEPTXF_INEPTXSA_SHIFT (0) /* Bits 0-15: IN endpoint FIFOx transmit RAM start address */ +#define OTGFS_DIEPTXF_INEPTXSA_MASK (0xffff << OTGFS_DIEPTXF_INEPTXSA_SHIFT) +#define OTGFS_DIEPTXF_INEPTXFD_SHIFT (16) /* Bits 16-31: IN endpoint TxFIFO depth */ +#define OTGFS_DIEPTXF_INEPTXFD_MASK (0xffff << OTGFS_DIEPTXF_INEPTXFD_SHIFT) +# define OTGFS_DIEPTXF_INEPTXFD_MIN (16 << OTGFS_DIEPTXF_INEPTXFD_MASK) + +/* Host-mode control and status registers */ + +/* Host configuration register */ + +#define OTGFS_HCFG_FSLSPCS_SHIFT (0) /* Bits 0-1: FS/LS PHY clock select */ +#define OTGFS_HCFG_FSLSPCS_MASK (3 << OTGFS_HCFG_FSLSPCS_SHIFT) +# define OTGFS_HCFG_FSLSPCS_FS48MHz (1 << OTGFS_HCFG_FSLSPCS_SHIFT) /* FS host mode, PHY clock is running at 48 MHz */ +# define OTGFS_HCFG_FSLSPCS_LS48MHz (1 << OTGFS_HCFG_FSLSPCS_SHIFT) /* LS host mode, Select 48 MHz PHY clock frequency */ +# define OTGFS_HCFG_FSLSPCS_LS6MHz (2 << OTGFS_HCFG_FSLSPCS_SHIFT) /* LS host mode, Select 6 MHz PHY clock frequency */ +#define OTGFS_HCFG_FSLSS (1 << 2) /* Bit 2: FS- and LS-only support */ + /* Bits 31:3 Reserved, must be kept at reset value */ +/* Host frame interval register */ + +#define OTGFS_HFIR_MASK (0xffff) + +/* Host frame number/frame time remaining register */ + +#define OTGFS_HFNUM_FRNUM_SHIFT (0) /* Bits 0-15: Frame number */ +#define OTGFS_HFNUM_FRNUM_MASK (0xffff << OTGFS_HFNUM_FRNUM_SHIFT) +#define OTGFS_HFNUM_FTREM_SHIFT (16) /* Bits 16-31: Frame time remaining */ +#define OTGFS_HFNUM_FTREM_MASK (0xffff << OTGFS_HFNUM_FTREM_SHIFT) + +/* Host periodic transmit FIFO/queue status register */ + +#define OTGFS_HPTXSTS_PTXFSAVL_SHIFT (0) /* Bits 0-15: Periodic transmit data FIFO space available */ +#define OTGFS_HPTXSTS_PTXFSAVL_MASK (0xffff << OTGFS_HPTXSTS_PTXFSAVL_SHIFT) +# define OTGFS_HPTXSTS_PTXFSAVL_FULL (0 << OTGFS_HPTXSTS_PTXFSAVL_SHIFT) +#define OTGFS_HPTXSTS_PTXQSAV_SHIFT (16) /* Bits 16-23: Periodic transmit request queue space available */ +#define OTGFS_HPTXSTS_PTXQSAV_MASK (0xff << OTGFS_HPTXSTS_PTXQSAV_SHIFT) +# define OTGFS_HPTXSTS_PTXQSAV_FULL (0 << OTGFS_HPTXSTS_PTXQSAV_SHIFT) +#define OTGFS_HPTXSTS_PTXQTOP_SHIFT (24) /* Bits 24-31: Top of the periodic transmit request queue */ +#define OTGFS_HPTXSTS_PTXQTOP_MASK (0x7f << OTGFS_HPTXSTS_PTXQTOP_SHIFT) +# define OTGFS_HPTXSTS_TERMINATE (1 << 24) /* Bit 24: Terminate (last entry for selected channel/endpoint) */ +# define OTGFS_HPTXSTS_TYPE_SHIFT (25) /* Bits 25-26: Type */ +# define OTGFS_HPTXSTS_TYPE_MASK (3 << OTGFS_HPTXSTS_TYPE_SHIFT) +# define OTGFS_HPTXSTS_TYPE_INOUT (0 << OTGFS_HPTXSTS_TYPE_SHIFT) /* IN/OUT token */ +# define OTGFS_HPTXSTS_TYPE_ZLP (1 << OTGFS_HPTXSTS_TYPE_SHIFT) /* Zero-length transmit packet */ +# define OTGFS_HPTXSTS_TYPE_HALT (3 << OTGFS_HPTXSTS_TYPE_SHIFT) /* Disable channel command */ +# define OTGFS_HPTXSTS_EPNUM_SHIFT (27) /* Bits 27-30: Endpoint number */ +# define OTGFS_HPTXSTS_EPNUM_MASK (15 << OTGFS_HPTXSTS_EPNUM_SHIFT) +# define OTGFS_HPTXSTS_CHNUM_SHIFT (27) /* Bits 27-30: Channel number */ +# define OTGFS_HPTXSTS_CHNUM_MASK (15 << OTGFS_HPTXSTS_CHNUM_SHIFT) +# define OTGFS_HPTXSTS_ODD (1 << 24) /* Bit 31: Send in odd (vs even) frame */ + +/* Host all channels interrupt and all channels interrupt mask registers */ + +#define OTGFS_HAINT(n) (1 << (n)) /* Bits 15:0 HAINTM: Channel interrupt */ + +/* Host port control and status register */ + +#define OTGFS_HPRT_PCSTS (1 << 0) /* Bit 0: Port connect status */ +#define OTGFS_HPRT_PCDET (1 << 1) /* Bit 1: Port connect detected */ +#define OTGFS_HPRT_PENA (1 << 2) /* Bit 2: Port enable */ +#define OTGFS_HPRT_PENCHNG (1 << 3) /* Bit 3: Port enable/disable change */ +#define OTGFS_HPRT_POCA (1 << 4) /* Bit 4: Port overcurrent active */ +#define OTGFS_HPRT_POCCHNG (1 << 5) /* Bit 5: Port overcurrent change */ +#define OTGFS_HPRT_PRES (1 << 6) /* Bit 6: Port resume */ +#define OTGFS_HPRT_PSUSP (1 << 7) /* Bit 7: Port suspend */ +#define OTGFS_HPRT_PRST (1 << 8) /* Bit 8: Port reset */ + /* Bit 9: Reserved, must be kept at reset value */ +#define OTGFS_HPRT_PLSTS_SHIFT (10) /* Bits 10-11: Port line status */ +#define OTGFS_HPRT_PLSTS_MASK (3 << OTGFS_HPRT_PLSTS_SHIFT) +# define OTGFS_HPRT_PLSTS_DP (1 << 10) /* Bit 10: Logic level of OTG_FS_FS_DP */ +# define OTGFS_HPRT_PLSTS_DM (1 << 11) /* Bit 11: Logic level of OTG_FS_FS_DM */ +#define OTGFS_HPRT_PPWR (1 << 12) /* Bit 12: Port power */ +#define OTGFS_HPRT_PTCTL_SHIFT (13) /* Bits 13-16: Port test control */ +#define OTGFS_HPRT_PTCTL_MASK (15 << OTGFS_HPRT_PTCTL_SHIFT) +# define OTGFS_HPRT_PTCTL_DISABLED (0 << OTGFS_HPRT_PTCTL_SHIFT) /* Test mode disabled */ +# define OTGFS_HPRT_PTCTL_J (1 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_J mode */ +# define OTGFS_HPRT_PTCTL_L (2 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_K mode */ +# define OTGFS_HPRT_PTCTL_SE0_NAK (3 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_SE0_NAK mode */ +# define OTGFS_HPRT_PTCTL_PACKET (4 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_Packet mode */ +# define OTGFS_HPRT_PTCTL_FORCE (5 << OTGFS_HPRT_PTCTL_SHIFT) /* Test_Force_Enable */ +#define OTGFS_HPRT_PSPD_SHIFT (17) /* Bits 17-18: Port speed */ +#define OTGFS_HPRT_PSPD_MASK (3 << OTGFS_HPRT_PSPD_SHIFT) +# define OTGFS_HPRT_PSPD_FS (1 << OTGFS_HPRT_PSPD_SHIFT) /* Full speed */ +# define OTGFS_HPRT_PSPD_LS (2 << OTGFS_HPRT_PSPD_SHIFT) /* Low speed */ + /* Bits 19-31: Reserved, must be kept at reset value */ + +/* Host channel-n characteristics register */ + +#define OTGFS_HCCHAR_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */ +#define OTGFS_HCCHAR_MPSIZ_MASK (0x7ff << OTGFS_HCCHAR_MPSIZ_SHIFT) +#define OTGFS_HCCHAR_EPNUM_SHIFT (11) /* Bits 11-14: Endpoint number */ +#define OTGFS_HCCHAR_EPNUM_MASK (15 << OTGFS_HCCHAR_EPNUM_SHIFT) +#define OTGFS_HCCHAR_EPDIR (1 << 15) /* Bit 15: Endpoint direction */ +# define OTGFS_HCCHAR_EPDIR_OUT (0) +# define OTGFS_HCCHAR_EPDIR_IN OTGFS_HCCHAR_EPDIR + /* Bit 16 Reserved, must be kept at reset value */ +#define OTGFS_HCCHAR_LSDEV (1 << 17) /* Bit 17: Low-speed device */ +#define OTGFS_HCCHAR_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_HCCHAR_EPTYP_MASK (3 << OTGFS_HCCHAR_EPTYP_SHIFT) +# define OTGFS_HCCHAR_EPTYP_CTRL (0 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Control */ +# define OTGFS_HCCHAR_EPTYP_ISOC (1 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Isochronous */ +# define OTGFS_HCCHAR_EPTYP_BULK (2 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Bulk */ +# define OTGFS_HCCHAR_EPTYP_INTR (3 << OTGFS_HCCHAR_EPTYP_SHIFT) /* Interrupt */ +#define OTGFS_HCCHAR_MCNT_SHIFT (20) /* Bits 20-21: Multicount */ +#define OTGFS_HCCHAR_MCNT_MASK (3 << OTGFS_HCCHAR_MCNT_SHIFT) +#define OTGFS_HCCHAR_DAD_SHIFT (22) /* Bits 22-28: Device address */ +#define OTGFS_HCCHAR_DAD_MASK (0x7f << OTGFS_HCCHAR_DAD_SHIFT) +#define OTGFS_HCCHAR_ODDFRM (1 << 29) /* Bit 29: Odd frame */ +#define OTGFS_HCCHAR_CHDIS (1 << 30) /* Bit 30: Channel disable */ +#define OTGFS_HCCHAR_CHENA (1 << 31) /* Bit 31: Channel enable */ + +/* Host channel-n interrupt and Host channel-0 interrupt mask registers */ + +#define OTGFS_HCINT_XFRC (1 << 0) /* Bit 0: Transfer completed */ +#define OTGFS_HCINT_CHH (1 << 1) /* Bit 1: Channel halted */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_HCINT_STALL (1 << 3) /* Bit 3: STALL response received interrupt */ +#define OTGFS_HCINT_NAK (1 << 4) /* Bit 4: NAK response received interrupt */ +#define OTGFS_HCINT_ACK (1 << 5) /* Bit 5: ACK response received/transmitted interrupt */ +#define OTGFS_HCINT_NYET (1 << 6) /* Bit 6: Response received interrupt */ +#define OTGFS_HCINT_TXERR (1 << 7) /* Bit 7: Transaction error */ +#define OTGFS_HCINT_BBERR (1 << 8) /* Bit 8: Babble error */ +#define OTGFS_HCINT_FRMOR (1 << 9) /* Bit 9: Frame overrun */ +#define OTGFS_HCINT_DTERR (1 << 10) /* Bit 10: Data toggle error */ + /* Bits 11-31 Reserved, must be kept at reset value */ +/* Host channel-n interrupt register */ + +#define OTGFS_HCTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */ +#define OTGFS_HCTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_HCTSIZ_XFRSIZ_SHIFT) +#define OTGFS_HCTSIZ_PKTCNT_SHIFT (19) /* Bits 19-28: Packet count */ +#define OTGFS_HCTSIZ_PKTCNT_MASK (0x3ff << OTGFS_HCTSIZ_PKTCNT_SHIFT) +#define OTGFS_HCTSIZ_DPID_SHIFT (29) /* Bits 29-30: Data PID */ +#define OTGFS_HCTSIZ_DPID_MASK (3 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_DATA0 (0 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_DATA2 (1 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_DATA1 (2 << OTGFS_HCTSIZ_DPID_SHIFT) +# define OTGFS_HCTSIZ_DPID_MDATA (3 << OTGFS_HCTSIZ_DPID_SHIFT) /* Non-control */ +# define OTGFS_HCTSIZ_PID_SETUP (3 << OTGFS_HCTSIZ_DPID_SHIFT) /* Control */ + /* Bit 31 Reserved, must be kept at reset value */ +/* Device-mode control and status registers */ + +/* Device configuration register */ + +#define OTGFS_DCFG_DSPD_SHIFT (0) /* Bits 0-1: Device speed */ +#define OTGFS_DCFG_DSPD_MASK (3 << OTGFS_DCFG_DSPD_SHIFT) +# define OTGFS_DCFG_DSPD_FS (3 << OTGFS_DCFG_DSPD_SHIFT) /* Full speed */ +#define OTGFS_DCFG_NZLSOHSK (1 << 2) /* Bit 2: Non-zero-length status OUT handshake */ + /* Bit 3: Reserved, must be kept at reset value */ +#define OTGFS_DCFG_DAD_SHIFT (4) /* Bits 4-10: Device address */ +#define OTGFS_DCFG_DAD_MASK (0x7f << OTGFS_DCFG_DAD_SHIFT) +#define OTGFS_DCFG_PFIVL_SHIFT (11) /* Bits 11-12: Periodic frame interval */ +#define OTGFS_DCFG_PFIVL_MASK (3 << OTGFS_DCFG_PFIVL_SHIFT) +# define OTGFS_DCFG_PFIVL_80PCT (0 << OTGFS_DCFG_PFIVL_SHIFT) /* 80% of the frame interval */ +# define OTGFS_DCFG_PFIVL_85PCT (1 << OTGFS_DCFG_PFIVL_SHIFT) /* 85% of the frame interval */ +# define OTGFS_DCFG_PFIVL_90PCT (2 << OTGFS_DCFG_PFIVL_SHIFT) /* 90% of the frame interval */ +# define OTGFS_DCFG_PFIVL_95PCT (3 << OTGFS_DCFG_PFIVL_SHIFT) /* 95% of the frame interval */ + /* Bits 13-31 Reserved, must be kept at reset value */ +/* Device control register */ + +#define OTGFS_TESTMODE_DISABLED (0) /* Test mode disabled */ +#define OTGFS_TESTMODE_J (1) /* Test_J mode */ +#define OTGFS_TESTMODE_K (2) /* Test_K mode */ +#define OTGFS_TESTMODE_SE0_NAK (3) /* Test_SE0_NAK mode */ +#define OTGFS_TESTMODE_PACKET (4) /* Test_Packet mode */ +#define OTGFS_TESTMODE_FORCE (5) /* Test_Force_Enable */ + +#define OTGFS_DCTL_RWUSIG (1 << 0) /* Bit 0: Remote wakeup signaling */ +#define OTGFS_DCTL_SDIS (1 << 1) /* Bit 1: Soft disconnect */ +#define OTGFS_DCTL_GINSTS (1 << 2) /* Bit 2: Global IN NAK status */ +#define OTGFS_DCTL_GONSTS (1 << 3) /* Bit 3: Global OUT NAK status */ +#define OTGFS_DCTL_TCTL_SHIFT (4) /* Bits 4-6: Test control */ +#define OTGFS_DCTL_TCTL_MASK (7 << OTGFS_DCTL_TCTL_SHIFT) +# define OTGFS_DCTL_TCTL_DISABLED (0 << OTGFS_DCTL_TCTL_SHIFT) /* Test mode disabled */ +# define OTGFS_DCTL_TCTL_J (1 << OTGFS_DCTL_TCTL_SHIFT) /* Test_J mode */ +# define OTGFS_DCTL_TCTL_K (2 << OTGFS_DCTL_TCTL_SHIFT) /* Test_K mode */ +# define OTGFS_DCTL_TCTL_SE0_NAK (3 << OTGFS_DCTL_TCTL_SHIFT) /* Test_SE0_NAK mode */ +# define OTGFS_DCTL_TCTL_PACKET (4 << OTGFS_DCTL_TCTL_SHIFT) /* Test_Packet mode */ +# define OTGFS_DCTL_TCTL_FORCE (5 << OTGFS_DCTL_TCTL_SHIFT) /* Test_Force_Enable */ +#define OTGFS_DCTL_SGINAK (1 << 7) /* Bit 7: Set global IN NAK */ +#define OTGFS_DCTL_CGINAK (1 << 8) /* Bit 8: Clear global IN NAK */ +#define OTGFS_DCTL_SGONAK (1 << 9) /* Bit 9: Set global OUT NAK */ +#define OTGFS_DCTL_CGONAK (1 << 10) /* Bit 10: Clear global OUT NAK */ +#define OTGFS_DCTL_POPRGDNE (1 << 11) /* Bit 11: Power-on programming done */ + /* Bits 12-31: Reserved, must be kept at reset value */ +/* Device status register */ + +#define OTGFS_DSTS_SUSPSTS (1 << 0) /* Bit 0: Suspend status */ +#define OTGFS_DSTS_ENUMSPD_SHIFT (1) /* Bits 1-2: Enumerated speed */ +#define OTGFS_DSTS_ENUMSPD_MASK (3 << OTGFS_DSTS_ENUMSPD_SHIFT) +# define OTGFS_DSTS_ENUMSPD_FS (3 << OTGFS_DSTS_ENUMSPD_MASK) /* Full speed */ + /* Bits 4-7: Reserved, must be kept at reset value */ +#define OTGFS_DSTS_EERR (1 << 3) /* Bit 3: Erratic error */ +#define OTGFS_DSTS_SOFFN_SHIFT (8) /* Bits 8-21: Frame number of the received SOF */ +#define OTGFS_DSTS_SOFFN_MASK (0x3fff << OTGFS_DSTS_SOFFN_SHIFT) +#define OTGFS_DSTS_SOFFN0 (1 << 8) /* Bits 8: Frame number even/odd bit */ +#define OTGFS_DSTS_SOFFN_EVEN 0 +#define OTGFS_DSTS_SOFFN_ODD OTGFS_DSTS_SOFFN0 + /* Bits 22-31: Reserved, must be kept at reset value */ +/* Device IN endpoint common interrupt mask register */ + +#define OTGFS_DIEPMSK_XFRCM (1 << 0) /* Bit 0: Transfer completed interrupt mask */ +#define OTGFS_DIEPMSK_EPDM (1 << 1) /* Bit 1: Endpoint disabled interrupt mask */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DIEPMSK_TOM (1 << 3) /* Bit 3: Timeout condition mask (Non-isochronous endpoints) */ +#define OTGFS_DIEPMSK_ITTXFEMSK (1 << 4) /* Bit 4: IN token received when TxFIFO empty mask */ +#define OTGFS_DIEPMSK_INEPNMM (1 << 5) /* Bit 5: IN token received with EP mismatch mask */ +#define OTGFS_DIEPMSK_INEPNEM (1 << 6) /* Bit 6: IN endpoint NAK effective mask */ + /* Bits 7-31: Reserved, must be kept at reset value */ +/* Device OUT endpoint common interrupt mask register */ + +#define OTGFS_DOEPMSK_XFRCM (1 << 0) /* Bit 0: Transfer completed interrupt mask */ +#define OTGFS_DOEPMSK_EPDM (1 << 1) /* Bit 1: Endpoint disabled interrupt mask */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DOEPMSK_STUPM (1 << 3) /* Bit 3: SETUP phase done mask */ +#define OTGFS_DOEPMSK_OTEPDM (1 << 4) /* Bit 4: OUT token received when endpoint disabled mask */ + /* Bits 5-31: Reserved, must be kept at reset value */ +/* Device all endpoints interrupt and All endpoints interrupt mask registers */ + +#define OTGFS_DAINT_IEP_SHIFT (0) /* Bits 0-15: IN endpoint interrupt bits */ +#define OTGFS_DAINT_IEP_MASK (0xffff << OTGFS_DAINT_IEP_SHIFT) +# define OTGFS_DAINT_IEP(n) (1 << (n)) +#define OTGFS_DAINT_OEP_SHIFT (16) /* Bits 16-31: OUT endpoint interrupt bits */ +#define OTGFS_DAINT_OEP_MASK (0xffff << OTGFS_DAINT_OEP_SHIFT) +# define OTGFS_DAINT_OEP(n) (1 << ((n)+16)) + +/* Device VBUS discharge time register */ + +#define OTGFS_DVBUSDIS_MASK (0xffff) + +/* Device VBUS pulsing time register */ + +#define OTGFS_DVBUSPULSE_MASK (0xfff) + +/* Device IN endpoint FIFO empty interrupt mask register */ + +#define OTGFS_DIEPEMPMSK(n) (1 << (n)) + +/* Device control IN endpoint 0 control register */ + +#define OTGFS_DIEPCTL0_MPSIZ_SHIFT (0) /* Bits 0-1: Maximum packet size */ +#define OTGFS_DIEPCTL0_MPSIZ_MASK (3 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) +# define OTGFS_DIEPCTL0_MPSIZ_64 (0 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 64 bytes */ +# define OTGFS_DIEPCTL0_MPSIZ_32 (1 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 32 bytes */ +# define OTGFS_DIEPCTL0_MPSIZ_16 (2 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 16 bytes */ +# define OTGFS_DIEPCTL0_MPSIZ_8 (3 << OTGFS_DIEPCTL0_MPSIZ_SHIFT) /* 8 bytes */ + /* Bits 2-14: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ + /* Bit 16: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DIEPCTL0_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DIEPCTL0_EPTYP_MASK (3 << OTGFS_DIEPCTL0_EPTYP_SHIFT) +# define OTGFS_DIEPCTL0_EPTYP_CTRL (0 << OTGFS_DIEPCTL0_EPTYP_SHIFT) /* Control (hard-coded) */ + /* Bit 20: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_STALL (1 << 21) /* Bit 21: STALL handshake */ +#define OTGFS_DIEPCTL0_TXFNUM_SHIFT (22) /* Bits 22-25: TxFIFO number */ +#define OTGFS_DIEPCTL0_TXFNUM_MASK (15 << OTGFS_DIEPCTL0_TXFNUM_SHIFT) +#define OTGFS_DIEPCTL0_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DIEPCTL0_SNAK (1 << 27) /* Bit 27: Set NAK */ + /* Bits 28-29: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL0_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DIEPCTL0_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device control IN endpoint n control register */ + +#define OTGFS_DIEPCTL_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */ +#define OTGFS_DIEPCTL_MPSIZ_MASK (0x7ff << OTGFS_DIEPCTL_MPSIZ_SHIFT) + /* Bits 11-14: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ +#define OTGFS_DIEPCTL_EONUM (1 << 16) /* Bit 16: Even/odd frame */ +# define OTGFS_DIEPCTL_EVEN (0) +# define OTGFS_DIEPCTL_ODD OTGFS_DIEPCTL_EONUM +# define OTGFS_DIEPCTL_DATA0 (0) +# define OTGFS_DIEPCTL_DATA1 OTGFS_DIEPCTL_EONUM +#define OTGFS_DIEPCTL_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DIEPCTL_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DIEPCTL_EPTYP_MASK (3 << OTGFS_DIEPCTL_EPTYP_SHIFT) +# define OTGFS_DIEPCTL_EPTYP_CTRL (0 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Control */ +# define OTGFS_DIEPCTL_EPTYP_ISOC (1 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Isochronous */ +# define OTGFS_DIEPCTL_EPTYP_BULK (2 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Bulk */ +# define OTGFS_DIEPCTL_EPTYP_INTR (3 << OTGFS_DIEPCTL_EPTYP_SHIFT) /* Interrupt */ + /* Bit 20: Reserved, must be kept at reset value */ +#define OTGFS_DIEPCTL_STALL (1 << 21) /* Bit 21: STALL handshake */ +#define OTGFS_DIEPCTL_TXFNUM_SHIFT (22) /* Bits 22-25: TxFIFO number */ +#define OTGFS_DIEPCTL_TXFNUM_MASK (15 << OTGFS_DIEPCTL_TXFNUM_SHIFT) +#define OTGFS_DIEPCTL_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DIEPCTL_SNAK (1 << 27) /* Bit 27: Set NAK */ +#define OTGFS_DIEPCTL_SD0PID (1 << 28) /* Bit 28: Set DATA0 PID (interrupt/bulk) */ +#define OTGFS_DIEPCTL_SEVNFRM (1 << 28) /* Bit 28: Set even frame (isochronous)) */ +#define OTGFS_DIEPCTL_SODDFRM (1 << 29) /* Bit 29: Set odd frame (isochronous) */ +#define OTGFS_DIEPCTL_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DIEPCTL_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device endpoint-n interrupt register */ + +#define OTGFS_DIEPINT_XFRC (1 << 0) /* Bit 0: Transfer completed interrupt */ +#define OTGFS_DIEPINT_EPDISD (1 << 1) /* Bit 1: Endpoint disabled interrupt */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DIEPINT_TOC (1 << 3) /* Bit 3: Timeout condition */ +#define OTGFS_DIEPINT_ITTXFE (1 << 4) /* Bit 4: IN token received when TxFIFO is empty */ + /* Bit 5: Reserved, must be kept at reset value */ +#define OTGFS_DIEPINT_INEPNE (1 << 6) /* Bit 6: IN endpoint NAK effective */ +#define OTGFS_DIEPINT_TXFE (1 << 7) /* Bit 7: Transmit FIFO empty */ + /* Bits 8-31: Reserved, must be kept at reset value */ +/* Device IN endpoint 0 transfer size register */ + +#define OTGFS_DIEPTSIZ0_XFRSIZ_SHIFT (0) /* Bits 0-6: Transfer size */ +#define OTGFS_DIEPTSIZ0_XFRSIZ_MASK (0x7f << OTGFS_DIEPTSIZ0_XFRSIZ_SHIFT) + /* Bits 7-18: Reserved, must be kept at reset value */ +#define OTGFS_DIEPTSIZ0_PKTCNT_SHIFT (19) /* Bits 19-20: Packet count */ +#define OTGFS_DIEPTSIZ0_PKTCNT_MASK (3 << OTGFS_DIEPTSIZ0_PKTCNT_SHIFT) + /* Bits 21-31: Reserved, must be kept at reset value */ +/* Device IN endpoint n transfer size register */ + +#define OTGFS_DIEPTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */ +#define OTGFS_DIEPTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_DIEPTSIZ_XFRSIZ_SHIFT) +#define OTGFS_DIEPTSIZ_PKTCNT_SHIFT (19) /* Bit 19-28: Packet count */ +#define OTGFS_DIEPTSIZ_PKTCNT_MASK (0x3ff << OTGFS_DIEPTSIZ_PKTCNT_SHIFT) +#define OTGFS_DIEPTSIZ_MCNT_SHIFT (29) /* Bits 29-30: Multi count */ +#define OTGFS_DIEPTSIZ_MCNT_MASK (3 << OTGFS_DIEPTSIZ_MCNT_SHIFT) + /* Bit 31: Reserved, must be kept at reset value */ +/* Device OUT endpoint TxFIFO status register */ + +#define OTGFS_DTXFSTS_MASK (0xffff) + +/* Device OUT endpoint 0 control register */ + +#define OTGFS_DOEPCTL0_MPSIZ_SHIFT (0) /* Bits 0-1: Maximum packet size */ +#define OTGFS_DOEPCTL0_MPSIZ_MASK (3 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) +# define OTGFS_DOEPCTL0_MPSIZ_64 (0 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 64 bytes */ +# define OTGFS_DOEPCTL0_MPSIZ_32 (1 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 32 bytes */ +# define OTGFS_DOEPCTL0_MPSIZ_16 (2 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 16 bytes */ +# define OTGFS_DOEPCTL0_MPSIZ_8 (3 << OTGFS_DOEPCTL0_MPSIZ_SHIFT) /* 8 bytes */ + /* Bits 2-14: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ + /* Bit 16: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DOEPCTL0_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DOEPCTL0_EPTYP_MASK (3 << OTGFS_DOEPCTL0_EPTYP_SHIFT) +# define OTGFS_DOEPCTL0_EPTYP_CTRL (0 << OTGFS_DOEPCTL0_EPTYP_SHIFT) /* Control (hard-coded) */ +#define OTGFS_DOEPCTL0_SNPM (1 << 20) /* Bit 20: Snoop mode */ +#define OTGFS_DOEPCTL0_STALL (1 << 21) /* Bit 21: STALL handshake */ + /* Bits 22-25: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DOEPCTL0_SNAK (1 << 27) /* Bit 27: Set NAK */ + /* Bits 28-29: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL0_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DOEPCTL0_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device OUT endpoint n control register */ + +#define OTGFS_DOEPCTL_MPSIZ_SHIFT (0) /* Bits 0-10: Maximum packet size */ +#define OTGFS_DOEPCTL_MPSIZ_MASK (0x7ff << OTGFS_DOEPCTL_MPSIZ_SHIFT) + /* Bits 11-14: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL_USBAEP (1 << 15) /* Bit 15: USB active endpoint */ +#define OTGFS_DOEPCTL_DPID (1 << 16) /* Bit 16: Endpoint data PID (interrupt/buld) */ +# define OTGFS_DOEPCTL_DATA0 (0) +# define OTGFS_DOEPCTL_DATA1 OTGFS_DOEPCTL_DPID +#define OTGFS_DOEPCTL_EONUM (1 << 16) /* Bit 16: Even/odd frame (isochronous) */ +# define OTGFS_DOEPCTL_EVEN (0) +# define OTGFS_DOEPCTL_ODD OTGFS_DOEPCTL_EONUM +#define OTGFS_DOEPCTL_NAKSTS (1 << 17) /* Bit 17: NAK status */ +#define OTGFS_DOEPCTL_EPTYP_SHIFT (18) /* Bits 18-19: Endpoint type */ +#define OTGFS_DOEPCTL_EPTYP_MASK (3 << OTGFS_DOEPCTL_EPTYP_SHIFT) +# define OTGFS_DOEPCTL_EPTYP_CTRL (0 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Control */ +# define OTGFS_DOEPCTL_EPTYP_ISOC (1 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Isochronous */ +# define OTGFS_DOEPCTL_EPTYP_BULK (2 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Bulk */ +# define OTGFS_DOEPCTL_EPTYP_INTR (3 << OTGFS_DOEPCTL_EPTYP_SHIFT) /* Interrupt */ +#define OTGFS_DOEPCTL_SNPM (1 << 20) /* Bit 20: Snoop mode */ +#define OTGFS_DOEPCTL_STALL (1 << 21) /* Bit 21: STALL handshake */ + /* Bits 22-25: Reserved, must be kept at reset value */ +#define OTGFS_DOEPCTL_CNAK (1 << 26) /* Bit 26: Clear NAK */ +#define OTGFS_DOEPCTL_SNAK (1 << 27) /* Bit 27: Set NAK */ +#define OTGFS_DOEPCTL_SD0PID (1 << 28) /* Bit 28: Set DATA0 PID (interrupt/bulk) */ +#define OTGFS_DOEPCTL_SEVNFRM (1 << 28) /* Bit 28: Set even frame (isochronous) */ +#define OTGFS_DOEPCTL_SD1PID (1 << 29) /* Bit 29: Set DATA1 PID (interrupt/bulk) */ +#define OTGFS_DOEPCTL_SODDFRM (1 << 29) /* Bit 29: Set odd frame (isochronous */ +#define OTGFS_DOEPCTL_EPDIS (1 << 30) /* Bit 30: Endpoint disable */ +#define OTGFS_DOEPCTL_EPENA (1 << 31) /* Bit 31: Endpoint enable */ + +/* Device endpoint-n interrupt register */ + +#define OTGFS_DOEPINT_XFRC (1 << 0) /* Bit 0: Transfer completed interrupt */ +#define OTGFS_DOEPINT_EPDISD (1 << 1) /* Bit 1: Endpoint disabled interrupt */ + /* Bit 2: Reserved, must be kept at reset value */ +#define OTGFS_DOEPINT_SETUP (1 << 3) /* Bit 3: SETUP phase done */ +#define OTGFS_DOEPINT_OTEPDIS (1 << 4) /* Bit 4: OUT token received when endpoint disabled */ + /* Bit 5: Reserved, must be kept at reset value */ +#define OTGFS_DOEPINT_B2BSTUP (1 << 6) /* Bit 6: Back-to-back SETUP packets received */ + /* Bits 7-31: Reserved, must be kept at reset value */ +/* Device OUT endpoint-0 transfer size register */ + +#define OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT (0) /* Bits 0-6: Transfer size */ +#define OTGFS_DOEPTSIZ0_XFRSIZ_MASK (0x7f << OTGFS_DOEPTSIZ0_XFRSIZ_SHIFT) + /* Bits 7-18: Reserved, must be kept at reset value */ +#define OTGFS_DOEPTSIZ0_PKTCNT (1 << 19) /* Bit 19 PKTCNT: Packet count */ + /* Bits 20-28: Reserved, must be kept at reset value */ +#define OTGFS_DOEPTSIZ0_STUPCNT_SHIFT (29) /* Bits 29-30: SETUP packet count */ +#define OTGFS_DOEPTSIZ0_STUPCNT_MASK (3 << OTGFS_DOEPTSIZ0_STUPCNT_SHIFT) + /* Bit 31: Reserved, must be kept at reset value */ +/* Device OUT endpoint-n transfer size register */ + +#define OTGFS_DOEPTSIZ_XFRSIZ_SHIFT (0) /* Bits 0-18: Transfer size */ +#define OTGFS_DOEPTSIZ_XFRSIZ_MASK (0x7ffff << OTGFS_DOEPTSIZ_XFRSIZ_SHIFT) +#define OTGFS_DOEPTSIZ_PKTCNT_SHIFT (19) /* Bit 19-28: Packet count */ +#define OTGFS_DOEPTSIZ_PKTCNT_MASK (0x3ff << OTGFS_DOEPTSIZ_PKTCNT_SHIFT) +#define OTGFS_DOEPTSIZ_STUPCNT_SHIFT (29) /* Bits 29-30: SETUP packet count */ +#define OTGFS_DOEPTSIZ_STUPCNT_MASK (3 << OTGFS_DOEPTSIZ_STUPCNT_SHIFT) +#define OTGFS_DOEPTSIZ_RXDPID_SHIFT (29) /* Bits 29-30: Received data PID */ +#define OTGFS_DOEPTSIZ_RXDPID_MASK (3 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_DATA0 (0 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_DATA2 (1 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_DATA1 (2 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) +# define OTGFS_DOEPTSIZ_RXDPID_MDATA (3 << OTGFS_DOEPTSIZ_RXDPID_SHIFT) + /* Bit 31: Reserved, must be kept at reset value */ +/* Power and clock gating control register */ + +#define OTGFS_PCGCCTL_STPPCLK (1 << 0) /* Bit 0: Stop PHY clock */ +#define OTGFS_PCGCCTL_GATEHCLK (1 << 1) /* Bit 1: Gate HCLK */ + /* Bits 2-3: Reserved, must be kept at reset value */ +#define OTGFS_PCGCCTL_PHYSUSP (1 << 4) /* Bit 4: PHY Suspended */ + /* Bits 5-31: Reserved, must be kept at reset value */ + +#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32FXXXXX_OTGFS_H */ diff --git a/arch/arm/src/stm32/stm32_adc.c b/arch/arm/src/stm32/stm32_adc.c index 22be50c9956..2fc9e3a7701 100644 --- a/arch/arm/src/stm32/stm32_adc.c +++ b/arch/arm/src/stm32/stm32_adc.c @@ -960,7 +960,7 @@ static void adc_startconv(struct stm32_dev_s *priv, bool enable) if (enable) { -#if CONFIG_ADC_CONTINUOUS +#ifdef CONFIG_ADC_CONTINUOUS /* Set continuous mode */ @@ -974,7 +974,7 @@ static void adc_startconv(struct stm32_dev_s *priv, bool enable) } else { -#if CONFIG_ADC_CONTINUOUS +#ifdef CONFIG_ADC_CONTINUOUS /* Disable the continuous conversion */ @@ -1761,10 +1761,9 @@ static void adc_shutdown(FAR struct adc_dev_s *dev) { FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; -#if CONFIG_STM32_STM32L15XX +#ifdef CONFIG_STM32_STM32L15XX adc_enable(priv, false); -# if defined(CONFIG_STM32_STM32L15XX) && ((STM32_CFGR_PLLSRC != 0) || \ - (STM32_SYSCLK_SW != RCC_CFGR_SW_HSI)) +# if (STM32_CFGR_PLLSRC != 0) || (STM32_SYSCLK_SW != RCC_CFGR_SW_HSI) adc_enable_hsi(false); # endif #endif diff --git a/arch/arm/src/stm32/stm32_can.c b/arch/arm/src/stm32/stm32_can.c index 297394abd25..fd174ffaffe 100644 --- a/arch/arm/src/stm32/stm32_can.c +++ b/arch/arm/src/stm32/stm32_can.c @@ -1070,6 +1070,7 @@ static int can_rx0interrupt(int irq, void *context) /* Get the CAN identifier. */ regval = can_getreg(priv, STM32_CAN_RI0R_OFFSET); + #ifdef CONFIG_CAN_EXTID if ((regval & CAN_RIR_IDE) != 0) { @@ -1089,17 +1090,22 @@ static int can_rx0interrupt(int irq, void *context) goto errout; } - hdr.ch_id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT; + hdr.ch_id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT; #endif + /* Clear the error indication and unused bits */ + + hdr.ch_error = 0; + hdr.ch_unused = 0; + /* Extract the RTR bit */ - hdr.ch_rtr = (regval & CAN_RIR_RTR) != 0 ? true : false; + hdr.ch_rtr = (regval & CAN_RIR_RTR) != 0 ? true : false; /* Get the DLC */ - regval = can_getreg(priv, STM32_CAN_RDT0R_OFFSET); - hdr.ch_dlc = (regval & CAN_RDTR_DLC_MASK) >> CAN_RDTR_DLC_SHIFT; + regval = can_getreg(priv, STM32_CAN_RDT0R_OFFSET); + hdr.ch_dlc = (regval & CAN_RDTR_DLC_MASK) >> CAN_RDTR_DLC_SHIFT; /* Save the message data */ diff --git a/arch/arm/src/stm32/stm32_eth.c b/arch/arm/src/stm32/stm32_eth.c index 1ef3687c04a..90c6c93271d 100644 --- a/arch/arm/src/stm32/stm32_eth.c +++ b/arch/arm/src/stm32/stm32_eth.c @@ -467,7 +467,7 @@ * checksum is OK the DMA can handle the frame otherwise the frame is dropped */ -#if CONFIG_STM32_ETH_HWCHECKSUM +#ifdef CONFIG_STM32_ETH_HWCHECKSUM # define DMAOMR_SET_MASK \ (ETH_DMAOMR_OSF | ETH_DMAOMR_RTC_64 | ETH_DMAOMR_TTC_64 | \ ETH_DMAOMR_TSF | ETH_DMAOMR_RSF) @@ -680,7 +680,6 @@ static void stm32_poll_expiry(int argc, uint32_t arg, ...); static int stm32_ifup(struct net_driver_s *dev); static int stm32_ifdown(struct net_driver_s *dev); -static int stm32_ifdown(struct net_driver_s *dev); static inline void stm32_txavail_process(FAR struct stm32_ethmac_s *priv); #ifdef CONFIG_NET_NOINTS static void stm32_txavail_work(FAR void *arg); @@ -1670,6 +1669,16 @@ static void stm32_receive(FAR struct stm32_ethmac_s *priv) if (dev->d_len > CONFIG_NET_ETH_MTU) { nlldbg("DROPPED: Too big: %d\n", dev->d_len); + + /* Free dropped packet buffer */ + + if (dev->d_buf) + { + stm32_freebuffer(priv, dev->d_buf); + dev->d_buf = NULL; + dev->d_len = 0; + } + continue; } @@ -1915,7 +1924,7 @@ static void stm32_txdone(FAR struct stm32_ethmac_s *priv) { DEBUGASSERT(priv->txtail != NULL); - /* Scan the TX desciptor change, returning buffers to free list */ + /* Scan the TX descriptor change, returning buffers to free list */ stm32_freeframe(priv); diff --git a/arch/arm/src/stm32/stm32_gpio.c b/arch/arm/src/stm32/stm32_gpio.c index e2adaea1f4f..f383b827efd 100644 --- a/arch/arm/src/stm32/stm32_gpio.c +++ b/arch/arm/src/stm32/stm32_gpio.c @@ -208,9 +208,9 @@ static inline void stm32_gpioremap(void) #ifdef CONFIG_STM32_JTAG_FULL_ENABLE /* The reset default */ -#elif CONFIG_STM32_JTAG_NOJNTRST_ENABLE +#elif defined(CONFIG_STM32_JTAG_NOJNTRST_ENABLE) val |= AFIO_MAPR_SWJ; /* enabled but without JNTRST */ -#elif CONFIG_STM32_JTAG_SW_ENABLE +#elif defined(CONFIG_STM32_JTAG_SW_ENABLE) val |= AFIO_MAPR_SWDP; /* set JTAG-DP disabled and SW-DP enabled */ #else val |= AFIO_MAPR_DISAB; /* set JTAG-DP and SW-DP Disabled */ diff --git a/arch/arm/src/stm32/stm32_irq.c b/arch/arm/src/stm32/stm32_irq.c index a9781cf0cee..c3cc59fc8b9 100644 --- a/arch/arm/src/stm32/stm32_irq.c +++ b/arch/arm/src/stm32/stm32_irq.c @@ -2,7 +2,7 @@ * arch/arm/src/stm32/stm32_irq.c * arch/arm/src/chip/stm32_irq.c * - * Copyright (C) 2009-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2009-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -76,8 +76,18 @@ * Public Data ****************************************************************************/ +/* This is the address of current interrupt saved state data. Used for + * context switching. Only value during interrupt handling. + */ + volatile uint32_t *current_regs; +/* This is the address of the exception vector table (determined by the + * linker script). + */ + +extern uint32_t _vectors[]; + /**************************************************************************** * Private Data ****************************************************************************/ @@ -320,15 +330,16 @@ void up_irqinitialize(void) * at address 0x0800:0000. If we are using the STMicro DFU bootloader, then * the vector table will be offset to a different location in FLASH and we * will need to set the NVIC vector location to this alternative location. - * - * If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ -#if defined(CONFIG_ARCH_RAMVECTORS) up_ramvec_initialize(); -#elif defined(CONFIG_STM32_DFU) - putreg32((uint32_t)_vectors, NVIC_VECTAB); #endif /* Set all interrupts (and exceptions) to the default priority */ diff --git a/arch/arm/src/stm32/stm32_lowputc.c b/arch/arm/src/stm32/stm32_lowputc.c index 8afb6fcd3e2..545bc2cc53d 100644 --- a/arch/arm/src/stm32/stm32_lowputc.c +++ b/arch/arm/src/stm32/stm32_lowputc.c @@ -406,7 +406,7 @@ void up_lowputc(char ch) /* Wait until the TX data register is empty */ while ((getreg32(STM32_CONSOLE_BASE + STM32_USART_SR_OFFSET) & USART_SR_TXE) == 0); -#if STM32_CONSOLE_RS485_DIR +#ifdef STM32_CONSOLE_RS485_DIR stm32_gpiowrite(STM32_CONSOLE_RS485_DIR, STM32_CONSOLE_RS485_DIR_POLARITY); #endif @@ -414,7 +414,7 @@ void up_lowputc(char ch) putreg32((uint32_t)ch, STM32_CONSOLE_BASE + STM32_USART_TDR_OFFSET); -#if STM32_CONSOLE_RS485_DIR +#ifdef STM32_CONSOLE_RS485_DIR while ((getreg32(STM32_CONSOLE_BASE + STM32_USART_SR_OFFSET) & USART_SR_TC) == 0); stm32_gpiowrite(STM32_CONSOLE_RS485_DIR, !STM32_CONSOLE_RS485_DIR_POLARITY); #endif @@ -519,7 +519,7 @@ void stm32_lowsetup(void) stm32_configgpio(STM32_CONSOLE_RX); #endif -#if STM32_CONSOLE_RS485_DIR +#ifdef STM32_CONSOLE_RS485_DIR stm32_configgpio(STM32_CONSOLE_RS485_DIR); stm32_gpiowrite(STM32_CONSOLE_RS485_DIR, !STM32_CONSOLE_RS485_DIR_POLARITY); #endif @@ -591,7 +591,7 @@ void stm32_lowsetup(void) stm32_configgpio(STM32_CONSOLE_RX); #endif -#if STM32_CONSOLE_RS485_DIR +#ifdef STM32_CONSOLE_RS485_DIR stm32_configgpio(STM32_CONSOLE_RS485_DIR); stm32_gpiowrite(STM32_CONSOLE_RS485_DIR, !STM32_CONSOLE_RS485_DIR_POLARITY); #endif diff --git a/arch/arm/src/stm32/stm32_otgfs.h b/arch/arm/src/stm32/stm32_otgfs.h index 79258168fc0..64369969df8 100644 --- a/arch/arm/src/stm32/stm32_otgfs.h +++ b/arch/arm/src/stm32/stm32_otgfs.h @@ -45,7 +45,12 @@ #include #include "stm32.h" -#include "chip/stm32_otgfs.h" + +#if defined(CONFIG_STM32_STM32F446) +# include "chip/stm32f44xxx_otgfs.h" +#else +# include "chip/stm32fxxxxx_otgfs.h" +#endif #if defined(CONFIG_STM32_OTGFS) diff --git a/arch/arm/src/stm32/stm32_otgfsdev.c b/arch/arm/src/stm32/stm32_otgfsdev.c index a7e90c69499..1da5733f6d1 100644 --- a/arch/arm/src/stm32/stm32_otgfsdev.c +++ b/arch/arm/src/stm32/stm32_otgfsdev.c @@ -5169,16 +5169,45 @@ static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv) /* Deactivate the power down */ +#if defined(CONFIG_STM32_STM32F446) + /* In the case of the STM32F446 the meaning of the bit has changed to VBUS + * Detection Enable when set + */ + + regval = OTGFS_GCCFG_PWRDWN; + +# ifdef CONFIG_USBDEV_VBUSSENSING + regval |= OTGFS_GCCFG_VBDEN; +# endif + +#else + /* In the case of the the all others the meaning of the bit is No VBUS + * Sense when Set + */ + regval = (OTGFS_GCCFG_PWRDWN | OTGFS_GCCFG_VBUSASEN | OTGFS_GCCFG_VBUSBSEN); -#ifndef CONFIG_USBDEV_VBUSSENSING +# ifndef CONFIG_USBDEV_VBUSSENSING regval |= OTGFS_GCCFG_NOVBUSSENS; -#endif -#ifdef CONFIG_STM32_OTGFS_SOFOUTPUT +# endif +# ifdef CONFIG_STM32_OTGFS_SOFOUTPUT regval |= OTGFS_GCCFG_SOFOUTEN; +# endif #endif stm32_putreg(regval, STM32_OTGFS_GCCFG); up_mdelay(20); + /* For the new OTG controller in the F446 when VBUS sensing is not used we + * need to force the B session valid + */ + +#if defined(CONFIG_STM32_STM32F446) +# ifndef CONFIG_USBDEV_VBUSSENSING + regval = stm32_getreg(STM32_OTGFS_GOTGCTL); + regval |= (OTGFS_GOTGCTL_BVALOEN | OTGFS_GOTGCTL_BVALOVAL); + stm32_putreg(regval, STM32_OTGFS_GOTGCTL); +# endif +#endif + /* Force Device Mode */ regval = stm32_getreg(STM32_OTGFS_GUSBCFG); diff --git a/arch/arm/src/stm32/stm32_otgfshost.c b/arch/arm/src/stm32/stm32_otgfshost.c index 56e09db17a5..d717ce2eb01 100644 --- a/arch/arm/src/stm32/stm32_otgfshost.c +++ b/arch/arm/src/stm32/stm32_otgfshost.c @@ -1093,7 +1093,7 @@ static int stm32_chan_wait(FAR struct stm32_usbhost_s *priv, /* Loop, testing for an end of transfer condition. The channel 'result' * was set to EBUSY and 'waiter' was set to true before the transfer; 'waiter' * will be set to false and 'result' will be set appropriately when the - * tranfer is completed. + * transfer is completed. */ do diff --git a/arch/arm/src/stm32/stm32_otghshost.c b/arch/arm/src/stm32/stm32_otghshost.c index 9e9cc0e9786..3d7340ca904 100644 --- a/arch/arm/src/stm32/stm32_otghshost.c +++ b/arch/arm/src/stm32/stm32_otghshost.c @@ -1093,7 +1093,7 @@ static int stm32_chan_wait(FAR struct stm32_usbhost_s *priv, /* Loop, testing for an end of transfer condition. The channel 'result' * was set to EBUSY and 'waiter' was set to true before the transfer; 'waiter' * will be set to false and 'result' will be set appropriately when the - * tranfer is completed. + * transfer is completed. */ do diff --git a/arch/arm/src/stm32/stm32_rtcc.c b/arch/arm/src/stm32/stm32_rtcc.c index 0c646293b11..7daecef41fc 100644 --- a/arch/arm/src/stm32/stm32_rtcc.c +++ b/arch/arm/src/stm32/stm32_rtcc.c @@ -580,7 +580,7 @@ static void rtc_resume(void) * ************************************************************************************/ -#if CONFIG_RTC_ALARM +#ifdef CONFIG_RTC_ALARM static int rtc_interrupt(int irq, void *context) { #warning "Missing logic" diff --git a/arch/arm/src/stm32/stm32_sdio.c b/arch/arm/src/stm32/stm32_sdio.c index 599df077ae6..eb4ca0e0cb4 100644 --- a/arch/arm/src/stm32/stm32_sdio.c +++ b/arch/arm/src/stm32/stm32_sdio.c @@ -64,7 +64,7 @@ #include "stm32_dma.h" #include "stm32_sdio.h" -#if CONFIG_STM32_SDIO +#ifdef CONFIG_STM32_SDIO /**************************************************************************** * Pre-processor Definitions diff --git a/arch/arm/src/stm32/stm32_serial.c b/arch/arm/src/stm32/stm32_serial.c index b0edc1be140..58aa48c5e47 100644 --- a/arch/arm/src/stm32/stm32_serial.c +++ b/arch/arm/src/stm32/stm32_serial.c @@ -77,7 +77,7 @@ * have also been selected. */ -#if SERIAL_HAVE_DMA +#ifdef SERIAL_HAVE_DMA # if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) /* Verify that DMA has been enabled and the DMA channel has been defined. @@ -1469,7 +1469,7 @@ static int up_setup(struct uart_dev_s *dev) } #endif -#if HAVE_RS485 +#ifdef HAVE_RS485 if (priv->rs485_dir_gpio != 0) { stm32_configgpio(priv->rs485_dir_gpio); @@ -1671,7 +1671,7 @@ static void up_shutdown(struct uart_dev_s *dev) } #endif -#if HAVE_RS485 +#ifdef HAVE_RS485 if (priv->rs485_dir_gpio != 0) { stm32_unconfiggpio(priv->rs485_dir_gpio); @@ -2712,7 +2712,7 @@ static int up_pm_prepare(struct pm_callback_s *cb, enum pm_state_e pmstate) * ****************************************************************************/ -#if USE_EARLYSERIALINIT +#ifdef USE_EARLYSERIALINIT void up_earlyserialinit(void) { #ifdef HAVE_UART diff --git a/arch/arm/src/stm32/stm32_tim.c b/arch/arm/src/stm32/stm32_tim.c index cced0d4a4ce..1f9d5375714 100644 --- a/arch/arm/src/stm32/stm32_tim.c +++ b/arch/arm/src/stm32/stm32_tim.c @@ -327,35 +327,35 @@ static int stm32_tim_setisr(FAR struct stm32_tim_dev_s *dev, switch (((struct stm32_tim_priv_s *)dev)->base) { -#if CONFIG_STM32_TIM2 +#ifdef CONFIG_STM32_TIM2 case STM32_TIM2_BASE: vectorno = STM32_IRQ_TIM2; break; #endif -#if CONFIG_STM32_TIM3 +#ifdef CONFIG_STM32_TIM3 case STM32_TIM3_BASE: vectorno = STM32_IRQ_TIM3; break; #endif -#if CONFIG_STM32_TIM4 +#ifdef CONFIG_STM32_TIM4 case STM32_TIM4_BASE: vectorno = STM32_IRQ_TIM4; break; #endif -#if CONFIG_STM32_TIM5 +#ifdef CONFIG_STM32_TIM5 case STM32_TIM5_BASE: vectorno = STM32_IRQ_TIM5; break; #endif #if STM32_NBTIM > 0 -#if CONFIG_STM32_TIM6 +#ifdef CONFIG_STM32_TIM6 case STM32_TIM6_BASE: vectorno = STM32_IRQ_TIM6; break; #endif #endif #if STM32_NBTIM > 1 -#if CONFIG_STM32_TIM7 +#ifdef CONFIG_STM32_TIM7 case STM32_TIM7_BASE: vectorno = STM32_IRQ_TIM7; break; @@ -364,12 +364,12 @@ static int stm32_tim_setisr(FAR struct stm32_tim_dev_s *dev, #if STM32_NATIM > 0 /* TODO: add support for multiple sources and callbacks */ -#if CONFIG_STM32_TIM1 +#ifdef CONFIG_STM32_TIM1 case STM32_TIM1_BASE: vectorno = STM32_IRQ_TIM1UP; break; #endif -#if CONFIG_STM32_TIM8 +#ifdef CONFIG_STM32_TIM8 case STM32_TIM8_BASE: vectorno = STM32_IRQ_TIM8UP; break; @@ -570,7 +570,7 @@ static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel switch (((struct stm32_tim_priv_s *)dev)->base) { -#if CONFIG_STM32_TIM2 +#ifdef CONFIG_STM32_TIM2 case STM32_TIM2_BASE: switch (channel) { @@ -599,7 +599,7 @@ static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel } break; #endif -#if CONFIG_STM32_TIM3 +#ifdef CONFIG_STM32_TIM3 case STM32_TIM3_BASE: switch (channel) { @@ -628,7 +628,7 @@ static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel } break; #endif -#if CONFIG_STM32_TIM4 +#ifdef CONFIG_STM32_TIM4 case STM32_TIM4_BASE: switch (channel) { @@ -656,7 +656,7 @@ static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel } break; #endif -#if CONFIG_STM32_TIM5 +#ifdef CONFIG_STM32_TIM5 case STM32_TIM5_BASE: switch (channel) { @@ -686,7 +686,7 @@ static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel #endif #if STM32_NATIM > 0 -#if CONFIG_STM32_TIM1 +#ifdef CONFIG_STM32_TIM1 case STM32_TIM1_BASE: switch (channel) { @@ -710,7 +710,7 @@ static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel } break; #endif -#if CONFIG_STM32_TIM8 +#ifdef CONFIG_STM32_TIM8 case STM32_TIM8_BASE: switch (channel) { @@ -811,7 +811,7 @@ struct stm32_tim_ops_s stm32_tim_ops = .ackint = &stm32_tim_ackint }; -#if CONFIG_STM32_TIM2 +#ifdef CONFIG_STM32_TIM2 struct stm32_tim_priv_s stm32_tim2_priv = { .ops = &stm32_tim_ops, @@ -820,7 +820,7 @@ struct stm32_tim_priv_s stm32_tim2_priv = }; #endif -#if CONFIG_STM32_TIM3 +#ifdef CONFIG_STM32_TIM3 struct stm32_tim_priv_s stm32_tim3_priv = { .ops = &stm32_tim_ops, @@ -829,7 +829,7 @@ struct stm32_tim_priv_s stm32_tim3_priv = }; #endif -#if CONFIG_STM32_TIM4 +#ifdef CONFIG_STM32_TIM4 struct stm32_tim_priv_s stm32_tim4_priv = { .ops = &stm32_tim_ops, @@ -838,7 +838,7 @@ struct stm32_tim_priv_s stm32_tim4_priv = }; #endif -#if CONFIG_STM32_TIM5 +#ifdef CONFIG_STM32_TIM5 struct stm32_tim_priv_s stm32_tim5_priv = { .ops = &stm32_tim_ops, @@ -848,7 +848,7 @@ struct stm32_tim_priv_s stm32_tim5_priv = #endif #if STM32_NBTIM > 0 -#if CONFIG_STM32_TIM6 +#ifdef CONFIG_STM32_TIM6 struct stm32_tim_priv_s stm32_tim6_priv = { .ops = &stm32_tim_ops, @@ -859,7 +859,7 @@ struct stm32_tim_priv_s stm32_tim6_priv = #endif #if STM32_NBTIM > 1 -#if CONFIG_STM32_TIM7 +#ifdef CONFIG_STM32_TIM7 struct stm32_tim_priv_s stm32_tim7_priv = { .ops = &stm32_tim_ops, @@ -871,7 +871,7 @@ struct stm32_tim_priv_s stm32_tim7_priv = #if STM32_NATIM > 0 -#if CONFIG_STM32_TIM1 +#ifdef CONFIG_STM32_TIM1 struct stm32_tim_priv_s stm32_tim1_priv = { .ops = &stm32_tim_ops, @@ -880,7 +880,7 @@ struct stm32_tim_priv_s stm32_tim1_priv = }; #endif -#if CONFIG_STM32_TIM8 +#ifdef CONFIG_STM32_TIM8 struct stm32_tim_priv_s stm32_tim8_priv = { .ops = &stm32_tim_ops, @@ -903,25 +903,25 @@ FAR struct stm32_tim_dev_s *stm32_tim_init(int timer) switch (timer) { -#if CONFIG_STM32_TIM2 +#ifdef CONFIG_STM32_TIM2 case 2: dev = (struct stm32_tim_dev_s *)&stm32_tim2_priv; modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM2EN); break; #endif -#if CONFIG_STM32_TIM3 +#ifdef CONFIG_STM32_TIM3 case 3: dev = (struct stm32_tim_dev_s *)&stm32_tim3_priv; modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM3EN); break; #endif -#if CONFIG_STM32_TIM4 +#ifdef CONFIG_STM32_TIM4 case 4: dev = (struct stm32_tim_dev_s *)&stm32_tim4_priv; modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM4EN); break; #endif -#if CONFIG_STM32_TIM5 +#ifdef CONFIG_STM32_TIM5 case 5: dev = (struct stm32_tim_dev_s *)&stm32_tim5_priv; modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM5EN); @@ -929,7 +929,7 @@ FAR struct stm32_tim_dev_s *stm32_tim_init(int timer) #endif #if STM32_NBTIM > 0 -#if CONFIG_STM32_TIM6 +#ifdef CONFIG_STM32_TIM6 case 6: dev = (struct stm32_tim_dev_s *)&stm32_tim6_priv; modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM6EN); @@ -937,7 +937,7 @@ FAR struct stm32_tim_dev_s *stm32_tim_init(int timer) #endif #endif #if STM32_NBTIM > 1 -#if CONFIG_STM32_TIM7 +#ifdef CONFIG_STM32_TIM7 case 7: dev = (struct stm32_tim_dev_s *)&stm32_tim7_priv; modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_TIM7EN); @@ -946,13 +946,13 @@ FAR struct stm32_tim_dev_s *stm32_tim_init(int timer) #endif #if STM32_NATIM > 0 -#if CONFIG_STM32_TIM1 +#ifdef CONFIG_STM32_TIM1 case 1: dev = (struct stm32_tim_dev_s *)&stm32_tim1_priv; modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM1EN); break; #endif -#if CONFIG_STM32_TIM8 +#ifdef CONFIG_STM32_TIM8 case 8: dev = (struct stm32_tim_dev_s *)&stm32_tim8_priv; modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM8EN); @@ -985,35 +985,35 @@ int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev) switch (((struct stm32_tim_priv_s *)dev)->base) { -#if CONFIG_STM32_TIM2 +#ifdef CONFIG_STM32_TIM2 case STM32_TIM2_BASE: modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM2EN, 0); break; #endif -#if CONFIG_STM32_TIM3 +#ifdef CONFIG_STM32_TIM3 case STM32_TIM3_BASE: modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM3EN, 0); break; #endif -#if CONFIG_STM32_TIM4 +#ifdef CONFIG_STM32_TIM4 case STM32_TIM4_BASE: modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM4EN, 0); break; #endif -#if CONFIG_STM32_TIM5 +#ifdef CONFIG_STM32_TIM5 case STM32_TIM5_BASE: modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM5EN, 0); break; #endif #if STM32_NBTIM > 0 -#if CONFIG_STM32_TIM6 +#ifdef CONFIG_STM32_TIM6 case STM32_TIM6_BASE: modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM6EN, 0); break; #endif #endif #if STM32_NBTIM > 1 -#if CONFIG_STM32_TIM7 +#ifdef CONFIG_STM32_TIM7 case STM32_TIM7_BASE: modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_TIM7EN, 0); break; @@ -1021,12 +1021,12 @@ int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev) #endif #if STM32_NATIM > 0 -#if CONFIG_STM32_TIM1 +#ifdef CONFIG_STM32_TIM1 case STM32_TIM1_BASE: modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM1EN, 0); break; #endif -#if CONFIG_STM32_TIM8 +#ifdef CONFIG_STM32_TIM8 case STM32_TIM8_BASE: modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM8EN, 0); break; diff --git a/arch/arm/src/stm32/stm32_timerisr.c b/arch/arm/src/stm32/stm32_timerisr.c index 52cc9823962..d7f3eafd2b8 100644 --- a/arch/arm/src/stm32/stm32_timerisr.c +++ b/arch/arm/src/stm32/stm32_timerisr.c @@ -71,7 +71,7 @@ #undef CONFIG_STM32_SYSTICK_HCLKd8 /* Power up default is HCLK, not HCLK/8 */ /* And I don't know now to re-configure it yet */ -#if CONFIG_STM32_SYSTICK_HCLKd8 +#ifdef CONFIG_STM32_SYSTICK_HCLKd8 # define SYSTICK_RELOAD ((STM32_HCLK_FREQUENCY / 8 / CLK_TCK) - 1) #else # define SYSTICK_RELOAD ((STM32_HCLK_FREQUENCY / CLK_TCK) - 1) @@ -138,7 +138,7 @@ void up_timer_initialize(void) #if 0 /* Does not work. Comes up with HCLK source and I can't change it */ regval = getreg32(NVIC_SYSTICK_CTRL); -#if CONFIG_STM32_SYSTICK_HCLKd8 +#ifdef CONFIG_STM32_SYSTICK_HCLKd8 regval &= ~NVIC_SYSTICK_CTRL_CLKSOURCE; #else regval |= NVIC_SYSTICK_CTRL_CLKSOURCE; diff --git a/arch/arm/src/stm32/stm32f42xxx_rcc.c b/arch/arm/src/stm32/stm32f42xxx_rcc.c index c28435842f3..b6082e44e74 100644 --- a/arch/arm/src/stm32/stm32f42xxx_rcc.c +++ b/arch/arm/src/stm32/stm32f42xxx_rcc.c @@ -672,21 +672,21 @@ static void stm32_stdclockconfig(void) /* Set the HCLK source/divider */ - regval = getreg32(STM32_RCC_CFGR); + regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_HPRE_MASK; regval |= STM32_RCC_CFGR_HPRE; putreg32(regval, STM32_RCC_CFGR); /* Set the PCLK2 divider */ - regval = getreg32(STM32_RCC_CFGR); + regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_PPRE2_MASK; regval |= STM32_RCC_CFGR_PPRE2; putreg32(regval, STM32_RCC_CFGR); /* Set the PCLK1 divider */ - regval = getreg32(STM32_RCC_CFGR); + regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_PPRE1_MASK; regval |= STM32_RCC_CFGR_PPRE1; putreg32(regval, STM32_RCC_CFGR); @@ -694,7 +694,7 @@ static void stm32_stdclockconfig(void) #ifdef CONFIG_RTC_HSECLOCK /* Set the RTC clock divisor */ - regval = getreg32(STM32_RCC_CFGR); + regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_RTCPRE_MASK; regval |= RCC_CFGR_RTCPRE(HSE_DIVISOR); putreg32(regval, STM32_RCC_CFGR); @@ -713,7 +713,7 @@ static void stm32_stdclockconfig(void) /* Enable the main PLL */ - regval = getreg32(STM32_RCC_CR); + regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_PLLON; putreg32(regval, STM32_RCC_CR); @@ -766,19 +766,19 @@ static void stm32_stdclockconfig(void) #ifdef CONFIG_STM32_LTDC /* Configure PLLSAI */ - regval = getreg32(STM32_RCC_PLLSAICFGR); + regval = getreg32(STM32_RCC_PLLSAICFGR); regval |= (STM32_RCC_PLLSAICFGR_PLLSAIN | STM32_RCC_PLLSAICFGR_PLLSAIR | STM32_RCC_PLLSAICFGR_PLLSAIQ); putreg32(regval, STM32_RCC_PLLSAICFGR); - regval = getreg32(STM32_RCC_DCKCFGR); + regval = getreg32(STM32_RCC_DCKCFGR); regval |= STM32_RCC_DCKCFGR_PLLSAIDIVR; putreg32(regval, STM32_RCC_DCKCFGR); /* Enable PLLSAI */ - regval = getreg32(STM32_RCC_CR); + regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_PLLSAION; putreg32(regval, STM32_RCC_CR); diff --git a/arch/arm/src/stm32/stm32f44xxx_rcc.c b/arch/arm/src/stm32/stm32f44xxx_rcc.c index d7962be922f..e0b396e9174 100644 --- a/arch/arm/src/stm32/stm32f44xxx_rcc.c +++ b/arch/arm/src/stm32/stm32f44xxx_rcc.c @@ -604,21 +604,21 @@ static void stm32_stdclockconfig(void) /* Set the HCLK source/divider */ - regval = getreg32(STM32_RCC_CFGR); + regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_HPRE_MASK; regval |= STM32_RCC_CFGR_HPRE; putreg32(regval, STM32_RCC_CFGR); /* Set the PCLK2 divider */ - regval = getreg32(STM32_RCC_CFGR); + regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_PPRE2_MASK; regval |= STM32_RCC_CFGR_PPRE2; putreg32(regval, STM32_RCC_CFGR); /* Set the PCLK1 divider */ - regval = getreg32(STM32_RCC_CFGR); + regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_PPRE1_MASK; regval |= STM32_RCC_CFGR_PPRE1; putreg32(regval, STM32_RCC_CFGR); @@ -626,7 +626,7 @@ static void stm32_stdclockconfig(void) #ifdef CONFIG_RTC_HSECLOCK /* Set the RTC clock divisor */ - regval = getreg32(STM32_RCC_CFGR); + regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_RTCPRE_MASK; regval |= RCC_CFGR_RTCPRE(HSE_DIVISOR); putreg32(regval, STM32_RCC_CFGR); @@ -645,7 +645,7 @@ static void stm32_stdclockconfig(void) /* Enable the main PLL */ - regval = getreg32(STM32_RCC_CR); + regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_PLLON; putreg32(regval, STM32_RCC_CR); @@ -664,7 +664,7 @@ static void stm32_stdclockconfig(void) { } - regval = getreg32(STM32_PWR_CR); + regval = getreg32(STM32_PWR_CR); regval |= PWR_CR_ODSWEN; putreg32(regval, STM32_PWR_CR); while ((getreg32(STM32_PWR_CSR) & PWR_CSR_ODSWRDY) == 0) @@ -693,18 +693,29 @@ static void stm32_stdclockconfig(void) { } -#ifdef CONFIG_STM32_USE_PLLSAI +#if defined(CONFIG_STM32_SAIPLL) /* Configure PLLSAI */ - regval = getreg32(STM32_RCC_PLLSAICFGR); + regval = getreg32(STM32_RCC_PLLSAICFGR); + regval &= ~(RCC_PLLSAICFGR_PLLSAIM_MASK | + RCC_PLLSAICFGR_PLLSAIN_MASK | + RCC_PLLSAICFGR_PLLSAIP_MASK | + RCC_PLLSAICFGR_PLLSAIQ_MASK); regval |= (STM32_RCC_PLLSAICFGR_PLLSAIM | STM32_RCC_PLLSAICFGR_PLLSAIN | STM32_RCC_PLLSAICFGR_PLLSAIP | STM32_RCC_PLLSAICFGR_PLLSAIQ); putreg32(regval, STM32_RCC_PLLSAICFGR); - regval = getreg32(STM32_RCC_DCKCFGR); + regval = getreg32(STM32_RCC_DCKCFGR); + regval &= ~(RCC_DCKCFGR_PLLI2SDIVQ_MASK | + RCC_DCKCFGR_PLLSAIDIVQ_MASK | + RCC_DCKCFGR_SAI1SRC_MASK | + RCC_DCKCFGR_SAI2SRC_MASK | + RCC_DCKCFGR_I2S1SRC_MASK | + RCC_DCKCFGR_I2S2SRC_MASK); + regval |= (STM32_RCC_DCKCFGR_PLLI2SDIVQ | STM32_RCC_DCKCFGR_PLLSAIDIVQ | STM32_RCC_DCKCFGR_SAI1SRC @@ -717,7 +728,7 @@ static void stm32_stdclockconfig(void) /* Enable PLLSAI */ - regval = getreg32(STM32_RCC_CR); + regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_PLLSAION; putreg32(regval, STM32_RCC_CR); @@ -728,11 +739,15 @@ static void stm32_stdclockconfig(void) } #endif -#ifdef CONFIG_STM32_USE_PLLI2S +#if defined(CONFIG_STM32_I2SPLL) /* Configure PLLI2S */ - regval = getreg32(STM32_RCC_PLLI2SCFGR); + regval = getreg32(STM32_RCC_PLLI2SCFGR); + regval &= ~(RCC_PLLI2SCFGR_PLLI2SM_MASK | + RCC_PLLI2SCFGR_PLLI2SN_MASK | + RCC_PLLI2SCFGR_PLLI2SP_MASK | + RCC_PLLI2SCFGR_PLLI2SQ_MASK); regval |= (STM32_RCC_PLLI2SCFGR_PLLI2SM | STM32_RCC_PLLI2SCFGR_PLLI2SN | STM32_RCC_PLLI2SCFGR_PLLI2SP @@ -740,7 +755,12 @@ static void stm32_stdclockconfig(void) | STM32_RCC_PLLI2SCFGR_PLLI2SR); putreg32(regval, STM32_RCC_PLLI2SCFGR); - regval = getreg32(STM32_RCC_DCKCFGR2); + regval = getreg32(STM32_RCC_DCKCFGR2); + regval &= ~(RCC_DCKCFGR2_FMPI2C1SEL_MASK | + RCC_DCKCFGR2_CECSEL_MASK | + RCC_DCKCFGR2_CK48MSEL_MASK | + RCC_DCKCFGR2_SDIOCSEL_MASK | + RCC_DCKCFGR2_SPDIFRXEL_MASK); regval |= (STM32_RCC_DCKCFGR2_FMPI2C1SEL | STM32_RCC_DCKCFGR2_CECSEL | STM32_RCC_DCKCFGR2_CK48MSEL @@ -751,7 +771,7 @@ static void stm32_stdclockconfig(void) /* Enable PLLI2S */ - regval = getreg32(STM32_RCC_CR); + regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_PLLI2SON; putreg32(regval, STM32_RCC_CR); @@ -762,8 +782,6 @@ static void stm32_stdclockconfig(void) } #endif - - #if defined(CONFIG_STM32_IWDG) || defined(CONFIG_RTC_LSICLOCK) /* Low speed internal clock source LSI */ diff --git a/arch/arm/src/stm32f7/Make.defs b/arch/arm/src/stm32f7/Make.defs index d6b4e369e23..1fa9d5de13e 100644 --- a/arch/arm/src/stm32f7/Make.defs +++ b/arch/arm/src/stm32f7/Make.defs @@ -77,6 +77,8 @@ ifeq ($(CONFIG_ARCH_FPU),y) CMN_ASRCS += up_fpu.S ifneq ($(CONFIG_ARMV7M_CMNVECTOR),y) CMN_CSRCS += up_copyarmstate.c +else ifeq ($(CONFIG_ARMV7M_LAZYFPU),y) +CMN_CSRCS += up_copyarmstate.c endif endif diff --git a/arch/arm/src/stm32f7/stm32_ethernet.c b/arch/arm/src/stm32f7/stm32_ethernet.c index a2ba9192512..5cd46247dcd 100644 --- a/arch/arm/src/stm32f7/stm32_ethernet.c +++ b/arch/arm/src/stm32f7/stm32_ethernet.c @@ -482,7 +482,7 @@ * checksum is OK the DMA can handle the frame otherwise the frame is dropped */ -#if CONFIG_STM32F7_ETH_HWCHECKSUM +#ifdef CONFIG_STM32F7_ETH_HWCHECKSUM # define DMAOMR_SET_MASK \ (ETH_DMAOMR_OSF | ETH_DMAOMR_RTC_64 | ETH_DMAOMR_TTC_64 | \ ETH_DMAOMR_TSF | ETH_DMAOMR_RSF) @@ -2042,7 +2042,7 @@ static void stm32_txdone(struct stm32_ethmac_s *priv) { DEBUGASSERT(priv->txtail != NULL); - /* Scan the TX desciptor change, returning buffers to free list */ + /* Scan the TX descriptor change, returning buffers to free list */ stm32_freeframe(priv); diff --git a/arch/arm/src/stm32f7/stm32_irq.c b/arch/arm/src/stm32f7/stm32_irq.c index 632fad2e2e9..59360736629 100644 --- a/arch/arm/src/stm32f7/stm32_irq.c +++ b/arch/arm/src/stm32f7/stm32_irq.c @@ -80,7 +80,16 @@ * Public Data ****************************************************************************/ +/* This is the address of current interrupt saved state data. Used for + * context switching. Only value during interrupt handling. + */ + volatile uint32_t *current_regs; + +/* This is the address of the exception vector table (determined by the + * linker script). + */ + extern uint32_t _vectors[]; /**************************************************************************** @@ -412,16 +421,21 @@ void up_irqinitialize(void) } #endif - /* Set up the vector table address. - * - * If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ -#if defined(CONFIG_ARCH_RAMVECTORS) up_ramvec_initialize(); -#elif defined(CONFIG_STM32F7_BOOTLOADER) - putreg32((uint32_t)_vectors, NVIC_VECTAB); #endif /* Set all interrupts (and exceptions) to the default priority */ diff --git a/arch/arm/src/stm32f7/stm32_lowputc.c b/arch/arm/src/stm32f7/stm32_lowputc.c index f23359ff8e7..a1c346cee28 100644 --- a/arch/arm/src/stm32f7/stm32_lowputc.c +++ b/arch/arm/src/stm32f7/stm32_lowputc.c @@ -338,7 +338,7 @@ void up_lowputc(char ch) /* Wait until the TX data register is empty */ while ((getreg32(STM32_CONSOLE_BASE + STM32_USART_ISR_OFFSET) & USART_ISR_TXE) == 0); -#if STM32_CONSOLE_RS485_DIR +#ifdef STM32_CONSOLE_RS485_DIR stm32_gpiowrite(STM32_CONSOLE_RS485_DIR, STM32_CONSOLE_RS485_DIR_POLARITY); #endif @@ -346,7 +346,7 @@ void up_lowputc(char ch) putreg32((uint32_t)ch, STM32_CONSOLE_BASE + STM32_USART_TDR_OFFSET); -#if STM32_CONSOLE_RS485_DIR +#ifdef STM32_CONSOLE_RS485_DIR while ((getreg32(STM32_CONSOLE_BASE + STM32_USART_ISR_OFFSET) & USART_ISR_TC) == 0); stm32_gpiowrite(STM32_CONSOLE_RS485_DIR, !STM32_CONSOLE_RS485_DIR_POLARITY); #endif @@ -389,7 +389,7 @@ void stm32_lowsetup(void) stm32_configgpio(STM32_CONSOLE_RX); #endif -#if STM32_CONSOLE_RS485_DIR +#ifdef STM32_CONSOLE_RS485_DIR stm32_configgpio(STM32_CONSOLE_RS485_DIR); stm32_gpiowrite(STM32_CONSOLE_RS485_DIR, !STM32_CONSOLE_RS485_DIR_POLARITY); #endif diff --git a/arch/arm/src/stm32f7/stm32_serial.c b/arch/arm/src/stm32f7/stm32_serial.c index fa3373df485..028e45cbe36 100644 --- a/arch/arm/src/stm32f7/stm32_serial.c +++ b/arch/arm/src/stm32f7/stm32_serial.c @@ -86,7 +86,7 @@ * have also been selected. */ -#if SERIAL_HAVE_DMA +#ifdef SERIAL_HAVE_DMA /* Verify that DMA has been enabled and the DMA channel has been defined. */ @@ -1400,7 +1400,7 @@ static int up_setup(struct uart_dev_s *dev) } #endif -#if HAVE_RS485 +#ifdef HAVE_RS485 if (priv->rs485_dir_gpio != 0) { stm32_configgpio(priv->rs485_dir_gpio); @@ -1603,7 +1603,7 @@ static void up_shutdown(struct uart_dev_s *dev) } #endif -#if HAVE_RS485 +#ifdef HAVE_RS485 if (priv->rs485_dir_gpio != 0) { stm32_unconfiggpio(priv->rs485_dir_gpio); @@ -2642,7 +2642,7 @@ static int up_pm_prepare(struct pm_callback_s *cb, enum pm_state_e pmstate) * ****************************************************************************/ -#if USE_EARLYSERIALINIT +#ifdef USE_EARLYSERIALINIT void up_earlyserialinit(void) { #ifdef HAVE_UART diff --git a/arch/arm/src/str71x/str71x_decodeirq.c b/arch/arm/src/str71x/str71x_decodeirq.c index fdc8c80517d..a87f5f059b3 100644 --- a/arch/arm/src/str71x/str71x_decodeirq.c +++ b/arch/arm/src/str71x/str71x_decodeirq.c @@ -132,7 +132,7 @@ void up_decodeirq(uint32_t *regs) current_regs = savestate; } -#if CONFIG_DEBUG +#ifdef CONFIG_DEBUG else { PANIC(); /* Normally never happens */ diff --git a/arch/arm/src/str71x/str71x_lowputc.c b/arch/arm/src/str71x/str71x_lowputc.c index 0055a352012..bf70f4730b3 100644 --- a/arch/arm/src/str71x/str71x_lowputc.c +++ b/arch/arm/src/str71x/str71x_lowputc.c @@ -78,7 +78,7 @@ * RX needs to be configured for input, tristate, cmos {0, 1, 0} */ -#if CONFIG_STR71X_UART0 +#ifdef CONFIG_STR71X_UART0 # define STR71X_UART0_GPIO0_MASK (0x0300) /* P0.8->U0.TX, B0.9->U0.RX */ # define STR71X_UART0_GPIO0_PC0BITS (0x0200) # define STR71X_UART0_GPIO0_PC1BITS (0x0300) @@ -90,7 +90,7 @@ # define STR71X_UART0_GPIO0_PC2BITS (0) #endif -#if CONFIG_STR71X_UART1 +#ifdef CONFIG_STR71X_UART1 # define STR71X_UART1_GPIO0_MASK (0x0c00) /* P0,10->U1.RX, P0.11->U1.TX */ # define STR71X_UART1_GPIO0_PC0BITS (0x0800) # define STR71X_UART1_GPIO0_PC1BITS (0x0c00) @@ -102,7 +102,7 @@ # define STR71X_UART1_GPIO0_PC2BITS (0) #endif -#if CONFIG_STR71X_UART2 +#ifdef CONFIG_STR71X_UART2 # define STR71X_UART2_GPIO0_MASK (0x6000) /* P0.13->U2.RX, P0.14>U2.TX */ # define STR71X_UART2_GPIO0_PC0BITS (0x4000) # define STR71X_UART2_GPIO0_PC1BITS (0x6000) @@ -114,7 +114,7 @@ # define STR71X_UART2_GPIO0_PC2BITS (0) #endif -#if CONFIG_STR71X_UART3 +#ifdef CONFIG_STR71X_UART3 # define STR71X_UART3_GPIO0_MASK (0x0003) /* P0.0->U3.TX, P0.1->U3.RX */ # define STR71X_UART3_GPIO0_PC0BITS (0x0001) # define STR71X_UART3_GPIO0_PC1BITS (0x0003) @@ -298,7 +298,7 @@ void up_lowsetup(void) * (the serial driver later depends on this configuration) */ -#if HAVE_UART +#ifdef HAVE_UART reg16 = getreg16(STR71X_GPIO0_PC0); reg16 &= ~STR71X_UART_GPIO0_MASK; reg16 |= STR71X_UART_GPIO0_PC0BITS; diff --git a/arch/arm/src/tiva/tiva_adc.h b/arch/arm/src/tiva/tiva_adc.h index 3b9f6feaccc..c6fc9ac2e07 100644 --- a/arch/arm/src/tiva/tiva_adc.h +++ b/arch/arm/src/tiva/tiva_adc.h @@ -61,7 +61,7 @@ #ifdef CONFIG_ARCH_CHIP_TM4C123 # define TIVA_ADC_CLOCK_MAX (16000000) # define TIVA_ADC_CLOCK_MIN (16000000) -#elif CONFIG_ARCH_CHIP_TM4C129 +#elif defined(CONFIG_ARCH_CHIP_TM4C129) # define TIVA_ADC_CLOCK_MAX (32000000) # define TIVA_ADC_CLOCK_MIN (16000000) #else @@ -75,7 +75,7 @@ # define TIVA_ADC_SAMPLE_RATE_SLOW (ADC_PC_SR_250K) # define TIVA_ADC_SAMPLE_RATE_FAST (ADC_PC_SR_500K) # define TIVA_ADC_SAMPLE_RATE_FASTEST (ADC_PC_SR_1M) -#elif CONFIG_ARCH_CHIP_TM4C129 +#elif defined(CONFIG_ARCH_CHIP_TM4C129) # define TIVA_ADC_SAMPLE_RATE_SLOWEST (ADC_PC_MCR_1_8) # define TIVA_ADC_SAMPLE_RATE_SLOW (ADC_PC_MCR_1_4) # define TIVA_ADC_SAMPLE_RATE_FAST (ADC_PC_MCR_1_2) diff --git a/arch/arm/src/tiva/tiva_irq.c b/arch/arm/src/tiva/tiva_irq.c index c2fc896e436..c9c9e15127d 100644 --- a/arch/arm/src/tiva/tiva_irq.c +++ b/arch/arm/src/tiva/tiva_irq.c @@ -77,8 +77,18 @@ * Public Data ****************************************************************************/ +/* This is the address of current interrupt saved state data. Used for + * context switching. Only value during interrupt handling. + */ + volatile uint32_t *current_regs; +/* This is the address of the exception vector table (determined by the + * linker script). + */ + +extern uint32_t _vectors[]; + /**************************************************************************** * Private Data ****************************************************************************/ @@ -380,11 +390,20 @@ void up_irqinitialize(void) putreg32(0, regaddr); } + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ -#ifdef CONFIG_ARCH_RAMVECTORS up_ramvec_initialize(); #endif @@ -392,7 +411,6 @@ void up_irqinitialize(void) putreg32((uint32_t)CONFIG_RAM_START, NVIC_VECTAB); #endif - /* Set all interrupts (and exceptions) to the default priority */ putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); diff --git a/arch/arm/src/tiva/tm4c_ethernet.c b/arch/arm/src/tiva/tm4c_ethernet.c index e613b47dd0b..0c259e1497e 100644 --- a/arch/arm/src/tiva/tm4c_ethernet.c +++ b/arch/arm/src/tiva/tm4c_ethernet.c @@ -479,7 +479,7 @@ * checksum is OK the DMA can handle the frame otherwise the frame is dropped */ -#if CONFIG_TIVA_EMAC_HWCHECKSUM +#ifdef CONFIG_TIVA_EMAC_HWCHECKSUM # define DMAOPMODE_SET_MASK \ (EMAC_DMAOPMODE_OSF | EMAC_DMAOPMODE_RTC_64 | EMAC_DMAOPMODE_TTC_64 | \ EMAC_DMAOPMODE_TSF | EMAC_DMAOPMODE_RSF) @@ -748,7 +748,7 @@ static void tiva_rxdescinit(FAR struct tiva_ethmac_s *priv); /* PHY Initialization */ -#if CONFIG_TIVA_PHY_INTERRUPTS +#ifdef CONFIG_TIVA_PHY_INTERRUPTS static void tiva_phy_intenable(bool enable); #endif static int tiva_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value); diff --git a/arch/avr/src/at32uc3/at32uc3_clkinit.c b/arch/avr/src/at32uc3/at32uc3_clkinit.c index c8e2eb1bf36..38ffebd3335 100644 --- a/arch/avr/src/at32uc3/at32uc3_clkinit.c +++ b/arch/avr/src/at32uc3/at32uc3_clkinit.c @@ -230,7 +230,7 @@ static inline void up_enablepll0(void) /* Select PLL0/1 oscillator */ -#if AVR32_CLOCK_PLL_OSC1 +#ifdef AVR32_CLOCK_PLL0_OSC1 regval |= PM_PLL_PLLOSC; #endif @@ -280,7 +280,7 @@ static inline void up_enablepll1(void) /* Select PLL0/1 oscillator */ -#if AVR32_CLOCK_PLL_OSC1 +#ifdef AVR32_CLOCK_PLL1_OSC1 regval |= PM_PLL_PLLOSC; #endif diff --git a/arch/avr/src/at32uc3/at32uc3_ssc.h b/arch/avr/src/at32uc3/at32uc3_ssc.h index 35b286b6aed..e5c1df3c624 100644 --- a/arch/avr/src/at32uc3/at32uc3_ssc.h +++ b/arch/avr/src/at32uc3/at32uc3_ssc.h @@ -114,7 +114,7 @@ #define SSC_RCMR_CKI (1 << 5) /* Bit 5: Receive Clock Inversion */ #define SSC_RCMR_CKG_SHIFT (6) /* Bits 6-7: Receive Clock Gating Selection */ #define SSC_RCMR_CKG_MASK (3 << SSC_RCMR_CKG_SHIFT) -# define SSC_RCMR_CKG_NONE (0 << SSC_RCMR_CKG_SHIFT) /* None, continous clock */ +# define SSC_RCMR_CKG_NONE (0 << SSC_RCMR_CKG_SHIFT) /* None, continuous clock */ # define SSC_RCMR_CKG_LOW (1 << SSC_RCMR_CKG_SHIFT) /* Enable if RX_FRAME_SYNC low */ # define SSC_RCMR_CKG_HIGH (2 << SSC_RCMR_CKG_SHIFT) /* Enable if RX_FRAME_SYNC high */ #define SSC_RCMR_START_SHIFT (8) /* Bits 8-11: Receive Start Selection */ @@ -171,7 +171,7 @@ #define SSC_TCMR_CKI (1 << 5) /* Bit 5: Transmit Clock Inversion */ #define SSC_TCMR_CKG_SHIFT (6) /* Bits 6-7: Transmit Clock Gating Selection */ #define SSC_TCMR_CKG_MASK (3 << SSC_TCMR_CKG_SHIFT) -# define SSC_TCMR_CKG_NONE (0 << SSC_TCMR_CKG_SHIFT) /* None, continous clock */ +# define SSC_TCMR_CKG_NONE (0 << SSC_TCMR_CKG_SHIFT) /* None, continuous clock */ # define SSC_TCMR_CKG_LOW (1 << SSC_TCMR_CKG_SHIFT) /* Enable if TX_FRAME_SYNC low */ # define SSC_TCMR_CKG_HIGH (2 << SSC_TCMR_CKG_SHIFT) /* Enable if TX_FRAME_SYNC high */ #define SSC_TCMR_START_SHIFT (8) /* Bits 8-11: Transmit Start Selection */ diff --git a/arch/avr/src/at32uc3/chip.h b/arch/avr/src/at32uc3/chip.h index 42b3ea681dc..99fad31eb9c 100644 --- a/arch/avr/src/at32uc3/chip.h +++ b/arch/avr/src/at32uc3/chip.h @@ -53,7 +53,7 @@ /* UC3 B0 (64-pin) / B1 (48-pin, no USB host) Series */ -#if CONFIG_ARCH_CHIP_AT32UC3B064 +#ifdef CONFIG_ARCH_CHIP_AT32UC3B064 # define CONFIG_ARCH_CHIP_AT32UC3B 1 /* UC3 B series */ # define CONFIG_ARCH_CHIP_AT32UC3B0 1 /* UC3 B0 (64-pin) series */ # define AVR32_ONCHIP_FLASH_SIZE (64*1024) /* Size of on-chip FLASH (bytes) */ @@ -71,7 +71,7 @@ # define AVR32_NOSC 2 /* Number of crystal oscillators */ # define AVR32_NADC10 8 /* Number of 10-bit A/D channels */ # define AVR32_NDMAC 7 /* Number of DMA channels */ -#elif CONFIG_ARCH_CHIP_AT32UC3B0128 +#elif defined(CONFIG_ARCH_CHIP_AT32UC3B0128) # define CONFIG_ARCH_CHIP_AT32UC3B 1 /* UC3 B series */ # define CONFIG_ARCH_CHIP_AT32UC3B0 1 /* UC3 B0 (64-pin) series */ # define AVR32_ONCHIP_FLASH_SIZE (128*1024) /* Size of on-chip FLASH (bytes) */ @@ -89,7 +89,7 @@ # define AVR32_NOSC 2 /* Number of crystal oscillators */ # define AVR32_NADC10 8 /* Number of 10-bit A/D channels */ # define AVR32_NDMAC 7 /* Number of DMA channels */ -#elif CONFIG_ARCH_CHIP_AT32UC3B0256 +#elif defined(CONFIG_ARCH_CHIP_AT32UC3B0256) # define CONFIG_ARCH_CHIP_AT32UC3B 1 /* UC3 B series */ # define CONFIG_ARCH_CHIP_AT32UC3B0 1 /* UC3 B0 (64-pin) series */ # define AVR32_ONCHIP_FLASH_SIZE (256*1024) /* Size of on-chip FLASH (bytes) */ @@ -107,7 +107,7 @@ # define AVR32_NOSC 2 /* Number of crystal oscillators */ # define AVR32_NADC10 8 /* Number of 10-bit A/D channels */ # define AVR32_NDMAC 7 /* Number of DMA channels */ -#elif CONFIG_ARCH_CHIP_AT32UC3B0512 +#elif defined(CONFIG_ARCH_CHIP_AT32UC3B0512) # define CONFIG_ARCH_CHIP_AT32UC3B 1 /* UC3 B series */ # define CONFIG_ARCH_CHIP_AT32UC3B0 1 /* UC3 B0 (64-pin) series */ # define AVR32_ONCHIP_FLASH_SIZE (512*1024) /* Size of on-chip FLASH (bytes) */ @@ -125,7 +125,7 @@ # define AVR32_NOSC 2 /* Number of crystal oscillators */ # define AVR32_NADC10 8 /* Number of 10-bit A/D channels */ # define AVR32_NDMAC 7 /* Number of DMA channels */ -#elif CONFIG_ARCH_CHIP_AT32UC3B164 +#elif defined(CONFIG_ARCH_CHIP_AT32UC3B164) # define CONFIG_ARCH_CHIP_AT32UC3B 1 /* UC3 B series */ # define CONFIG_ARCH_CHIP_AT32UC3B1 1 /* UC3 B0 (48-pin) series */ # define AVR32_ONCHIP_FLASH_SIZE (64*1024) /* Size of on-chip FLASH (bytes) */ @@ -143,7 +143,7 @@ # define AVR32_NOSC 1 /* Number of crystal oscillators */ # define AVR32_NADC10 6 /* Number of 10-bit A/D channels */ # define AVR32_NDMAC 7 /* Number of DMA channels */ -#elif CONFIG_ARCH_CHIP_AT32UC3B1128 +#elif defined(CONFIG_ARCH_CHIP_AT32UC3B1128) # define CONFIG_ARCH_CHIP_AT32UC3B 1 /* UC3 B series */ # define CONFIG_ARCH_CHIP_AT32UC3B1 1 /* UC3 B0 (48-pin) series */ # define AVR32_ONCHIP_FLASH_SIZE (128*1024) /* Size of on-chip FLASH (bytes) */ @@ -161,7 +161,7 @@ # define AVR32_NOSC 1 /* Number of crystal oscillators */ # define AVR32_NADC10 6 /* Number of 10-bit A/D channels */ # define AVR32_NDMAC 7 /* Number of DMA channels */ -#elif CONFIG_ARCH_CHIP_AT32UC3B1256 +#elif defined(CONFIG_ARCH_CHIP_AT32UC3B1256) # define CONFIG_ARCH_CHIP_AT32UC3B 1 /* UC3 B series */ # define CONFIG_ARCH_CHIP_AT32UC3B1 1 /* UC3 B0 (48-pin) series */ # define AVR32_ONCHIP_FLASH_SIZE (256*1024) /* Size of on-chip FLASH (bytes) */ @@ -179,7 +179,7 @@ # define AVR32_NOSC 1 /* Number of crystal oscillators */ # define AVR32_NADC10 6 /* Number of 10-bit A/D channels */ # define AVR32_NDMAC 7 /* Number of DMA channels */ -#elif CONFIG_ARCH_CHIP_AT32UC3B1512 +#elif defined(CONFIG_ARCH_CHIP_AT32UC3B1512) # define CONFIG_ARCH_CHIP_AT32UC3B 1 /* UC3 B series */ # define CONFIG_ARCH_CHIP_AT32UC3B1 1 /* UC3 B0 (48-pin) series */ # define AVR32_ONCHIP_FLASH_SIZE (512*1024) /* Size of on-chip FLASH (bytes) */ diff --git a/arch/avr/src/common/up_initialize.c b/arch/avr/src/common/up_initialize.c index 5fb247847c1..0e8499c99d0 100644 --- a/arch/avr/src/common/up_initialize.c +++ b/arch/avr/src/common/up_initialize.c @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -268,6 +269,12 @@ void up_initialize(void) up_netinitialize(); #endif +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + /* Initialize USB */ up_usbinitialize(); diff --git a/arch/hc/src/common/up_initialize.c b/arch/hc/src/common/up_initialize.c index f22be91528a..2e947c3ef79 100644 --- a/arch/hc/src/common/up_initialize.c +++ b/arch/hc/src/common/up_initialize.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -192,6 +193,12 @@ void up_initialize(void) up_netinitialize(); #endif +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + /* Initialize USB */ up_usbinitialize(); diff --git a/arch/mips/src/common/up_initialize.c b/arch/mips/src/common/up_initialize.c index cfe893e7959..c06b01e9908 100644 --- a/arch/mips/src/common/up_initialize.c +++ b/arch/mips/src/common/up_initialize.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -194,6 +195,12 @@ void up_initialize(void) up_netinitialize(); #endif +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + /* Initialize USB -- device and/or host */ up_usbinitialize(); diff --git a/arch/mips/src/mips32/up_vfork.c b/arch/mips/src/mips32/up_vfork.c index 948abefb375..f31b7081daa 100644 --- a/arch/mips/src/mips32/up_vfork.c +++ b/arch/mips/src/mips32/up_vfork.c @@ -117,7 +117,7 @@ pid_t up_vfork(const struct vfork_s *context) struct task_tcb_s *child; size_t stacksize; uint32_t newsp; -#if CONFIG_MIPS32_FRAMEPOINTER +#ifdef CONFIG_MIPS32_FRAMEPOINTER uint32_t newfp; #endif uint32_t stackutil; @@ -125,7 +125,7 @@ pid_t up_vfork(const struct vfork_s *context) svdbg("s0:%08x s1:%08x s2:%08x s3:%08x s4:%08x\n", context->s0, context->s1, context->s2, context->s3, context->s4); -#if CONFIG_MIPS32_FRAMEPOINTER +#ifdef CONFIG_MIPS32_FRAMEPOINTER svdbg("s5:%08x s6:%08x s7:%08x\n", context->s5, context->s6, context->s7); #ifdef MIPS32_SAVE_GP @@ -199,7 +199,7 @@ pid_t up_vfork(const struct vfork_s *context) /* Was there a frame pointer in place before? */ -#if CONFIG_MIPS32_FRAMEPOINTER +#ifdef CONFIG_MIPS32_FRAMEPOINTER if (context->fp <= (uint32_t)parent->adj_stack_ptr && context->fp >= (uint32_t)parent->adj_stack_ptr - stacksize) { @@ -237,13 +237,13 @@ pid_t up_vfork(const struct vfork_s *context) child->cmn.xcp.regs[REG_S5] = context->s5; /* Volatile register s5 */ child->cmn.xcp.regs[REG_S6] = context->s6; /* Volatile register s6 */ child->cmn.xcp.regs[REG_S7] = context->s7; /* Volatile register s7 */ -#if CONFIG_MIPS32_FRAMEPOINTER +#ifdef CONFIG_MIPS32_FRAMEPOINTER child->cmn.xcp.regs[REG_FP] = newfp; /* Frame pointer */ #else child->cmn.xcp.regs[REG_S8] = context->s8; /* Volatile register s8 */ #endif child->cmn.xcp.regs[REG_SP] = newsp; /* Stack pointer */ -#if MIPS32_SAVE_GP +#ifdef MIPS32_SAVE_GP child->cmn.xcp.regs[REG_GP] = newsp; /* Global pointer */ #endif diff --git a/arch/mips/src/pic32mx/pic32mx-ethernet.c b/arch/mips/src/pic32mx/pic32mx-ethernet.c index 1b9c575045e..32120fba1ab 100644 --- a/arch/mips/src/pic32mx/pic32mx-ethernet.c +++ b/arch/mips/src/pic32mx/pic32mx-ethernet.c @@ -1005,7 +1005,7 @@ static struct pic32mx_rxdesc_s *pic32mx_rxdesc(struct pic32mx_driver_s *priv) rxdesc = &priv->pd_rxdesc[i]; if ((rxdesc->status & RXDESC_STATUS_EOWN) == 0) { - /* Yes.. return a pointer to the desciptor */ + /* Yes.. return a pointer to the descriptor */ return rxdesc; } diff --git a/arch/mips/src/pic32mx/pic32mx-usbdev.c b/arch/mips/src/pic32mx/pic32mx-usbdev.c index c9d6c0e9d36..cc05aef6e91 100644 --- a/arch/mips/src/pic32mx/pic32mx-usbdev.c +++ b/arch/mips/src/pic32mx/pic32mx-usbdev.c @@ -2876,7 +2876,7 @@ static int pic32mx_interrupt(int irq, void *context) usbtrace(TRACE_INTDECODE(PIC32MX_TRACEINTID_TRNCS), regval); - /* Handle the endpoint tranfer complete event. */ + /* Handle the endpoint transfer complete event. */ epno = (regval & USB_STAT_ENDPT_MASK) >> USB_STAT_ENDPT_SHIFT; if (epno == 0) diff --git a/arch/mips/src/pic32mz/pic32mz-config.h b/arch/mips/src/pic32mz/pic32mz-config.h index e14effece86..af150d4979e 100644 --- a/arch/mips/src/pic32mz/pic32mz-config.h +++ b/arch/mips/src/pic32mz/pic32mz-config.h @@ -472,7 +472,7 @@ #endif #undef CONFIG_PIC32MZ_FWDTEN -#if CONFIG_PIC32MZ_WDTENABLE +#ifdef CONFIG_PIC32MZ_WDTENABLE # define CONFIG_PIC32MZ_FWDTEN DEVCFG1_FWDT_ENSABLED #else # define CONFIG_PIC32MZ_FWDTEN DEVCFG1_FWDT_DISABLED diff --git a/arch/mips/src/pic32mz/pic32mz-ethernet.c b/arch/mips/src/pic32mz/pic32mz-ethernet.c index e33c063078c..7a0e65f0975 100644 --- a/arch/mips/src/pic32mz/pic32mz-ethernet.c +++ b/arch/mips/src/pic32mz/pic32mz-ethernet.c @@ -1023,7 +1023,7 @@ static struct pic32mz_rxdesc_s *pic32mz_rxdesc(struct pic32mz_driver_s *priv) rxdesc = &priv->pd_rxdesc[i]; if ((rxdesc->status & RXDESC_STATUS_EOWN) == 0) { - /* Yes.. return a pointer to the desciptor */ + /* Yes.. return a pointer to the descriptor */ return rxdesc; } diff --git a/arch/rgmp/include/math.h b/arch/rgmp/include/math.h index 790acab6285..e042ba4a3c5 100644 --- a/arch/rgmp/include/math.h +++ b/arch/rgmp/include/math.h @@ -65,7 +65,7 @@ extern "C" /* General Functions ********************************************************/ float ceilf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double ceil (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -73,7 +73,7 @@ long double ceill (long double x); #endif float floorf(float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double floor (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -81,7 +81,7 @@ long double floorl(long double x); #endif float fabsf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double fabs (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -89,7 +89,7 @@ long double fabsl (long double x); #endif float modff (float x, float *iptr); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double modf (double x, double *iptr); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -97,7 +97,7 @@ long double modfl (long double x, long double *iptr); #endif float fmodf (float x, float div); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double fmod (double x, double div); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -107,7 +107,7 @@ long double fmodl (long double x, long double div); /* Exponential and Logarithmic Functions ************************************/ float powf (float b, float e); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double pow (double b, double e); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -115,7 +115,7 @@ long double powl (long double b, long double e); #endif float expf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double exp (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -123,7 +123,7 @@ long double expl (long double x); #endif float logf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double log (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -131,7 +131,7 @@ long double logl (long double x); #endif float log10f(float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double log10 (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -139,7 +139,7 @@ long double log10l(long double x); #endif float log2f (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double log2 (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -147,7 +147,7 @@ long double log2l (long double x); #endif float sqrtf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double sqrt (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -155,7 +155,7 @@ long double sqrtl (long double x); #endif float ldexpf(float x, int n); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE double ldexp (double x, int n); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -163,7 +163,7 @@ long double ldexpl(long double x, int n); #endif float frexpf(float x, int *exp); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE double frexp (double x, int *exp); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -173,7 +173,7 @@ long double frexpl(long double x, int *exp); /* Trigonometric Functions **************************************************/ float sinf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double sin (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -181,7 +181,7 @@ long double sinl (long double x); #endif float cosf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double cos (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -189,7 +189,7 @@ long double cosl (long double x); #endif float tanf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double tan (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -197,7 +197,7 @@ long double tanl (long double x); #endif float asinf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double asin (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -205,7 +205,7 @@ long double asinl (long double x); #endif float acosf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double acos (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -213,7 +213,7 @@ long double acosl (long double x); #endif float atanf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double atan (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -221,7 +221,7 @@ long double atanl (long double x); #endif float atan2f(float y, float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double atan2 (double y, double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -229,7 +229,7 @@ long double atan2l(long double y, long double x); #endif float sinhf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double sinh (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -237,7 +237,7 @@ long double sinhl (long double x); #endif float coshf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double cosh (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE @@ -245,7 +245,7 @@ long double coshl (long double x); #endif float tanhf (float x); -#if CONFIG_HAVE_DOUBLE +#ifdef CONFIG_HAVE_DOUBLE //double tanh (double x); #endif #ifdef CONFIG_HAVE_LONG_DOUBLE diff --git a/arch/sh/src/common/up_initialize.c b/arch/sh/src/common/up_initialize.c index e7f0fbd5957..0224bce01c3 100644 --- a/arch/sh/src/common/up_initialize.c +++ b/arch/sh/src/common/up_initialize.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -182,6 +183,12 @@ void up_initialize(void) up_netinitialize(); #endif +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + /* Initialize USB */ up_usbinitialize(); diff --git a/arch/sim/src/up_appinit.c b/arch/sim/src/up_appinit.c index 606186fe88f..ddaf0886395 100644 --- a/arch/sim/src/up_appinit.c +++ b/arch/sim/src/up_appinit.c @@ -38,6 +38,9 @@ ***************************************************************************/ #include + +#include + #include /*************************************************************************** diff --git a/arch/sim/src/up_initialize.c b/arch/sim/src/up_initialize.c index d61e84aa23c..24aaa49dbd3 100644 --- a/arch/sim/src/up_initialize.c +++ b/arch/sim/src/up_initialize.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -165,6 +166,12 @@ void up_initialize(void) netdriver_init(); /* Our "real" network driver */ #endif +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + #if defined(CONFIG_FS_SMARTFS) && defined(CONFIG_SIM_SPIFLASH) up_init_smartfs(); #endif diff --git a/arch/sim/src/up_internal.h b/arch/sim/src/up_internal.h index 257efa8d5a7..5feb7868d08 100644 --- a/arch/sim/src/up_internal.h +++ b/arch/sim/src/up_internal.h @@ -159,7 +159,7 @@ /* Simulated Heap Definitions **********************************************/ /* Size of the simulated heap */ -#if CONFIG_MM_SMALL +#ifdef CONFIG_MM_SMALL # define SIM_HEAP_SIZE (64*1024) #else # define SIM_HEAP_SIZE (4*1024*1024) @@ -280,7 +280,7 @@ int sim_ajoy_initialize(void); /* up_tapdev.c ************************************************************/ -#if defined(CONFIG_NET) && !defined(__CYGWIN__) +#if defined(CONFIG_NET_ETHERNET) && !defined(__CYGWIN__) void tapdev_init(void); unsigned int tapdev_read(unsigned char *buf, unsigned int buflen); void tapdev_send(unsigned char *buf, unsigned int buflen); @@ -292,7 +292,7 @@ void tapdev_send(unsigned char *buf, unsigned int buflen); /* up_wpcap.c *************************************************************/ -#if defined(CONFIG_NET) && defined(__CYGWIN__) +#if defined(CONFIG_NET_ETHERNET) && defined(__CYGWIN__) void wpcap_init(void); unsigned int wpcap_read(unsigned char *buf, unsigned int buflen); void wpcap_send(unsigned char *buf, unsigned int buflen); @@ -304,7 +304,7 @@ void wpcap_send(unsigned char *buf, unsigned int buflen); /* up_netdriver.c *********************************************************/ -#ifdef CONFIG_NET +#ifdef CONFIG_NET_ETHERNET int netdriver_init(void); int netdriver_setmacaddr(unsigned char *macaddr); void netdriver_loop(void); diff --git a/arch/sim/src/up_netdriver.c b/arch/sim/src/up_netdriver.c index a710a38319f..43368f3fe61 100644 --- a/arch/sim/src/up_netdriver.c +++ b/arch/sim/src/up_netdriver.c @@ -44,7 +44,7 @@ #include -#ifdef CONFIG_NET +#ifdef CONFIG_NET_ETHERNET #include #include @@ -325,5 +325,5 @@ int netdriver_setmacaddr(unsigned char *macaddr) return 0; } -#endif /* CONFIG_NET */ +#endif /* CONFIG_NET_ETHERNET */ diff --git a/arch/x86/src/common/up_initialize.c b/arch/x86/src/common/up_initialize.c index 9356dd8cd1d..76f1621c5d8 100644 --- a/arch/x86/src/common/up_initialize.c +++ b/arch/x86/src/common/up_initialize.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -194,6 +195,12 @@ void up_initialize(void) up_netinitialize(); #endif +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + /* Initialize USB -- device and/or host */ up_usbinitialize(); diff --git a/arch/z16/src/common/up_initialize.c b/arch/z16/src/common/up_initialize.c index e906731d954..9a7710755da 100644 --- a/arch/z16/src/common/up_initialize.c +++ b/arch/z16/src/common/up_initialize.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -198,5 +199,11 @@ void up_initialize(void) up_netinitialize(); #endif +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + board_led_on(LED_IRQSENABLED); } diff --git a/arch/z80/src/common/up_initialize.c b/arch/z80/src/common/up_initialize.c index a71a256626e..7f0fdc68a0f 100644 --- a/arch/z80/src/common/up_initialize.c +++ b/arch/z80/src/common/up_initialize.c @@ -44,6 +44,7 @@ #include #include #include +#include #include @@ -139,7 +140,7 @@ void up_initialize(void) * needs to be done before any tasks are created). */ -#if CONFIG_ARCH_ADDRENV +#ifdef CONFIG_ARCH_ADDRENV (void)up_mmuinit(); #endif @@ -181,5 +182,11 @@ void up_initialize(void) up_netinitialize(); #endif +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + board_led_on(LED_IRQSENABLED); } diff --git a/arch/z80/src/common/up_internal.h b/arch/z80/src/common/up_internal.h index 746b4d32fa5..819dd3c4c8d 100644 --- a/arch/z80/src/common/up_internal.h +++ b/arch/z80/src/common/up_internal.h @@ -145,7 +145,7 @@ void up_sigdeliver(void); /* Defined in CPU-specific logic (only for Z180) */ -#if CONFIG_ARCH_ADDRENV +#ifdef CONFIG_ARCH_ADDRENV int up_mmuinit(void); #endif