This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push: new e4752fb S32K1xx arch: Add (optional) support for SPI native/hardware chip select e4752fb is described below commit e4752fbaee8f1a0de63fffcedadc1bf1f5f3d891 Author: Jari van Ewijk <jari.vanew...@nxp.com> AuthorDate: Mon Oct 4 17:11:14 2021 +0200 S32K1xx arch: Add (optional) support for SPI native/hardware chip select --- arch/arm/src/s32k1xx/Kconfig | 4 ++ arch/arm/src/s32k1xx/hardware/s32k1xx_lpspi.h | 1 + arch/arm/src/s32k1xx/s32k1xx_lpspi.c | 89 +++++++++++++++++++++++---- 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/arch/arm/src/s32k1xx/Kconfig b/arch/arm/src/s32k1xx/Kconfig index ded70be..36fa483 100644 --- a/arch/arm/src/s32k1xx/Kconfig +++ b/arch/arm/src/s32k1xx/Kconfig @@ -624,6 +624,10 @@ menu "LPSPI Configuration" config S32K1XX_LPSPI_DWORD bool "DWORD up to 64 bit transfer support" default n + +config S32K1XX_LPSPI_HWPCS + bool "Use native hardware peripheral chip selects instead of GPIO pins" + default n endmenu # LPSPI Configuration diff --git a/arch/arm/src/s32k1xx/hardware/s32k1xx_lpspi.h b/arch/arm/src/s32k1xx/hardware/s32k1xx_lpspi.h index 0750d94..8e4c32d 100644 --- a/arch/arm/src/s32k1xx/hardware/s32k1xx_lpspi.h +++ b/arch/arm/src/s32k1xx/hardware/s32k1xx_lpspi.h @@ -299,6 +299,7 @@ # define LPSPI_TCR_MSBF (0 << 23) /* MSB First */ #define LPSPI_TCR_PCS_SHIFT (24) /* Bits 24-25: Peripheral Chip Select */ #define LPSPI_TCR_PCS_MASK (3 << LPSPI_TCR_PCS_SHIFT) +# define LPSPI_TCR_PCS(n) (((n) << LPSPI_TCR_PCS_SHIFT) & LPSPI_TCR_PCS_MASK) # define LPSPI_TCR_PCS_0 (0 << LPSPI_TCR_PCS_SHIFT) /* Transfer using LPSPI_PCS[0] */ # define LPSPI_TCR_PCS_1 (1 << LPSPI_TCR_PCS_SHIFT) /* Transfer using LPSPI_PCS[1] */ # define LPSPI_TCR_PCS_2 (2 << LPSPI_TCR_PCS_SHIFT) /* Transfer using LPSPI_PCS[2] */ diff --git a/arch/arm/src/s32k1xx/s32k1xx_lpspi.c b/arch/arm/src/s32k1xx/s32k1xx_lpspi.c index 60ea04d..87d9cc5 100644 --- a/arch/arm/src/s32k1xx/s32k1xx_lpspi.c +++ b/arch/arm/src/s32k1xx/s32k1xx_lpspi.c @@ -19,19 +19,19 @@ ****************************************************************************/ /**************************************************************************** - * The external functions, s32k1xx_lpspi0/1/2select and - * s32k1xx_lpspi0/1/2status must be provided by board-specific logic. They - * are implementations of the select and status methods of the SPI interface - * defined by struct s32k1xx_lpspi_ops_s (see include/nuttx/spi/spi.h). - * All other methods (including s32k1xx_lpspibus_initialize()) are provided - * by common S32K1XX logic. To use this common SPI logic on your board: + * The external functions, s32k1xx_lpspiNselect* and s32k1xx_lpspiNstatus + * must be provided by board-specific logic. They are implementations of the + * select and status methods of the SPI interface defined by struct + * s32k1xx_lpspi_ops_s (see include/nuttx/spi/spi.h). All other methods + * (including s32k1xx_lpspibus_initialize()) are provided by common S32K1XX + * logic. To use this common SPI logic on your board: * * 1. Provide logic in s32k1xx_boardinitialize() to configure SPI chip * select pins. - * 2. Provide s32k1xx_lpspi0/1/2select() and s32k1xx_lpspi0/1/2status() - * functions in your board-specific logic. These functions will perform - * chip selection and status operations using GPIOs in the way your - * board is configured. + * 2. Provide s32k1xx_lpspiNselect() and s32k1xx_lpspiNstatus() functions + * in your board-specific logic. These functions will perform chip + * selection and status operations using GPIOs in the way your board is + * configured. * 3. Add a calls to s32k1xx_lpspibus_initialize() in your low level * application initialization logic * 4. The handle returned by s32k1xx_lpspibus_initialize() may then be @@ -39,6 +39,12 @@ * mmcsd_lpspislotinitialize(), for example, will bind the SPI driver * to the SPI MMC/SD driver). * + * NOTE*: If CONFIG_S32K1XX_LPSPI_HWPCS is selected, s32k1xx_lpspiNselect() + * does NOT need to provided by board-specific logic. In this case a + * generic implementation is used that switches between native + * hardware chip select pins. It is important that all pins are + * configured when the SPI bus is initialized. + * ****************************************************************************/ /**************************************************************************** @@ -135,6 +141,9 @@ struct s32k1xx_lpspidev_s uint32_t actual; /* Actual clock frequency */ int8_t nbits; /* Width of word in bits */ uint8_t mode; /* Mode 0,1,2,3 */ +#ifdef CONFIG_S32K1XX_LPSPI_HWPCS + uint32_t pcs; /* Peripheral Chip Select currently used */ +#endif }; enum s32k1xx_delay_e @@ -176,6 +185,10 @@ void s32k1xx_lpspi_set_delay_scaler(FAR struct s32k1xx_lpspidev_s *priv, /* SPI methods */ static int s32k1xx_lpspi_lock(FAR struct spi_dev_s *dev, bool lock); +#ifdef CONFIG_S32K1XX_LPSPI_HWPCS +static void s32k1xx_lpspi_select(FAR struct spi_dev_s *dev, uint32_t devid, + bool selected); +#endif static uint32_t s32k1xx_lpspi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static void s32k1xx_lpspi_setmode(FAR struct spi_dev_s *dev, @@ -216,7 +229,11 @@ s32k1xx_lpspi_bus_initialize(FAR struct s32k1xx_lpspidev_s *priv); static const struct spi_ops_s g_spi0ops = { .lock = s32k1xx_lpspi_lock, +#ifdef CONFIG_S32K1XX_LPSPI_HWPCS + .select = s32k1xx_lpspi_select, +#else .select = s32k1xx_lpspi0select, +#endif .setfrequency = s32k1xx_lpspi_setfrequency, .setmode = s32k1xx_lpspi_setmode, .setbits = s32k1xx_lpspi_setbits, @@ -262,7 +279,11 @@ static struct s32k1xx_lpspidev_s g_lpspi0dev = static const struct spi_ops_s g_spi1ops = { .lock = s32k1xx_lpspi_lock, +#ifdef CONFIG_S32K1XX_LPSPI_HWPCS + .select = s32k1xx_lpspi_select, +#else .select = s32k1xx_lpspi1select, +#endif .setfrequency = s32k1xx_lpspi_setfrequency, .setmode = s32k1xx_lpspi_setmode, .setbits = s32k1xx_lpspi_setbits, @@ -308,7 +329,11 @@ static struct s32k1xx_lpspidev_s g_lpspi1dev = static const struct spi_ops_s g_spi2ops = { .lock = s32k1xx_lpspi_lock, +#ifdef CONFIG_S32K1XX_LPSPI_HWPCS + .select = s32k1xx_lpspi_select, +#else .select = s32k1xx_lpspi2select, +#endif .setfrequency = s32k1xx_lpspi_setfrequency, .setmode = s32k1xx_lpspi_setmode, .setbits = s32k1xx_lpspi_setbits, @@ -944,6 +969,48 @@ static int s32k1xx_lpspi_lock(FAR struct spi_dev_s *dev, bool lock) return ret; } +#ifdef CONFIG_S32K1XX_LPSPI_HWPCS +/**************************************************************************** + * Name: s32k1xx_lpspi_select + * + * Description: + * Change to another SPI chip select (hardware/native, not emulated with + * GPIO) to select another device. The hardware itself controls when + * the chip select is enabled or disabled. + * + * Input Parameters: + * dev - Device-specific state data + * devid - Identifies the device to select + * selected - Ignored, selection is controlled by hardware + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void s32k1xx_lpspi_select(FAR struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + FAR struct s32k1xx_lpspidev_s *priv = (FAR struct s32k1xx_lpspidev_s *)dev; + + /* LPSPI on S32K1XX supports PCS 0-3 */ + + DEBUGASSERT(SPIDEVID_INDEX(devid) <= 3); + + /* Has the Peripheral Chip Select changed? */ + + if (devid != priv->pcs) + { + s32k1xx_lpspi_modifyreg32(priv, S32K1XX_LPSPI_TCR_OFFSET, + LPSPI_TCR_PCS_MASK, + LPSPI_TCR_PCS(SPIDEVID_INDEX(devid))); + priv->pcs = devid; + } + + spiinfo("devid: %" PRId32 ", CS: hardware-controlled\n", devid); +} +#endif /* CONFIG_S32K1XX_LPSPI HWPCS */ + /**************************************************************************** * Name: s32k1xx_lpspi_setfrequency * @@ -1071,7 +1138,7 @@ static uint32_t s32k1xx_lpspi_setfrequency(FAR struct spi_dev_s *dev, * mode - The SPI mode requested * * Returned Value: - * Returns the actual frequency selected + * none * ****************************************************************************/