SAMA5: SPI Driver + AT25 FLASH work; SAM3/4: Correct an error, SPI will not be correctly configured if CONFIG_SPI_OWNBUS=n

This commit is contained in:
Gregory Nutt 2013-08-05 10:29:43 -06:00
parent 36f4cb53dd
commit cff3e713f1
2 changed files with 75 additions and 42 deletions

View File

@ -896,6 +896,10 @@ FAR struct spi_dev_s *up_spiinitialize(int cs)
{
FAR struct sam_spidev_s *priv;
irqstate_t flags;
#ifndef CONFIG_SPI_OWNBUS
uint32_t regaddr;
uint32_t regval;
#endif
/* The support SAM parts have only a single SPI port */
@ -985,6 +989,22 @@ FAR struct spi_dev_s *up_spiinitialize(int cs)
spi_dumpregs("After initialization");
}
#ifndef CONFIG_SPI_OWNBUS
/* Set to mode=0 and nbits=8 and impossible frequency. It is only
* critical to do this if CONFIG_SPI_OWNBUS is not defined because in
* that case, the SPI will only be reconfigured if there is a change.
*/
regaddr = g_csraddr[cs];
regval = getreg32(regaddr);
regval &= ~(SPI_CSR_CPOL | SPI_CSR_NCPHA | SPI_CSR_BITS_MASK);
regval |= (SPI_CSR_NCPHA | SPI_CSR_BITS(8));
putreg32(regval, regaddr);
priv->nbits = 8;
spivdbg("csr[%08x]=%08x\n", regaddr, regval);
#endif
return &priv->spidev;
}
#endif /* CONFIG_SAM34_SPI0 */

View File

