From 7d4cb73bd662224051c8d1e523b1d047576b04cf Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 8 Aug 2016 08:28:13 -0600 Subject: [PATCH] STM32 and EFM32 SPI drivers adopted an incompatible conventions somewhere along the line. The set the number of bits to negative when calling SPI_SETBITS which had the magical side-effect of setting LSB first order of bit transmission. This is not only a hokey way to pass control information but is supported by no other SPI drivers. This change three things: (1) It adds HWFEAT_LSBFIRST as a new H/W feature. (2) It changes the implementations of SPI_SETBITS in the STM32 and EFM32 derivers so that negated bit numbers are simply errors and it adds the SPI_HWFEATURES method that can set the LSB bit order, and (3) It changes all calls with negative number of bits from all drivers: The number of bits is now always positive and SPI_HWFEATUREs is called with HWFEAT_LSBFIRST to set the bit order. --- arch/arm/src/efm32/efm32_spi.c | 106 +++++++++++++++++++---------- arch/arm/src/stm32/stm32_spi.c | 81 ++++++++++++++++++---- arch/arm/src/stm32f7/stm32_spi.c | 103 +++++++++++++++++++++------- arch/arm/src/stm32l4/stm32l4_spi.c | 89 +++++++++++++++++------- drivers/lcd/memlcd.c | 16 +++-- drivers/wireless/pn532.c | 15 ++-- include/nuttx/spi/spi.h | 8 ++- 7 files changed, 306 insertions(+), 112 deletions(-) diff --git a/arch/arm/src/efm32/efm32_spi.c b/arch/arm/src/efm32/efm32_spi.c index c4dbb3b282d..42560029c25 100644 --- a/arch/arm/src/efm32/efm32_spi.c +++ b/arch/arm/src/efm32/efm32_spi.c @@ -185,6 +185,10 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency); static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setbits(struct spi_dev_s *dev, int nbits); +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(FAR struct spi_dev_s *dev, + spi_hwfeatures_t features); +#endif static uint8_t spi_status(struct spi_dev_s *dev, enum spi_dev_e devid); #ifdef CONFIG_SPI_CMDDATA static int spi_cmddata(struct spi_dev_s *dev, enum spi_dev_e devid, @@ -218,7 +222,7 @@ static const struct spi_ops_s g_spiops = .setmode = spi_setmode, .setbits = spi_setbits, #ifdef CONFIG_SPI_HWFEATURES - .hwfeatures = 0, + .hwfeatures = spi_hwfeatures, #endif .status = spi_status, #ifdef CONFIG_SPI_CMDDATA @@ -976,47 +980,16 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits) const struct efm32_spiconfig_s *config; uint32_t regval; uint32_t setting; - bool lsbfirst; spiinfo("nbits=%d\n", nbits); DEBUGASSERT(priv && priv->config); config = priv->config; - /* Bit order is encoded by the sign of nbits */ + /* Has the number of bits changed? */ - if (nbits < 0) + if (nbits != priv->nbits) { - /* LSB first */ - - lsbfirst = true; - nbits = -nbits; - } - else - { - /* MSH first */ - - lsbfirst = false; - } - - /* Has the number of bits or the bit order changed? */ - - if (nbits != priv->nbits || lsbfirst != priv->lsbfirst) - { - /* Set the new bit order */ - - regval = spi_getreg(config, EFM32_USART_CTRL_OFFSET); - if (lsbfirst) - { - regval &= ~USART_CTRL_MSBF; - } - else - { - regval |= USART_CTRL_MSBF; - } - - spi_putreg(config, EFM32_USART_CTRL_OFFSET, regval); - /* Select the new number of bits */ switch (nbits) @@ -1086,11 +1059,72 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits) * faster */ - priv->nbits = nbits; - priv->lsbfirst = lsbfirst; + priv->nbits = nbits; } } +/**************************************************************************** + * Name: spi_hwfeatures + * + * Description: + * Set hardware-specific feature flags. + * + * Input Parameters: + * dev - Device-specific state data + * flags - H/W feature flags + * + * Returned Value: + * Zero (OK) if the selected H/W features are enabled; A negated errno + * value if any H/W feature is not supportable. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(FAR struct spi_dev_s *dev, spi_hwfeatures_t features) +{ + struct efm32_spidev_s *priv = (struct efm32_spidev_s *)dev; + const struct efm32_spiconfig_s *config; + uint32_t regval; + bool lsbfirst; + + spiinfo("features=%08x\n", features); + + DEBUGASSERT(priv && priv->config); + config = priv->config; + + /* Bit order is encoded by the sign of nbits */ + + lsbfirst = ((hwfeatures & HWFEAT_LSBFIRST) != 0); + + /* Has the number of bits or the bit order changed? */ + + if (lsbfirst != priv->lsbfirst) + { + /* Set the new bit order */ + + regval = spi_getreg(config, EFM32_USART_CTRL_OFFSET); + if (lsbfirst) + { + regval &= ~USART_CTRL_MSBF; + } + else + { + regval |= USART_CTRL_MSBF; + } + + spi_putreg(config, EFM32_USART_CTRL_OFFSET, regval); + + /* Save the selection so the subsequence re-configurations will be + * faster + */ + + priv->lsbfirst = lsbfirst; + } + + return OK; +} +#endif + /**************************************************************************** * Name: spi_status * diff --git a/arch/arm/src/stm32/stm32_spi.c b/arch/arm/src/stm32/stm32_spi.c index 807a13127f2..61815bea12e 100644 --- a/arch/arm/src/stm32/stm32_spi.c +++ b/arch/arm/src/stm32/stm32_spi.c @@ -222,6 +222,10 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setbits(FAR struct spi_dev_s *dev, int nbits); +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(FAR struct spi_dev_s *dev, + spi_hwfeatures_t features); +#endif static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords); @@ -249,7 +253,7 @@ static const struct spi_ops_s g_sp1iops = .setmode = spi_setmode, .setbits = spi_setbits, #ifdef CONFIG_SPI_HWFEATURES - .hwfeatures = 0, /* Not supported */ + .hwfeatures = spi_hwfeatures, #endif .status = stm32_spi1status, #ifdef CONFIG_SPI_CMDDATA @@ -292,6 +296,9 @@ static const struct spi_ops_s g_sp2iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi2status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi2cmddata, @@ -333,6 +340,9 @@ static const struct spi_ops_s g_sp3iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi3status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi3cmddata, @@ -374,6 +384,9 @@ static const struct spi_ops_s g_sp4iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi4status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi4cmddata, @@ -415,6 +428,9 @@ static const struct spi_ops_s g_sp5iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi5status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi5cmddata, @@ -456,6 +472,9 @@ static const struct spi_ops_s g_sp6iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi6status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi3cmddata, @@ -1136,24 +1155,14 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) switch (nbits) { - case -8: - setbits = SPI_CR1_LSBFIRST; - clrbits = SPI_CR1_DFF; - break; - case 8: setbits = 0; - clrbits = SPI_CR1_DFF | SPI_CR1_LSBFIRST; - break; - - case -16: - setbits = SPI_CR1_DFF | SPI_CR1_LSBFIRST; - clrbits = 0; + clrbits = SPI_CR1_DFF; break; case 16: setbits = SPI_CR1_DFF; - clrbits = SPI_CR1_LSBFIRST; + clrbits = 0; break; default: @@ -1170,6 +1179,52 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) } } +/**************************************************************************** + * Name: spi_hwfeatures + * + * Description: + * Set hardware-specific feature flags. + * + * Input Parameters: + * dev - Device-specific state data + * flags - H/W feature flags + * + * Returned Value: + * Zero (OK) if the selected H/W features are enabled; A negated errno + * value if any H/W feature is not supportable. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(FAR struct spi_dev_s *dev, spi_hwfeatures_t features) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + uint16_t setbits; + uint16_t clrbits; + + spiinfo("features=%08x\n", features); + + /* Transfer data LSB first? */ + + if ((hwfeatures & HWFEAT_LSBFIRST) != 0) + { + setbits = SPI_CR1_LSBFIRST; + clrbits = 0; + } + else + { + setbits = 0; + clrbits = SPI_CR1_LSBFIRST; + } + + spi_modifycr1(priv, 0, SPI_CR1_SPE); + spi_modifycr1(priv, setbits, clrbits); + spi_modifycr1(priv, SPI_CR1_SPE, 0); + + return OK; +} +#endif + /************************************************************************************ * Name: spi_send * diff --git a/arch/arm/src/stm32f7/stm32_spi.c b/arch/arm/src/stm32f7/stm32_spi.c index 78b5eeaf06b..bafd62a7869 100644 --- a/arch/arm/src/stm32f7/stm32_spi.c +++ b/arch/arm/src/stm32f7/stm32_spi.c @@ -203,6 +203,10 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setbits(FAR struct spi_dev_s *dev, int nbits); +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(FAR struct spi_dev_s *dev, + spi_hwfeatures_t features); +#endif static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords); @@ -230,7 +234,7 @@ static const struct spi_ops_s g_sp1iops = .setmode = spi_setmode, .setbits = spi_setbits, #ifdef CONFIG_SPI_HWFEATURES - .hwfeatures = 0, /* Not supported */ + .hwfeatures = spi_hwfeatures, #endif .status = stm32_spi1status, #ifdef CONFIG_SPI_CMDDATA @@ -273,6 +277,9 @@ static const struct spi_ops_s g_sp2iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi2status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi2cmddata, @@ -314,6 +321,9 @@ static const struct spi_ops_s g_sp3iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi3status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi3cmddata, @@ -355,6 +365,9 @@ static const struct spi_ops_s g_sp4iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi4status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi4cmddata, @@ -396,6 +409,9 @@ static const struct spi_ops_s g_sp5iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi5status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi5cmddata, @@ -437,6 +453,9 @@ static const struct spi_ops_s g_sp6iops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32_spi6status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32_spi3cmddata, @@ -1219,10 +1238,8 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) { FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; - uint16_t setbitscr1; - uint16_t clrbitscr1; - uint16_t setbitscr2; - uint16_t clrbitscr2; + uint16_t setbits; + uint16_t clrbits; int savbits = nbits; spiinfo("nbits=%d\n", nbits); @@ -1231,21 +1248,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) if (nbits != priv->nbits) { - /* Yes... Set CR1/2 appropriately */ - /* Negative sign means LSBFIRST, set this in CR1*/ - - if (nbits < 0) - { - setbitscr1 = SPI_CR1_LSBFIRST; - clrbitscr1 = 0; - nbits = -nbits; - } - else - { - setbitscr1 = 0; - clrbitscr1 = SPI_CR1_LSBFIRST; - } - + /* Yes... Set CR2 appropriately */ /* Set the number of bits (valid range 4-16) */ if (nbits < 4 || nbits > 16) @@ -1253,8 +1256,8 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) return; } - clrbitscr2 = SPI_CR2_DS_MASK; - setbitscr2 = SPI_CR2_DS_VAL(nbits); + clrbits = SPI_CR2_DS_MASK; + setbits = SPI_CR2_DS_VAL(nbits); /* If nbits is <=8, then we are in byte mode and FRXTH shall be set * (else, transaction will not complete). @@ -1262,16 +1265,15 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) if (nbits < 9) { - setbitscr2 |= SPI_CR2_FRXTH; /* RX FIFO Threshold = 1 byte */ + setbits |= SPI_CR2_FRXTH; /* RX FIFO Threshold = 1 byte */ } else { - clrbitscr2 |= SPI_CR2_FRXTH; /* RX FIFO Threshold = 2 bytes */ + clrbits |= SPI_CR2_FRXTH; /* RX FIFO Threshold = 2 bytes */ } spi_modifycr1(priv, 0, SPI_CR1_SPE); - spi_modifycr1(priv, setbitscr1, clrbitscr1); - spi_modifycr2(priv, setbitscr2, clrbitscr2); + spi_modifycr2(priv, setbits, clrbits); spi_modifycr1(priv, SPI_CR1_SPE, 0); /* Save the selection so the subsequence re-configurations will be faster */ @@ -1280,6 +1282,55 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) } } +/**************************************************************************** + * Name: spi_hwfeatures + * + * Description: + * Set hardware-specific feature flags. + * + * Input Parameters: + * dev - Device-specific state data + * flags - H/W feature flags + * + * Returned Value: + * Zero (OK) if the selected H/W features are enabled; A negated errno + * value if any H/W feature is not supportable. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(FAR struct spi_dev_s *dev, spi_hwfeatures_t features) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + uint16_t setbitscr1; + uint16_t clrbitscr1; + uint16_t setbitscr2; + uint16_t clrbitscr2; + int savbits = nbits; + + spiinfo("features=%08x\n", features); + + /* Transfer data LSB first? */ + + if ((hwfeatures & HWFEAT_LSBFIRST) != 0) + { + setbits = SPI_CR1_LSBFIRST; + clrbits = 0; + } + else + { + setbits = 0; + clrbits = SPI_CR1_LSBFIRST; + } + + spi_modifycr1(priv, 0, SPI_CR1_SPE); + spi_modifycr1(priv, setbits, clrbits); + spi_modifycr1(priv, SPI_CR1_SPE, 0); + + return OK; +} +#endif + /************************************************************************************ * Name: spi_send * diff --git a/arch/arm/src/stm32l4/stm32l4_spi.c b/arch/arm/src/stm32l4/stm32l4_spi.c index 3d64d812729..ac213abc688 100644 --- a/arch/arm/src/stm32l4/stm32l4_spi.c +++ b/arch/arm/src/stm32l4/stm32l4_spi.c @@ -203,6 +203,10 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setbits(FAR struct spi_dev_s *dev, int nbits); +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(FAR struct spi_dev_s *dev, + spi_hwfeatures_t features); +#endif static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords); @@ -230,7 +234,7 @@ static const struct spi_ops_s g_spi1ops = .setmode = spi_setmode, .setbits = spi_setbits, #ifdef CONFIG_SPI_HWFEATURES - .hwfeatures = 0, /* Not supported */ + .hwfeatures = spi_hwfeatures, #endif .status = stm32l4_spi1status, #ifdef CONFIG_SPI_CMDDATA @@ -274,6 +278,9 @@ static const struct spi_ops_s g_spi2ops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32l4_spi2status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32l4_spi2cmddata, @@ -315,6 +322,9 @@ static const struct spi_ops_s g_spi3ops = .setfrequency = spi_setfrequency, .setmode = spi_setmode, .setbits = spi_setbits, +#ifdef CONFIG_SPI_HWFEATURES + .hwfeatures = spi_hwfeatures, +#endif .status = stm32l4_spi3status, #ifdef CONFIG_SPI_CMDDATA .cmddata = stm32l4_spi3cmddata, @@ -1092,8 +1102,8 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) { FAR struct stm32l4_spidev_s *priv = (FAR struct stm32l4_spidev_s *)dev; - uint16_t setbits1, setbits2; - uint16_t clrbits1, clrbits2; + uint16_t setbits; + uint16_t clrbits; int savbits = nbits; spiinfo("nbits=%d\n", nbits); @@ -1102,21 +1112,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) if (nbits != priv->nbits) { - /* Yes... Set CR1/2 appropriately */ - /* Negative sign means LSBFIRST, set this in CR1*/ - - if (nbits < 0) - { - setbits1 = SPI_CR1_LSBFIRST; - clrbits1 = 0; - nbits = -nbits; - } - else - { - setbits1 = 0; - clrbits1 = SPI_CR1_LSBFIRST; - } - + /* Yes... Set CR2 appropriately */ /* Set the number of bits (valid range 4-16) */ if (nbits < 4 || nbits > 16) @@ -1124,8 +1120,8 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) return; } - clrbits2 = SPI_CR2_DS_MASK; - setbits2 = SPI_CR2_DS_VAL(nbits); + clrbits = SPI_CR2_DS_MASK; + setbits = SPI_CR2_DS_VAL(nbits); /* If nbits is <=8, then we are in byte mode and FRXTH shall be set * (else, transaction will not complete). @@ -1133,16 +1129,15 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) if (nbits < 9) { - setbits2 |= SPI_CR2_FRXTH; /* RX FIFO Threshold = 1 byte */ + setbits |= SPI_CR2_FRXTH; /* RX FIFO Threshold = 1 byte */ } else { - clrbits2 |= SPI_CR2_FRXTH; /* RX FIFO Threshold = 2 bytes */ + clrbits |= SPI_CR2_FRXTH; /* RX FIFO Threshold = 2 bytes */ } spi_modifycr(STM32L4_SPI_CR1_OFFSET, priv, 0, SPI_CR1_SPE); - spi_modifycr(STM32L4_SPI_CR1_OFFSET, priv, setbits1, clrbits1); - spi_modifycr(STM32L4_SPI_CR2_OFFSET, priv, setbits2, clrbits2); + spi_modifycr(STM32L4_SPI_CR2_OFFSET, priv, setbits, clrbits); spi_modifycr(STM32L4_SPI_CR1_OFFSET, priv, SPI_CR1_SPE, 0); /* Save the selection so the subsequence re-configurations will be faster */ @@ -1151,6 +1146,52 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) } } +/**************************************************************************** + * Name: spi_hwfeatures + * + * Description: + * Set hardware-specific feature flags. + * + * Input Parameters: + * dev - Device-specific state data + * flags - H/W feature flags + * + * Returned Value: + * Zero (OK) if the selected H/W features are enabled; A negated errno + * value if any H/W feature is not supportable. + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_HWFEATURES +static int spi_hwfeatures(FAR struct spi_dev_s *dev, spi_hwfeatures_t features) +{ + FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + uint16_t setbits; + uint16_t clrbits; + + spiinfo("features=%08x\n", features); + + /* Transfer data LSB first? */ + + if ((hwfeatures & HWFEAT_LSBFIRST) != 0) + { + setbits = SPI_CR1_LSBFIRST; + clrbits = 0; + } + else + { + setbits = 0; + clrbits = SPI_CR1_LSBFIRST; + } + + spi_modifycr(STM32L4_SPI_CR1_OFFSET, priv, 0, SPI_CR1_SPE); + spi_modifycr(STM32L4_SPI_CR1_OFFSET, priv, setbits, clrbits); + spi_modifycr(STM32L4_SPI_CR1_OFFSET, priv, SPI_CR1_SPE, 0); + + return OK; +} +#endif + /************************************************************************************ * Name: spi_send * diff --git a/drivers/lcd/memlcd.c b/drivers/lcd/memlcd.c index 59976b7a521..07782001923 100644 --- a/drivers/lcd/memlcd.c +++ b/drivers/lcd/memlcd.c @@ -59,7 +59,11 @@ * Pre-processor Definitions ****************************************************************************/ -/* Configuration */ +/* H/W features must be enabled in order to support LSB first operation */ + +#ifndef CONFIG_SPI_HWFEATURES +# error CONFIG_SPI_HWFEATURES=y required by this driver +#endif /* Cisplay resolution */ @@ -103,7 +107,7 @@ /* Other misc settings */ #define MEMLCD_SPI_FREQUENCY 2250000 -#define MEMLCD_SPI_BITS (-8) +#define MEMLCD_SPI_BITS 8 #define MEMLCD_SPI_MODE SPIDEV_MODE0 #define LS_BIT (1 << 0) @@ -281,12 +285,12 @@ static void memlcd_select(FAR struct spi_dev_s *spi) SPI_SETMODE(spi, MEMLCD_SPI_MODE); SPI_SETBITS(spi, MEMLCD_SPI_BITS); - (void)SPI_HWFEATURES(spi, 0); -# ifdef CONFIG_MEMLCD_SPI_FREQUENCY + (void)SPI_HWFEATURES(spi, HWFEAT_LSBFIRST); +#ifdef CONFIG_MEMLCD_SPI_FREQUENCY (void)SPI_SETFREQUENCY(spi, CONFIG_MEMLCD_SPI_FREQUENCY); -# else +#else (void)SPI_SETFREQUENCY(spi, MEMLCD_SPI_FREQUENCY); -# endif +#endif } /**************************************************************************** diff --git a/drivers/wireless/pn532.c b/drivers/wireless/pn532.c index 260c5375a7c..52137863885 100644 --- a/drivers/wireless/pn532.c +++ b/drivers/wireless/pn532.c @@ -56,6 +56,13 @@ * Pre-processor Definitions ****************************************************************************/ +/* Configuration ************************************************************/ +/* H/W features must be enabled in order to support LSB first operation */ + +#ifndef CONFIG_SPI_HWFEATURES +# error CONFIG_SPI_HWFEATURES=y required by this driver +#endif + #ifdef CONFIG_WL_PN532_DEBUG # define pn532err _err # define pn532info _info @@ -145,8 +152,8 @@ static void pn532_lock(FAR struct spi_dev_s *spi) (void)SPI_LOCK(spi, true); SPI_SETMODE(spi, SPIDEV_MODE0); - SPI_SETBITS(spi, -8); - (void)SPI_HWFEATURES(spi, 0); + SPI_SETBITS(spi, 8); + (void)SPI_HWFEATURES(spi, HWFEAT_LSBFIRST); (void)SPI_SETFREQUENCY(spi, CONFIG_PN532_SPI_FREQ); } @@ -160,8 +167,8 @@ static inline void pn532_configspi(FAR struct spi_dev_s *spi) /* Configure SPI for the PN532 module. */ SPI_SETMODE(spi, SPIDEV_MODE0); - SPI_SETBITS(spi, -8); - (void)SPI_HWFEATURES(spi, 0); + SPI_SETBITS(spi, 8); + (void)SPI_HWFEATURES(spi, HWFEAT_LSBFIRST); (void)SPI_SETFREQUENCY(spi, CONFIG_PN532_SPI_FREQ); } diff --git a/include/nuttx/spi/spi.h b/include/nuttx/spi/spi.h index 53046fcc733..6b6ebe733ee 100644 --- a/include/nuttx/spi/spi.h +++ b/include/nuttx/spi/spi.h @@ -175,9 +175,7 @@ * * Input Parameters: * dev - Device-specific state data - * 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 + * nbits - The number of bits in an SPI word. * * Returned Value: * none @@ -225,6 +223,8 @@ * Do not set the LASTXFER-Bit at the last word of the next * exchange, Flag is auto-resetting after the next LASTXFER * condition. (see spi_exchange) + * Bit 4: HWFEAT_LSBFIRST + * Data transferred LSB first (default is MSB first) */ # ifdef CONFIG_SPI_CRCGENERATION @@ -237,6 +237,8 @@ # define HWFEAT_ESCAPE_LASTXFER (1 << 3) # endif +# define HWFEAT_LSBFIRST (1 << 4) + #else /* Any attempt to select hardware features with CONFIG_SPI_HWFEATURES * deselected will return an -ENOSYS error.