drivers: spi: spi_ll_stm32: Add support for STM32MP1x SoC

Add SPI driver support for STM32MP1x SoC.

Signed-off-by: Yaël Boutreux <yael.boutreux@st.com>
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Signed-off-by: Alexandre Torgue <alexandre.torgue@st.com>
diff --git a/drivers/spi/Kconfig.stm32 b/drivers/spi/Kconfig.stm32
index be8a3aa..1147d8b 100644
--- a/drivers/spi/Kconfig.stm32
+++ b/drivers/spi/Kconfig.stm32
@@ -17,7 +17,9 @@
 
 config SPI_STM32_HAS_FIFO
 	bool
-	depends on SOC_SERIES_STM32L4X || SOC_SERIES_STM32F0X || SOC_SERIES_STM32F3X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32WBX
+	depends on (SOC_SERIES_STM32L4X || SOC_SERIES_STM32F0X || \
+	SOC_SERIES_STM32F3X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32MP1X || \
+	SOC_SERIES_STM32WBX)
 	default y
 
 config SPI_STM32_INTERRUPT
diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c
index 37362e9..fce2e17 100644
--- a/drivers/spi/spi_ll_stm32.c
+++ b/drivers/spi/spi_ll_stm32.c
@@ -31,6 +31,10 @@
  * error flag, because STM32F1 SoCs do not support it and  STM32CUBE
  * for F1 family defines an unused LL_SPI_SR_FRE.
  */
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+#define SPI_STM32_ERR_MSK (LL_SPI_SR_UDR | LL_SPI_SR_CRCE | LL_SPI_SR_MODF | \
+			   LL_SPI_SR_OVR | LL_SPI_SR_TIFRE)
+#else
 #if defined(LL_SPI_SR_UDR)
 #define SPI_STM32_ERR_MSK (LL_SPI_SR_UDR | LL_SPI_SR_CRCERR | LL_SPI_SR_MODF | \
 			   LL_SPI_SR_OVR | LL_SPI_SR_FRE)
@@ -40,6 +44,7 @@
 #else
 #define SPI_STM32_ERR_MSK (LL_SPI_SR_CRCERR | LL_SPI_SR_MODF | LL_SPI_SR_OVR)
 #endif
+#endif /* CONFIG_SOC_SERIES_STM32MP1X */
 
 /* Value to shift out when no application data needs transmitting. */
 #define SPI_STM32_TX_NOP 0x00
@@ -93,6 +98,19 @@
 	while (!ll_func_tx_is_empty(spi)) {
 		/* NOP */
 	}