@ -128,6 +128,8 @@ struct sam_spics_s
typedef void (*select_t)(enum spi_dev_e devid, bool selected);
/* Chip select register offsetrs */
/* The overall state of one SPI controller */
struct sam_spidev_s
@ -135,7 +137,6 @@ struct sam_spidev_s
uint32_t base; /* SPI controller register base address */
sem_t spisem; /* Assures mutually exclusive acess to SPI */
bool initialized; /* TRUE: Controller has been initialized */
const uint32_t *csraddr; /* Addresses of CSR register */
select_t select; /* SPI select callout */
/* Debug stuff */
@ -200,6 +201,14 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer,
* Private Data
****************************************************************************/
/* This array maps chip select numbers (0-3) to CSR register offsets */
static const uint8_t g_csroffset[4] =
{
SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR1_OFFSET,
SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR3_OFFSET
};
#ifdef CONFIG_SAMA5_SPI0
/* SPI0 driver operations */
@ -226,19 +235,11 @@ static const struct spi_ops_s g_spi0ops =
.registercallback = 0, /* Not implemented */
};
/* This array maps chip select numbers (0-3) to CSR register addresses */
static const uint32_t g_csraddr0[4] =
{
SAM_SPI0_CSR0, SAM_SPI0_CSR1, SAM_SPI0_CSR2, SAM_SPI0_CSR3
};
/* This is the overall state of the SPI0 controller */
static struct sam_spidev_s g_spi0dev =
{
.base = SAM_SPI0_VBASE,
.csraddr = g_csraddr0,
.select = sam_spi0select,
};
#endif
@ -269,19 +270,11 @@ static const struct spi_ops_s g_spi1ops =
.registercallback = 0, /* Not implemented */
};
/* This array maps chip select numbers (0-3) to CSR register addresses */
static const uint32_t g_csraddr1[4] =
{
SAM_SPI1_CSR0, SAM_SPI1_CSR1, SAM_SPI1_CSR2, SAM_SPI1_CSR3
};
/* This is the overall state of the SPI0 controller */
static struct sam_spidev_s g_spi1dev =
{
.base = SAM_SPI1_VBASE,
.csraddr = g_csraddr1,
.select = sam_spi1select,
};
#endif
@ -392,7 +385,7 @@ static inline void spi_putreg(struct sam_spidev_s *spi, uint32_t value,
}
#endif
spi_putreg(spi, value, address);
putreg32(value, address);
}
/****************************************************************************
@ -415,17 +408,17 @@ static void spi_dumpregs(struct sam_spidev_s *spi, const char *msg)
{
spivdbg("%s:\n", msg);
spivdbg(" MR:%08x SR:%08x IMR:%08x\n",
spi_getreg(spi, SAM_SPI_MR_OFFSET),
spi_getreg(spi, SAM_SPI_SR_OFFSET),
spi_getreg(spi, SAM_SPI_IMR_OFFSET));
getreg32(spi->base + SAM_SPI_MR_OFFSET),
getreg32(spi->base + SAM_SPI_SR_OFFSET),
getreg32(spi->base + SAM_SPI_IMR_OFFSET));
spivdbg(" CSR0:%08x CSR1:%08x CSR2:%08x CSR3:%08x\n",
spi_getreg(spi, SAM_SPI_CSR0_OFFSET),
spi_getreg(spi, SAM_SPI_CSR1_OFFSET),
spi_getreg(spi, SAM_SPI_CSR2_OFFSET),
spi_getreg(spi, SAM_SPI_CSR3_OFFSET));
getreg32(spi->base + SAM_SPI_CSR0_OFFSET),
getreg32(spi->base + SAM_SPI_CSR1_OFFSET),
getreg32(spi->base + SAM_SPI_CSR2_OFFSET),
getreg32(spi->base + SAM_SPI_CSR3_OFFSET));
spivdbg(" WPCR:%08x WPSR:%08x\n",
spi_getreg(spi, SAM_SPI_WPCR_OFFSET),
spi_getreg(spi, SAM_SPI_WPSR_OFFSET));
getreg32(spi->base + SAM_SPI_WPCR_OFFSET),
getreg32(spi->base + SAM_SPI_WPSR_OFFSET));
}
#endif
@ -642,7 +635,7 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
uint32_t dlybs;
uint32_t dlybct;
uint32_t regval;
uint32_t regaddr;
unsigned int offset;
spivdbg("cs=%d frequency=%d\n", spics->cs, frequency);
@ -677,8 +670,8 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
/* Save the new scbr value */
regaddr = spi->csraddr[spics->cs];
regval = getreg32(regaddr);
offset = (unsigned int)g_csroffset[spics->cs];
regval = spi_getreg(spi, offset);
regval &= ~(SPI_CSR_SCBR_MASK | SPI_CSR_DLYBS_MASK | SPI_CSR_DLYBCT_MASK);
regval |= scbr << SPI_CSR_SCBR_SHIFT;
@ -711,12 +704,12 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
dlybct = SAM_SPI_CLOCK / 200000 / 32;
regval |= dlybct << SPI_CSR_DLYBCT_SHIFT;
putreg32(regval, regaddr);
spi_putreg(spi, regval, offset);
/* Calculate the new actual frequency */
actual = SAM_SPI_CLOCK / scbr;
spivdbg("csr[%08x]=%08x actual=%d\n", regaddr, regval, actual);
spivdbg("csr[offset=%02x]=%08x actual=%d\n", offset, regval, actual);
/* Save the frequency setting */
@ -749,7 +742,7 @@ static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode)
struct sam_spics_s *spics = (struct sam_spics_s *)dev;
struct sam_spidev_s *spi = spi_device(spics);
uint32_t regval;
uint32_t regaddr;
unsigned int offset;
spivdbg("cs=%d mode=%d\n", spics->cs, mode);
@ -769,8 +762,8 @@ static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode)
* 3 1 0
*/
regaddr = spi->csraddr[spics->cs];
regval = getreg32(regaddr);
offset = (unsigned int)g_csroffset[spics->cs];
regval = spi_getreg(spi, offset);
regval &= ~(SPI_CSR_CPOL | SPI_CSR_NCPHA);
switch (mode)
@ -795,8 +788,8 @@ static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode)
return;
}
putreg32(regval, regaddr);
spivdbg("csr[%08x]=%08x\n", regaddr, regval);
spi_putreg(spi, regval, offset);
spivdbg("csr[offset=%02x]=%08x\n", offset, regval);
/* Save the mode so that subsequent re-configurations will be faster */
@ -825,8 +818,8 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
{
struct sam_spics_s *spics = (struct sam_spics_s *)dev;
struct sam_spidev_s *spi = spi_device(spics);
uint32_t regaddr;
uint32_t regval;
unsigned int offset;
spivdbg("cs=%d nbits=%d\n", spics->cs, nbits);
DEBUGASSERT(spics && nbits > 7 && nbits < 17);
@ -846,13 +839,13 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
#endif
/* Yes... Set number of bits appropriately */
regaddr = spi->csraddr[spics->cs];
regval = getreg32(regaddr);
offset = (unsigned int)g_csroffset[spics->cs];
regval = spi_getreg(spi, offset);
regval &= ~SPI_CSR_BITS_MASK;
regval |= SPI_CSR_BITS(nbits);
putreg32(regval, regaddr);
spi_putreg(spi, regval, offset);
spivdbg("csr[%08x]=%08x\n", regaddr, regval);
spivdbg("csr[offset=%02x]=%08x\n", offset, regval);
/* Save the selection so the subsequence re-configurations will be faster */
@ -1105,6 +1098,10 @@ struct spi_dev_s *up_spiinitialize(int port)
int csno = (port & __SPI_CS_MASK) >> __SPI_CS_SHIFT;
int spino = (port & __SPI_SPI_MASK) >> __SPI_SPI_SHIFT;
irqstate_t flags;
#ifndef CONFIG_SPI_OWNBUS
uint32_t regval;
unsigned int offset;
#endif
/* The support SAM parts have only a single SPI port */
@ -1231,6 +1228,22 @@ struct spi_dev_s *up_spiinitialize(int port)
spi_dumpregs(spi, "After initialization");
}
#ifndef CONFIG_SPI_OWNBUS
/* Set to mode=0 and nbits=8 and impossible frequency. It is only
* critical to do this if CONFIG_SPI_OWNBUS is not defined because in
* that case, the SPI will only be reconfigured if there is a change.
*/
offset = (unsigned int)g_csroffset[csno];
regval = spi_getreg(spi, offset);
regval &= ~(SPI_CSR_CPOL | SPI_CSR_NCPHA | SPI_CSR_BITS_MASK);
regval |= (SPI_CSR_NCPHA | SPI_CSR_BITS(8));
spi_putreg(spi, regval, offset);
spics->nbits = 8;
spivdbg("csr[offset=%02x]=%08x\n", offset, regval);
#endif
return &spics->spidev;
}
#endif /* CONFIG_SAMA5_SPI0 || CONFIG_SAMA5_SPI1 */