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.
This commit is contained in:
SPRESENSE 2021-05-19 17:03:58 +09:00 committed by Alin Jerpelea
parent db340a8941
commit 67a56410ee

View File

@ -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