+
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	/* With the STM32MP1, if the device is the SPI master, we need to enable
+	 * the start of the transfer with LL_SPI_StartMasterTransfer(spi)
+	 */
+	if (LL_SPI_GetMode(spi) == LL_SPI_MODE_MASTER) {
+		LL_SPI_StartMasterTransfer(spi);
+		while (!LL_SPI_IsActiveMasterTransfer(spi)) {
+			/* NOP */
+		}
+	}
+#endif
+
 	if (SPI_WORD_SIZE_GET(data->ctx.config->operation) == 8) {
 		LL_SPI_TransmitData8(spi, tx_frame);
 		/* The update is ignored if TX is off. */
diff --git a/drivers/spi/spi_ll_stm32.h b/drivers/spi/spi_ll_stm32.h
index 472431b..ce1618e 100644
--- a/drivers/spi/spi_ll_stm32.h
+++ b/drivers/spi/spi_ll_stm32.h
@@ -25,47 +25,92 @@
 
 static inline u32_t ll_func_tx_is_empty(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	return LL_SPI_IsActiveFlag_TXP(spi);
+#else
 	return LL_SPI_IsActiveFlag_TXE(spi);
+#endif
 }
 
 static inline u32_t ll_func_rx_is_not_empty(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	return LL_SPI_IsActiveFlag_RXP(spi);
+#else
 	return LL_SPI_IsActiveFlag_RXNE(spi);
+#endif
 }
 
 static inline void ll_func_enable_int_tx_empty(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	LL_SPI_EnableIT_TXP(spi);
+#else
 	LL_SPI_EnableIT_TXE(spi);
+#endif
 }
 
 static inline void ll_func_enable_int_rx_not_empty(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	LL_SPI_EnableIT_RXP(spi);
+#else
 	LL_SPI_EnableIT_RXNE(spi);
+#endif
 }
 
 static inline void ll_func_enable_int_errors(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	LL_SPI_EnableIT_UDR(spi);
+	LL_SPI_EnableIT_OVR(spi);
+	LL_SPI_EnableIT_CRCERR(spi);
+	LL_SPI_EnableIT_FRE(spi);
+	LL_SPI_EnableIT_MODF(spi);
+#else
 	LL_SPI_EnableIT_ERR(spi);
+#endif
 }
 
 static inline void ll_func_disable_int_tx_empty(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	LL_SPI_DisableIT_TXP(spi);
+#else
 	LL_SPI_DisableIT_TXE(spi);
+#endif
 }
 
 static inline void ll_func_disable_int_rx_not_empty(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	LL_SPI_DisableIT_RXP(spi);
+#else
 	LL_SPI_DisableIT_RXNE(spi);
+#endif
 }
 
 static inline void ll_func_disable_int_errors(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	LL_SPI_DisableIT_UDR(spi);
+	LL_SPI_DisableIT_OVR(spi);
+	LL_SPI_DisableIT_CRCERR(spi);
+	LL_SPI_DisableIT_FRE(spi);
+	LL_SPI_DisableIT_MODF(spi);
+#else
 	LL_SPI_DisableIT_ERR(spi);
+#endif
 }
 
 static inline u32_t ll_func_spi_is_busy(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	return (!LL_SPI_IsActiveFlag_MODF(spi) &&
+		!LL_SPI_IsActiveFlag_TXC(spi));
+#else
 	return LL_SPI_IsActiveFlag_BSY(spi);
+#endif
 }
 
 /* Header is compiled first, this switch avoid the compiler to lookup for
@@ -74,13 +119,37 @@
 #ifdef CONFIG_SPI_STM32_HAS_FIFO
 static inline void ll_func_set_fifo_threshold_8bit(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	LL_SPI_SetFIFOThreshold(spi, LL_SPI_FIFO_TH_01DATA);
+#else
 	LL_SPI_SetRxFIFOThreshold(spi, LL_SPI_RX_FIFO_TH_QUARTER);
+#endif
 }
 #endif
 
 static inline void ll_func_disable_spi(SPI_TypeDef *spi)
 {
+#ifdef CONFIG_SOC_SERIES_STM32MP1X
+	if (LL_SPI_IsActiveMasterTransfer(spi)) {
+		LL_SPI_SuspendMasterTransfer(spi);
+		while (LL_SPI_IsActiveMasterTransfer(spi)) {
+			/* NOP */
+		}
+	}
+
 	LL_SPI_Disable(spi);
+	while (LL_SPI_IsEnabled(spi)) {
+		/* NOP */
+	}
+
+	/* Flush RX buffer */
+	while (LL_SPI_IsActiveFlag_RXP(spi)) {
+		(void)LL_SPI_ReceiveData8(spi);
+	}
+	LL_SPI_ClearFlag_SUSP(spi);
+#else
+	LL_SPI_Disable(spi);
+#endif
 }
 
 #endif	/* ZEPHYR_DRIVERS_SPI_SPI_LL_STM32_H_ */
diff --git a/soc/arm/st_stm32/stm32mp1/soc.h b/soc/arm/st_stm32/stm32mp1/soc.h
index 2a8b366..392e010 100644
--- a/soc/arm/st_stm32/stm32mp1/soc.h
+++ b/soc/arm/st_stm32/stm32mp1/soc.h
@@ -46,6 +46,10 @@
 #include <stm32mp1xx_ll_usart.h>
 #endif
 
+#ifdef CONFIG_SPI_STM32
+#include <stm32mp1xx_ll_spi.h>
+#endif
+
 #ifdef CONFIG_IPM_STM32_IPCC
 #include <stm32mp1xx_ll_ipcc.h>
 #endif