SAMD: A little more SPI logic

This commit is contained in:
Gregory Nutt
2014-02-19 18:48:59 -06:00
parent 951f4ff4a3
commit 41afd1c3d8
4 changed files with 89 additions and 29 deletions
+2
View File
@@ -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 */
+1 -4
View File
@@ -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 */
+27
View File
@@ -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
View File
@@ -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
****************************************************************************/ ****************************************************************************/