mirror of
https://github.com/apache/nuttx.git
synced 2026-06-05 15:58:59 +08:00
SAMD: A little more SPI logic
This commit is contained in:
@@ -202,6 +202,8 @@
|
|||||||
#define SPI_STATUS_BUFOVF (1 << 2) /* Bit 2: Buffer overflow */
|
#define SPI_STATUS_BUFOVF (1 << 2) /* Bit 2: Buffer overflow */
|
||||||
#define SPI_STATUS_SYNCBUSY (1 << 15) /* Bit 15: Synchronization busy */
|
#define SPI_STATUS_SYNCBUSY (1 << 15) /* Bit 15: Synchronization busy */
|
||||||
|
|
||||||
|
#define SPI_STATUS_CLRALL SPI_STATUS_BUFOVF
|
||||||
|
|
||||||
/* Address register */
|
/* Address register */
|
||||||
|
|
||||||
#define SPI_ADDR_SHIFT (0) /* Bits 0-7: Address */
|
#define SPI_ADDR_SHIFT (0) /* Bits 0-7: Address */
|
||||||
|
|||||||
@@ -292,14 +292,11 @@ sam_pad_configure(const struct sam_usart_config_s * const config)
|
|||||||
#ifdef SAMD_HAVE_USART
|
#ifdef SAMD_HAVE_USART
|
||||||
int sam_usart_internal(const struct sam_usart_config_s * const config)
|
int sam_usart_internal(const struct sam_usart_config_s * const config)
|
||||||
{
|
{
|
||||||
uint32_t regval;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Enable clocking to the SERCOM module in PM */
|
/* Enable clocking to the SERCOM module in PM */
|
||||||
|
|
||||||
regval = getreg32(SAM_PM_APBCMASK);
|
sercom_enable(config->sercom);
|
||||||
regval |= PM_APBCMASK_SERCOM(config->sercom);
|
|
||||||
putreg32(regval, SAM_PM_APBCMASK);
|
|
||||||
|
|
||||||
/* Configure the GCLKs for the SERCOM module */
|
/* Configure the GCLKs for the SERCOM module */
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,33 @@ extern "C"
|
|||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sercom_enable
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Enable clocking to a SERCOM module in PM
|
||||||
|
*
|
||||||
|
* Assumptions/Limitation:
|
||||||
|
* This operation is global and non-atomic. The caller should disable
|
||||||
|
* interrupts prior to calling this function.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline int sercom_enable(int sercom)
|
||||||
|
{
|
||||||
|
uint32_t regval;
|
||||||
|
|
||||||
|
/* Enable clocking to the SERCOM module in PM */
|
||||||
|
|
||||||
|
regval = getreg32(SAM_PM_APBCMASK);
|
||||||
|
regval |= PM_APBCMASK_SERCOM(sercom);
|
||||||
|
putreg32(regval, SAM_PM_APBCMASK);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
+59
-25
@@ -121,7 +121,7 @@ struct sam_spidev_s
|
|||||||
port_pinset_t pad2; /* Pin configuration for PAD2 */
|
port_pinset_t pad2; /* Pin configuration for PAD2 */
|
||||||
port_pinset_t pad3; /* Pin configuration for PAD3 */
|
port_pinset_t pad3; /* Pin configuration for PAD3 */
|
||||||
uint32_t muxconfig; /* Pad multiplexing configuration */
|
uint32_t muxconfig; /* Pad multiplexing configuration */
|
||||||
uint32_t frequency; /* Source clock frequency */
|
uint32_t srcfreq; /* Source clock frequency */
|
||||||
uintptr_t base; /* SERCOM base address */
|
uintptr_t base; /* SERCOM base address */
|
||||||
|
|
||||||
/* Dynamic configuration */
|
/* Dynamic configuration */
|
||||||
@@ -157,17 +157,17 @@ static bool spi_checkreg(struct sam_spidev_s *spi, bool wr,
|
|||||||
# define spi_checkreg(spi,wr,regval,regaddr) (false)
|
# define spi_checkreg(spi,wr,regval,regaddr) (false)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline uint8_t spi_getreg8(struct sam_spidev_s *spi,
|
static uint8_t spi_getreg8(struct sam_spidev_s *spi,
|
||||||
unsigned int offset);
|
unsigned int offset);
|
||||||
static inline void spi_putreg8(struct sam_spidev_s *spi, uint8_t regval,
|
static void spi_putreg8(struct sam_spidev_s *spi, uint8_t regval,
|
||||||
unsigned int offset);
|
unsigned int offset);
|
||||||
static inline uint16_t spi_getreg16(struct sam_spidev_s *spi,
|
static uint16_t spi_getreg16(struct sam_spidev_s *spi,
|
||||||
unsigned int offset);
|
unsigned int offset);
|
||||||
static inline void spi_putreg16(struct sam_spidev_s *spi, uint16_t regval,
|
static void spi_putreg16(struct sam_spidev_s *spi, uint16_t regval,
|
||||||
unsigned int offset);
|
unsigned int offset);
|
||||||
static inline uint32_t spi_getreg32(struct sam_spidev_s *spi,
|
static uint32_t spi_getreg32(struct sam_spidev_s *spi,
|
||||||
unsigned int offset);
|
unsigned int offset);
|
||||||
static inline void spi_putreg32(struct sam_spidev_s *spi, uint32_t regval,
|
static void spi_putreg32(struct sam_spidev_s *spi, uint32_t regval,
|
||||||
unsigned int offset);
|
unsigned int offset);
|
||||||
|
|
||||||
#if defined(CONFIG_DEBUG_SPI) && defined(CONFIG_DEBUG_VERBOSE)
|
#if defined(CONFIG_DEBUG_SPI) && defined(CONFIG_DEBUG_VERBOSE)
|
||||||
@@ -194,6 +194,10 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer,
|
|||||||
size_t nwords);
|
size_t nwords);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Initialization */
|
||||||
|
|
||||||
|
static void spi_pad_configure(struct sam_spidev_s *priv);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -237,7 +241,7 @@ static struct sam_spidev_s g_spi0dev =
|
|||||||
.pad2 = BOARD_SERCOM0_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM0_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM0_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM0_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM0_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM0_MUXCONFIG,
|
||||||
.frequency = BOARD_SERCOM0_FREQUENCY,
|
.srcfreq = BOARD_SERCOM0_FREQUENCY,
|
||||||
.base = SAM_SERCOM0_BASE,
|
.base = SAM_SERCOM0_BASE,
|
||||||
#ifndef CONFIG_SPI_OWNBUS
|
#ifndef CONFIG_SPI_OWNBUS
|
||||||
.spilock = SEM_INITIALIZER(1),
|
.spilock = SEM_INITIALIZER(1),
|
||||||
@@ -284,7 +288,7 @@ static struct sam_spidev_s g_spi1dev =
|
|||||||
.pad2 = BOARD_SERCOM1_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM1_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM1_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM1_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM1_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM1_MUXCONFIG,
|
||||||
.frequency = BOARD_SERCOM1_FREQUENCY,
|
.srcfreq = BOARD_SERCOM1_FREQUENCY,
|
||||||
.base = SAM_SERCOM1_BASE,
|
.base = SAM_SERCOM1_BASE,
|
||||||
#ifndef CONFIG_SPI_OWNBUS
|
#ifndef CONFIG_SPI_OWNBUS
|
||||||
.spilock = SEM_INITIALIZER(1),
|
.spilock = SEM_INITIALIZER(1),
|
||||||
@@ -331,7 +335,7 @@ static struct sam_spidev_s g_spi2dev =
|
|||||||
.pad2 = BOARD_SERCOM2_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM2_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM2_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM2_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM2_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM2_MUXCONFIG,
|
||||||
.frequency = BOARD_SERCOM2_FREQUENCY,
|
.srcfreq = BOARD_SERCOM2_FREQUENCY,
|
||||||
.base = SAM_SERCOM2_BASE,
|
.base = SAM_SERCOM2_BASE,
|
||||||
#ifndef CONFIG_SPI_OWNBUS
|
#ifndef CONFIG_SPI_OWNBUS
|
||||||
.spilock = SEM_INITIALIZER(1),
|
.spilock = SEM_INITIALIZER(1),
|
||||||
@@ -378,7 +382,7 @@ static struct sam_spidev_s g_spi3dev =
|
|||||||
.pad2 = BOARD_SERCOM3_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM3_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM3_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM3_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM3_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM3_MUXCONFIG,
|
||||||
.frequency = BOARD_SERCOM3_FREQUENCY,
|
.srcfreq = BOARD_SERCOM3_FREQUENCY,
|
||||||
.base = SAM_SERCOM3_BASE,
|
.base = SAM_SERCOM3_BASE,
|
||||||
#ifndef CONFIG_SPI_OWNBUS
|
#ifndef CONFIG_SPI_OWNBUS
|
||||||
.spilock = SEM_INITIALIZER(1),
|
.spilock = SEM_INITIALIZER(1),
|
||||||
@@ -425,7 +429,7 @@ static struct sam_spidev_s g_spi4dev =
|
|||||||
.pad2 = BOARD_SERCOM4_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM4_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM4_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM4_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM4_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM4_MUXCONFIG,
|
||||||
.frequency = BOARD_SERCOM4_FREQUENCY,
|
.srcfreq = BOARD_SERCOM4_FREQUENCY,
|
||||||
.base = SAM_SERCOM4_BASE,
|
.base = SAM_SERCOM4_BASE,
|
||||||
#ifndef CONFIG_SPI_OWNBUS
|
#ifndef CONFIG_SPI_OWNBUS
|
||||||
.spilock = SEM_INITIALIZER(1),
|
.spilock = SEM_INITIALIZER(1),
|
||||||
@@ -472,7 +476,7 @@ static struct sam_spidev_s g_spi5dev =
|
|||||||
.pad2 = BOARD_SERCOM5_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM5_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM5_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM5_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM5_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM5_MUXCONFIG,
|
||||||
.frequency = BOARD_SERCOM5_FREQUENCY,
|
.srcfreq = BOARD_SERCOM5_FREQUENCY,
|
||||||
.base = SAM_SERCOM5_BASE,
|
.base = SAM_SERCOM5_BASE,
|
||||||
#ifndef CONFIG_SPI_OWNBUS
|
#ifndef CONFIG_SPI_OWNBUS
|
||||||
.spilock = SEM_INITIALIZER(1),
|
.spilock = SEM_INITIALIZER(1),
|
||||||
@@ -550,8 +554,7 @@ static bool spi_checkreg(struct sam_spidev_s *priv, bool wr, uint32_t regval,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline uint8_t spi_getreg8(struct sam_spidev_s *priv,
|
static uint8_t spi_getreg8(struct sam_spidev_s *priv, unsigned int offset)
|
||||||
unsigned int offset)
|
|
||||||
{
|
{
|
||||||
uintptr_t regaddr = priv->base + offset;
|
uintptr_t regaddr = priv->base + offset;
|
||||||
uint8_t regval = getreg8(regaddr);
|
uint8_t regval = getreg8(regaddr);
|
||||||
@@ -574,8 +577,8 @@ static inline uint8_t spi_getreg8(struct sam_spidev_s *priv,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void spi_putreg8(struct sam_spidev_s *priv, uint8_t regval,
|
static void spi_putreg8(struct sam_spidev_s *priv, uint8_t regval,
|
||||||
unsigned int offset)
|
unsigned int offset)
|
||||||
{
|
{
|
||||||
uintptr_t regaddr = priv->base + offset;
|
uintptr_t regaddr = priv->base + offset;
|
||||||
|
|
||||||
@@ -597,8 +600,7 @@ static inline void spi_putreg8(struct sam_spidev_s *priv, uint8_t regval,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline uint16_t spi_getreg16(struct sam_spidev_s *priv,
|
static uint16_t spi_getreg16(struct sam_spidev_s *priv, unsigned int offset)
|
||||||
unsigned int offset)
|
|
||||||
{
|
{
|
||||||
uintptr_t regaddr = priv->base + offset;
|
uintptr_t regaddr = priv->base + offset;
|
||||||
uint16_t regval = getreg16(regaddr);
|
uint16_t regval = getreg16(regaddr);
|
||||||
@@ -621,8 +623,8 @@ static inline uint16_t spi_getreg16(struct sam_spidev_s *priv,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void spi_putreg16(struct sam_spidev_s *priv, uint16_t regval,
|
static void spi_putreg16(struct sam_spidev_s *priv, uint16_t regval,
|
||||||
unsigned int offset)
|
unsigned int offset)
|
||||||
{
|
{
|
||||||
uintptr_t regaddr = priv->base + offset;
|
uintptr_t regaddr = priv->base + offset;
|
||||||
|
|
||||||
@@ -644,8 +646,7 @@ static inline void spi_putreg16(struct sam_spidev_s *priv, uint16_t regval,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline uint32_t spi_getreg32(struct sam_spidev_s *priv,
|
static uint32_t spi_getreg32(struct sam_spidev_s *priv, unsigned int offset)
|
||||||
unsigned int offset)
|
|
||||||
{
|
{
|
||||||
uintptr_t regaddr = priv->base + offset;
|
uintptr_t regaddr = priv->base + offset;
|
||||||
uint32_t regval = getreg32(regaddr);
|
uint32_t regval = getreg32(regaddr);
|
||||||
@@ -668,8 +669,8 @@ static inline uint32_t spi_getreg32(struct sam_spidev_s *priv,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void spi_putreg32(struct sam_spidev_s *priv, uint32_t regval,
|
static void spi_putreg32(struct sam_spidev_s *priv, uint32_t regval,
|
||||||
unsigned int offset)
|
unsigned int offset)
|
||||||
{
|
{
|
||||||
uintptr_t regaddr = priv->base + offset;
|
uintptr_t regaddr = priv->base + offset;
|
||||||
|
|
||||||
@@ -1130,6 +1131,39 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer, size_t nwords)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: spi_pad_configure
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure the SERCOM SPI pads.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void spi_pad_configure(struct sam_spidev_s *priv)
|
||||||
|
{
|
||||||
|
/* Configure SERCOM pads */
|
||||||
|
|
||||||
|
if (priv->pad0 != 0)
|
||||||
|
{
|
||||||
|
sam_configport(priv->pad0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->pad1 != 0)
|
||||||
|
{
|
||||||
|
sam_configport(priv->pad1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->pad2 != 0)
|
||||||
|
{
|
||||||
|
sam_configport(priv->pad2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->pad3 != 0)
|
||||||
|
{
|
||||||
|
sam_configport(priv->pad3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
Reference in New Issue
Block a user