diff --git a/arch/arm/src/nrf52/Kconfig b/arch/arm/src/nrf52/Kconfig index 9d1bd2c35d..002a31b8f4 100644 --- a/arch/arm/src/nrf52/Kconfig +++ b/arch/arm/src/nrf52/Kconfig @@ -109,14 +109,6 @@ config NRF52_RTC bool default n -config NRF52_SPI_MASTER_WORKAROUND_1BYTE_TRANSFER - bool "SPI Master 1 Byte transfer anomaly workaround" - depends on NRF52_SPI_MASTER && ARCH_CHIP_NRF52832 - default y - ---help--- - Enable the workaround to fix SPI Master 1 byte transfer bug - which occurs in NRF52832 revision 1 and revision 2. - menu "NRF52 Peripheral Selection" config NRF52_I2C0_MASTER @@ -598,3 +590,14 @@ config NRF52_SAADC_LIMITS endif # NRF52_SAADC endmenu # SAADC Configuration + +menu "SPI Configuration" + +config NRF52_SPI_MASTER_WORKAROUND_1BYTE_TRANSFER + bool "Master 1 Byte transfer anomaly workaround" + depends on NRF52_SPI_MASTER && ARCH_CHIP_NRF52832 + default y + ---help--- + Enable the workaround to fix SPI Master 1 byte transfer bug + which occurs in NRF52832 revision 1 and revision 2. +endmenu diff --git a/arch/arm/src/nrf52/hardware/nrf52_spi.h b/arch/arm/src/nrf52/hardware/nrf52_spi.h index 47d7e5dda2..9a983612e7 100644 --- a/arch/arm/src/nrf52/hardware/nrf52_spi.h +++ b/arch/arm/src/nrf52/hardware/nrf52_spi.h @@ -153,41 +153,14 @@ #define SPIM_ENABLE_DIS (0) /* Disable SPIM */ #define SPIM_ENABLE_EN (0x7 << 0) /* Enable SPIM */ -/* PSELSCK Register */ +/* PSEL(MOSI/MISO/SCK/CSN) Register */ -#define SPIM_PSELSCK_PIN_SHIFT (0) /* Bits 0-4: SCK pin number */ -#define SPIM_PSELSCK_PIN_MASK (0x1f << SPIM_PSELSCK_PIN_SHIFT) -#define SPIM_PSELSCK_PORT_SHIFT (5) /* Bit 5: SCK port number */ -#define SPIM_PSELSCK_PORT_MASK (0x1 << SPIM_PSELSCK_PORT_SHIFT) -#define SPIM_PSELSCK_CONNECTED (1 << 31) /* Bit 31: Connection */ -#define SPIM_PSELSCK_RESET (0xffffffff) - -/* PSELMOSI Register */ - -#define SPIM_PSELMOSI_PIN_SHIFT (0) /* Bits 0-4: MOSI pin number */ -#define SPIM_PSELMOSI_PIN_MASK (0x1f << SPIM_PSELMOSI_PIN_SHIFT) -#define SPIM_PSELMOSI_PORT_SHIFT (5) /* Bit 5: MOSI port number */ -#define SPIM_PSELMOSI_PORT_MASK (0x1 << SPIM_PSELMOSI_PORT_SHIFT) -#define SPIM_PSELMOSI_CONNECTED (1 << 31) /* Bit 31: Connection */ -#define SPIM_PSELMOSI_RESET (0xffffffff) - -/* PSELMISO Register */ - -#define SPIM_PSELMISO_PIN_SHIFT (0) /* Bits 0-4: MISO pin number */ -#define SPIM_PSELMISO_PIN_MASK (0x1f << SPIM_PSELMISO_PIN_SHIFT) -#define SPIM_PSELMISO_PORT_SHIFT (5) /* Bit 5: MISO port number */ -#define SPIM_PSELMISO_PORT_MASK (0x1 << SPIM_PSELMISO_PORT_SHIFT) -#define SPIM_PSELMISO_CONNECTED (1 << 31) /* Bit 31: Connection */ -#define SPIM_PSELMISO_RESET (0xffffffff) - -/* PSELCSN Register */ - -#define SPIM_PSELCSN_PIN_SHIFT (0) /* Bits 0-4: CSN pin number */ -#define SPIM_PSELCSN_PIN_MASK (0x1f << SPIM_PSELCSN_PIN_SHIFT) -#define SPIM_PSELCSN_PORT_SHIFT (5) /* Bit 5: CSN port number */ -#define SPIM_PSELCSN_PORT_MASK (0x1 << SPIM_PSELCSN_PORT_SHIFT) -#define SPIM_PSELCSN_CONNECTED (1 << 31) /* Bit 31: Connection */ -#define SPIM_PSELCSN_RESET (0xffffffff) +#define SPIM_PSEL_PIN_SHIFT (0) /* Bits 0-4: pin number */ +#define SPIM_PSEL_PIN_MASK (0x1f << SPIM_PSEL_PIN_SHIFT) +#define SPIM_PSEL_PORT_SHIFT (5) /* Bit 5: port number */ +#define SPIM_PSEL_PORT_MASK (0x1 << SPIM_PSEL_PORT_SHIFT) +#define SPIM_PSEL_CONNECTED (1 << 31) /* Bit 31: Connection */ +#define SPIM_PSEL_RESET (0xffffffff) /* FREQUENCY Register */ diff --git a/arch/arm/src/nrf52/nrf52_spi.c b/arch/arm/src/nrf52/nrf52_spi.c index 65037bab3d..afc275c812 100644 --- a/arch/arm/src/nrf52/nrf52_spi.c +++ b/arch/arm/src/nrf52/nrf52_spi.c @@ -72,12 +72,10 @@ struct nrf52_spidev_s { struct spi_dev_s spidev; /* Externally visible part of the SPI interface */ uint32_t base; /* Base address of SPI register */ + nrf52_pinset_t sck_pin; /* Pin settings for SPI clock */ #ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS uint32_t irq; /* SPI IRQ number */ #endif - uint32_t sck_pin; /* SCK pin configuration */ - uint32_t mosi_pin; /* MOSI pin configuration */ - uint32_t miso_pin; /* MISO pin configuration */ uint32_t frequency; /* Requested clock frequency */ uint8_t mode; /* Mode 0,1,2,3 */ @@ -99,6 +97,8 @@ static inline void nrf52_spi_putreg(FAR struct nrf52_spidev_s *priv, static inline uint32_t nrf52_spi_getreg(FAR struct nrf52_spidev_s *priv, uint32_t offset); +static void nrf52_spi_pselinit(uint32_t pselreg, nrf52_pinset_t pinset); + /* SPI methods */ static int nrf52_spi_lock(FAR struct spi_dev_s *dev, bool lock); @@ -131,6 +131,7 @@ static int nrf52_spi_isr(int irq, FAR void *context, FAR void *arg); /* Initialization */ static int nrf52_spi_init(FAR struct nrf52_spidev_s *priv); +static void nrf52_spi_gpioinit(FAR struct nrf52_spidev_s *priv); /**************************************************************************** * Private Data @@ -178,12 +179,10 @@ static struct nrf52_spidev_s g_spi0dev = }, .base = NRF52_SPIM0_BASE, + .sck_pin = BOARD_SPI0_SCK_PIN, #ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS .irq = NRF52_IRQ_SPI_TWI_0, #endif - .sck_pin = BOARD_SPI0_SCK_PIN, - .mosi_pin = BOARD_SPI0_MOSI_PIN, - .miso_pin = BOARD_SPI0_MISO_PIN, .frequency = 0, .mode = 0 }; @@ -231,12 +230,10 @@ static struct nrf52_spidev_s g_spi1dev = }, .base = NRF52_SPIM1_BASE, + .sck_pin = BOARD_SPI1_SCK_PIN, #ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS .irq = NRF52_IRQ_SPI_TWI_1, #endif - .sck_pin = BOARD_SPI1_SCK_PIN, - .mosi_pin = BOARD_SPI1_MOSI_PIN, - .miso_pin = BOARD_SPI1_MISO_PIN, .frequency = 0, .mode = 0 }; @@ -284,12 +281,10 @@ static struct nrf52_spidev_s g_spi2dev = }, .base = NRF52_SPIM2_BASE, + .sck_pin = BOARD_SPI2_SCK_PIN, #ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS .irq = NRF52_IRQ_SPI2, #endif - .sck_pin = BOARD_SPI2_SCK_PIN, - .mosi_pin = BOARD_SPI2_MOSI_PIN, - .miso_pin = BOARD_SPI2_MISO_PIN, .frequency = 0, .mode = 0 }; @@ -337,12 +332,10 @@ static struct nrf52_spidev_s g_spi3dev = }, .base = NRF52_SPIM3_BASE, + .sck_pin = BOARD_SPI3_SCK_PIN, #ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS .irq = NRF52_IRQ_SPI3, #endif - .sck_pin = BOARD_SPI3_SCK_PIN, - .mosi_pin = BOARD_SPI3_MOSI_PIN, - .miso_pin = BOARD_SPI3_MISO_PIN, .frequency = 0, .mode = 0 }; @@ -393,7 +386,6 @@ static inline uint32_t nrf52_spi_getreg(FAR struct nrf52_spidev_s *priv, static int nrf52_spi_isr(int irq, FAR void *context, FAR void *arg) { FAR struct nrf52_spidev_s *priv = (FAR struct nrf52_spidev_s *)arg; - uint32_t regval = 0; /* Get interrupt event */ @@ -412,6 +404,107 @@ static int nrf52_spi_isr(int irq, FAR void *context, FAR void *arg) } #endif +/**************************************************************************** + * Name: nrf52_spi_pselinit + * + * Description: + * Configure PSEL for SPI devices + * + ****************************************************************************/ + +static void nrf52_spi_pselinit(uint32_t pselreg, nrf52_pinset_t pinset) +{ + uint32_t regval; + int pin = GPIO_PIN_DECODE(pinset); + int port = GPIO_PORT_DECODE(pinset); + + regval = (pin << SPIM_PSEL_PIN_SHIFT); + regval |= (port << SPIM_PSEL_PORT_SHIFT); + putreg32(pselreg, regval); +} + +/**************************************************************************** + * Name: nrf52_spi_gpioinit + * + * Description: + * Configure GPIO for SPI pins + * + ****************************************************************************/ + +static void nrf52_spi_gpioinit(FAR struct nrf52_spidev_s *priv) +{ + nrf52_gpio_config(priv->sck_pin); + nrf52_spi_pselinit(priv->base + NRF52_SPIM_PSELSCK_OFFSET, + priv->sck_pin); +#ifdef CONFIG_NRF52_SPI0_MASTER + if (priv == &g_spi0dev) + { +#ifdef BOARD_SPI0_MISO_PIN + nrf52_gpio_config(BOARD_SPI0_MISO_PIN); + nrf52_spi_pselinit(priv->base + NRF52_SPIM_PSELMISO_OFFSET, + BOARD_SPI0_MISO_PIN); + nrf52_gpio_write(BOARD_SPI0_MISO_PIN, false); +#endif +#ifdef BOARD_SPI0_MOSI_PIN + nrf52_gpio_config(BOARD_SPI0_MOSI_PIN); + nrf52_spi_pselinit(priv->base + NRF52_SPIM_PSELMOSI_OFFSET, + BOARD_SPI0_MOSI_PIN); +#endif + } +#endif + +#ifdef CONFIG_NRF52_SPI1_MASTER + if (priv == &g_spi1dev) + { +#ifdef BOARD_SPI1_MISO_PIN + nrf52_gpio_config(BOARD_SPI1_MISO_PIN); + nrf52_spi_pselinit(priv->base + NRF52_SPIM_PSELMISO_OFFSET, + BOARD_SPI1_MISO_PIN); + nrf52_gpio_write(BOARD_SPI1_MISO_PIN, false); +#endif +#ifdef BOARD_SPI1_MOSI_PIN + nrf52_gpio_config(BOARD_SPI1_MOSI_PIN); + nrf52_spi_pselinit(priv->base + NRF52_SPIM_PSELMOSI_OFFSET, + BOARD_SPI1_MOSI_PIN); +#endif + } +#endif + +#ifdef CONFIG_NRF52_SPI2_MASTER + if (priv == &g_spi2dev) + { +#ifdef BOARD_SPI2_MISO_PIN + nrf52_gpio_config(BOARD_SPI2_MISO_PIN); + nrf52_spi_pselinit(priv->base + NRF52_SPIM_PSELMISO_OFFSET, + BOARD_SPI1_MISO_PIN); + nrf52_gpio_write(BOARD_SPI1_MISO_PIN, false); +#endif +#ifdef BOARD_SPI2_MOSI_PIN + nrf52_gpio_config(BOARD_SPI2_MOSI_PIN); + nrf52_spi_pselinit(priv->base + NRF52_SPIM_PSELMOSI_OFFSET, + BOARD_SPI2_MOSI_PIN); +#endif + } +#endif + +#ifdef CONFIG_NRF52_SPI3_MASTER + if (priv == &g_spi3dev) + { +#ifdef BOARD_SPI3_MISO_PIN + nrf52_gpio_config(BOARD_SPI3_MISO_PIN); + nrf52_spi_pselinit(priv->base + NRF52_SPIM_PSELMISO_OFFSET, + BOARD_SPI3_MISO_PIN); + nrf52_gpio_write(BOARD_SPI1_MISO_PIN, false); +#endif +#ifdef BOARD_SPI3_MOSI_PIN + nrf52_gpio_config(BOARD_SPI3_MOSI_PIN); + nrf52_spi_pselinit(priv->base + NRF52_SPIM_PSELMOSI_OFFSET, + BOARD_SPI3_MOSI_PIN); +#endif + } +#endif +} + /**************************************************************************** * Name: nrf52_spi_init * @@ -422,58 +515,18 @@ static int nrf52_spi_isr(int irq, FAR void *context, FAR void *arg) static int nrf52_spi_init(FAR struct nrf52_spidev_s *priv) { - uint32_t regval = 0; - int pin = 0; - int port = 0; - /* Disable SPI */ nrf52_spi_putreg(priv, NRF52_SPIM_ENABLE_OFFSET, SPIM_ENABLE_DIS); /* Configure SPI pins */ - nrf52_gpio_config(priv->sck_pin); - nrf52_gpio_config(priv->mosi_pin); - nrf52_gpio_config(priv->miso_pin); - - /* Select SCK pins */ - - pin = GPIO_PIN_DECODE(priv->sck_pin); - port = GPIO_PORT_DECODE(priv->sck_pin); - - regval = (pin << SPIM_PSELSCK_PIN_SHIFT); - regval |= (port << SPIM_PSELSCK_PORT_SHIFT); - nrf52_spi_putreg(priv, NRF52_SPIM_PSELSCK_OFFSET, regval); - - /* Select MOSI pins */ - - pin = GPIO_PIN_DECODE(priv->mosi_pin); - port = GPIO_PORT_DECODE(priv->mosi_pin); - - regval = (pin << SPIM_PSELMOSI_PIN_SHIFT); - regval |= (port << SPIM_PSELMOSI_PORT_SHIFT); - nrf52_spi_putreg(priv, NRF52_SPIM_PSELMOSI_OFFSET, regval); - - /* According to manual we have to write 0 to MOSI pin */ - - nrf52_gpio_write(priv->mosi_pin, false); - - /* Select MISO pins */ - - pin = GPIO_PIN_DECODE(priv->miso_pin); - port = GPIO_PORT_DECODE(priv->miso_pin); - - regval = (pin << SPIM_PSELMISO_PIN_SHIFT); - regval |= (port << SPIM_PSELMISO_PORT_SHIFT); - nrf52_spi_putreg(priv, NRF52_SPIM_PSELMISO_OFFSET, regval); - - /* NOTE: Chip select pin must be configured by board-specific logic */ + nrf52_spi_gpioinit(priv); #ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS /* Enable interrupts for RX and TX done */ - regval = SPIM_INT_END; - nrf52_spi_putreg(priv, NRF52_SPIM_INTENSET_OFFSET, regval); + nrf52_spi_putreg(priv, NRF52_SPIM_INTENSET_OFFSET, SPIM_INT_END); #endif /* Enable SPI */