From 1bae8843f185e3ff60a055027292b17a906eb0d0 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 19 Nov 2025 11:44:57 +0200 Subject: [PATCH 1/2] arch/imx9: Correct LPSPI TCR register PCS bit definitions According to the TRM, only bits 24-25 are reserved for chip select, and the maximum number of internal chip selects is 3 (on LPSPI4 bus only). Fix the TCR_PCS_MASK and remove extra definitions. Signed-off-by: Jukka Laitinen --- arch/arm64/src/imx9/hardware/imx9_lpspi.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/arm64/src/imx9/hardware/imx9_lpspi.h b/arch/arm64/src/imx9/hardware/imx9_lpspi.h index 30361542653c6..6d7e7c233e1d7 100644 --- a/arch/arm64/src/imx9/hardware/imx9_lpspi.h +++ b/arch/arm64/src/imx9/hardware/imx9_lpspi.h @@ -284,16 +284,11 @@ #define LPSPI_TCR_BYSW (1 << 22) /* Bit 22: Byte Swap (BYSW) */ #define LPSPI_TCR_LSBF (1 << 23) /* Bit 23: LSB First (LSBF) */ # define LPSPI_TCR_MSBF (0 << 23) /* MSB First */ -#define LPSPI_TCR_PCS_SHIFT (24) /* Bits 24-26: Peripheral Chip Select (PCS) */ -#define LPSPI_TCR_PCS_MASK (0x07 << LPSPI_TCR_PCS_SHIFT) +#define LPSPI_TCR_PCS_SHIFT (24) /* Bits 24-25: Peripheral Chip Select (PCS) */ +#define LPSPI_TCR_PCS_MASK (0x03 << LPSPI_TCR_PCS_SHIFT) # define LPSPI_TCR_PCS_0 (0x00 << LPSPI_TCR_PCS_SHIFT) /* Transfer using PCS[0] */ # define LPSPI_TCR_PCS_1 (0x01 << LPSPI_TCR_PCS_SHIFT) /* Transfer using PCS[1] */ # define LPSPI_TCR_PCS_2 (0x02 << LPSPI_TCR_PCS_SHIFT) /* Transfer using PCS[2] */ -# define LPSPI_TCR_PCS_3 (0x03 << LPSPI_TCR_PCS_SHIFT) /* Transfer using PCS[3] */ -# define LPSPI_TCR_PCS_4 (0x04 << LPSPI_TCR_PCS_SHIFT) /* Transfer using PCS[4] */ -# define LPSPI_TCR_PCS_5 (0x05 << LPSPI_TCR_PCS_SHIFT) /* Transfer using PCS[5] */ -# define LPSPI_TCR_PCS_6 (0x06 << LPSPI_TCR_PCS_SHIFT) /* Transfer using PCS[6] */ -# define LPSPI_TCR_PCS_7 (0x07 << LPSPI_TCR_PCS_SHIFT) /* Transfer using PCS[7] */ #define LPSPI_TCR_PRESCALE_SHIFT (27) /* Bits 27-29: Prescaler Value (PRESCALE) */ #define LPSPI_TCR_PRESCALE_MASK (0x07 << LPSPI_TCR_PRESCALE_SHIFT) From 7f458cd29792c4dac6d450fb2cb1079eaccf8567 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 19 Nov 2025 11:35:06 +0200 Subject: [PATCH 2/2] arch/imx9: Enable manual control for LPSPI PCS signals Add a function imx9_lpspi_select_cs to assert CS at the start of an SPI transfer and keep it asserted until called again to de-assert it. This can be called by board-provided imx9_lpspi_select, in case the CS needs to be controlled via the LPSPI block and not GPIO. The TCR register CONT (continue) bit is asserted to prevent CS toggling during the transfer, and the PCS bits are set to mark the correct CS Signed-off-by: Jukka Laitinen --- arch/arm64/src/imx9/imx9_lpspi.c | 34 ++++++++++++++++++++++++++++++++ arch/arm64/src/imx9/imx9_lpspi.h | 21 ++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/arch/arm64/src/imx9/imx9_lpspi.c b/arch/arm64/src/imx9/imx9_lpspi.c index b6caa7d4d1163..5f665334d63f4 100644 --- a/arch/arm64/src/imx9/imx9_lpspi.c +++ b/arch/arm64/src/imx9/imx9_lpspi.c @@ -2094,4 +2094,38 @@ void imx9_lpspi_uninitialize(struct spi_dev_s *dev) } } +/**************************************************************************** + * Name: imx9_lpspi_select_cs + * + * Description: + * Assert or de-assert internal PCS0 or PCS1 line. Can be called by + * board-specific chip-select logic. Assertion of the CS is done at the + * start of the next transfer and de-assertion after this function is + * called again to de-assert the cs and the transfer has ended. + * + * Input Parameters: + * dev - Device-specific state data + * cs - Chip select 0 or 1 + * select - true: assert CS, false: de-assert CS + * + * Returned Value: + * None + * + ****************************************************************************/ + +void imx9_lpspi_select_cs(struct spi_dev_s *dev, int cs, bool select) +{ + struct imx9_lpspidev_s *priv = (struct imx9_lpspidev_s *)dev; + + if (select) + { + uint32_t pcs = (cs << LPSPI_TCR_PCS_SHIFT) & LPSPI_TCR_PCS_MASK; + imx9_lpspi_modifytcr(priv, LPSPI_TCR_PCS_MASK, pcs | LPSPI_TCR_CONT); + } + else + { + imx9_lpspi_modifytcr(priv, LPSPI_TCR_CONT, 0); + } +} + #endif /* CONFIG_IMX9_LPSPI */ diff --git a/arch/arm64/src/imx9/imx9_lpspi.h b/arch/arm64/src/imx9/imx9_lpspi.h index 0e39c31f69658..280474712ef82 100644 --- a/arch/arm64/src/imx9/imx9_lpspi.h +++ b/arch/arm64/src/imx9/imx9_lpspi.h @@ -148,6 +148,27 @@ int imx9_lpspi_register(struct spi_dev_s *dev, void *arg); #endif +/**************************************************************************** + * Name: imx9_lpspi_select_cs + * + * Description: + * Assert or de-assert internal PCS0 or PCS1 line. Can be called by + * board-specific chip-select logic. Assertion of the CS is done at the + * start of the next transfer and de-assertion after this function is + * called again to de-assert the cs and the transfer has ended. + * + * Input Parameters: + * dev - Device-specific state data + * cs - Chip select 0 or 1 + * select - true: assert CS, false: de-assert CS + * + * Returned Value: + * None + * + ****************************************************************************/ + +void imx9_lpspi_select_cs(struct spi_dev_s *dev, int cs, bool select); + #undef EXTERN #if defined(__cplusplus) }