This is an automated email from the ASF dual-hosted git repository.

jerpelea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 67a56410ee729c3a36d830ac89cea8782cd211c7
Author: SPRESENSE <41312067+sprese...@users.noreply.github.com>
AuthorDate: Wed May 19 17:03:58 2021 +0900

    arch: cxd56xx: Prohibit clock change during SPI transfer
    
    If the system clock is changed during the SPI transfer, the SPI data can
    be corrupted. So this commit prohibits the clock change during SPI transfer,
    and keep the clock until the transfer is completed.
---
 arch/arm/src/cxd56xx/cxd56_spi.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/arch/arm/src/cxd56xx/cxd56_spi.c b/arch/arm/src/cxd56xx/cxd56_spi.c
index 5a648ed..f537e60 100644
--- a/arch/arm/src/cxd56xx/cxd56_spi.c
+++ b/arch/arm/src/cxd56xx/cxd56_spi.c
@@ -33,6 +33,7 @@
 #include <string.h>
 
 #include <arch/board/board.h>
+#include <arch/chip/pm.h>
 #include <nuttx/irq.h>
 #include <nuttx/arch.h>
 #include <nuttx/semaphore.h>
@@ -327,6 +328,11 @@ static struct cxd56_spidev_s g_spi3dev =
 };
 #endif
 
+/* Inhibit clock change */
+
+static struct pm_cpu_freqlock_s g_hold_lock =
+  PM_CPUFREQLOCK_INIT(0, PM_CPUFREQLOCK_FLAG_HOLD);
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -643,6 +649,10 @@ static uint32_t spi_send(FAR struct spi_dev_s *dev, 
uint32_t wd)
   register uint32_t regval;
   register uint32_t cr1val = 0;
 
+  /* Prohibit the clock change during SPI transfer */
+
+  up_pm_acquire_freqlock(&g_hold_lock);
+
   /* Disable clock gating (clock enable) */
 
   cxd56_spi_clock_gate_disable(priv->port);
@@ -683,6 +693,10 @@ static uint32_t spi_send(FAR struct spi_dev_s *dev, 
uint32_t wd)
 
   cxd56_spi_clock_gate_enable(priv->port);
 
+  /* Allow the clock change after SPI transfer */
+
+  up_pm_release_freqlock(&g_hold_lock);
+
   return regval;
 }
 
@@ -737,6 +751,10 @@ static void spi_do_exchange(FAR struct spi_dev_s *dev,
   tx.pv = txbuffer;
   rx.pv = rxbuffer;
 
+  /* Prohibit the clock change during SPI transfer */
+
+  up_pm_acquire_freqlock(&g_hold_lock);
+
   /* Disable clock gating (clock enable) */
 
   cxd56_spi_clock_gate_disable(priv->port);
@@ -811,6 +829,10 @@ static void spi_do_exchange(FAR struct spi_dev_s *dev,
   /* Enable clock gating (clock disable) */
 
   cxd56_spi_clock_gate_enable(priv->port);
+
+  /* Allow the clock change after SPI transfer */
+
+  up_pm_release_freqlock(&g_hold_lock);
 }
 
 /****************************************************************************
@@ -1350,6 +1372,10 @@ void spi_flush(FAR struct spi_dev_s *dev)
   FAR struct cxd56_spidev_s *priv = (FAR struct cxd56_spidev_s *)dev;
   uint32_t regval                 = 0;
 
+  /* Prohibit the clock change during SPI transfer */
+
+  up_pm_acquire_freqlock(&g_hold_lock);
+
   /* Disable clock gating (clock enable) */
 
   cxd56_spi_clock_gate_disable(priv->port);
@@ -1393,6 +1419,10 @@ void spi_flush(FAR struct spi_dev_s *dev)
   /* Enable clock gating (clock disable) */
 
   cxd56_spi_clock_gate_enable(priv->port);
+
+  /* Allow the clock change after SPI transfer */
+
+  up_pm_release_freqlock(&g_hold_lock);
 }
 
 #ifdef CONFIG_CXD56_DMAC
@@ -1414,6 +1444,10 @@ static void spi_dmaexchange(FAR struct spi_dev_s *dev,
 
   DEBUGASSERT(priv && priv->spibase);
 
+  /* Prohibit the clock change during SPI transfer */
+
+  up_pm_acquire_freqlock(&g_hold_lock);
+
   /* Disable clock gating (clock enable) */
 
   cxd56_spi_clock_gate_disable(priv->port);
@@ -1450,6 +1484,10 @@ static void spi_dmaexchange(FAR struct spi_dev_s *dev,
   /* Enable clock gating (clock disable) */
 
   cxd56_spi_clock_gate_enable(priv->port);
+
+  /* Allow the clock change after SPI transfer */
+
+  up_pm_release_freqlock(&g_hold_lock);
 }
 
 #ifndef CONFIG_SPI_EXCHANGE

Reply via email to