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; FAR struct sam_spidev_s *priv;
irqstate_t flags; irqstate_t flags;
#ifndef CONFIG_SPI_OWNBUS
uint32_t regaddr;
uint32_t regval;
#endif
/* The support SAM parts have only a single SPI port */ /* 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"); 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; return &priv->spidev;
} }
#endif /* CONFIG_SAM34_SPI0 */ #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); typedef void (*select_t)(enum spi_dev_e devid, bool selected);
/* Chip select register offsetrs */
/* The overall state of one SPI controller */ /* The overall state of one SPI controller */
struct sam_spidev_s struct sam_spidev_s
@ -135,7 +137,6 @@ struct sam_spidev_s
uint32_t base; /* SPI controller register base address */ uint32_t base; /* SPI controller register base address */
sem_t spisem; /* Assures mutually exclusive acess to SPI */ sem_t spisem; /* Assures mutually exclusive acess to SPI */
bool initialized; /* TRUE: Controller has been initialized */ bool initialized; /* TRUE: Controller has been initialized */
const uint32_t *csraddr; /* Addresses of CSR register */
select_t select; /* SPI select callout */ select_t select; /* SPI select callout */
/* Debug stuff */ /* Debug stuff */
@ -200,6 +201,14 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer,
* Private Data * 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 #ifdef CONFIG_SAMA5_SPI0
/* SPI0 driver operations */ /* SPI0 driver operations */
@ -226,19 +235,11 @@ static const struct spi_ops_s g_spi0ops =
.registercallback = 0, /* Not implemented */ .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 */ /* This is the overall state of the SPI0 controller */
static struct sam_spidev_s g_spi0dev = static struct sam_spidev_s g_spi0dev =
{ {
.base = SAM_SPI0_VBASE, .base = SAM_SPI0_VBASE,
.csraddr = g_csraddr0,
.select = sam_spi0select, .select = sam_spi0select,
}; };
#endif #endif
@ -269,19 +270,11 @@ static const struct spi_ops_s g_spi1ops =
.registercallback = 0, /* Not implemented */ .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 */ /* This is the overall state of the SPI0 controller */
static struct sam_spidev_s g_spi1dev = static struct sam_spidev_s g_spi1dev =
{ {
.base = SAM_SPI1_VBASE, .base = SAM_SPI1_VBASE,
.csraddr = g_csraddr1,
.select = sam_spi1select, .select = sam_spi1select,
}; };
#endif #endif
@ -392,7 +385,7 @@ static inline void spi_putreg(struct sam_spidev_s *spi, uint32_t value,
} }
#endif #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("%s:\n", msg);
spivdbg(" MR:%08x SR:%08x IMR:%08x\n", spivdbg(" MR:%08x SR:%08x IMR:%08x\n",
spi_getreg(spi, SAM_SPI_MR_OFFSET), getreg32(spi->base + SAM_SPI_MR_OFFSET),
spi_getreg(spi, SAM_SPI_SR_OFFSET), getreg32(spi->base + SAM_SPI_SR_OFFSET),
spi_getreg(spi, SAM_SPI_IMR_OFFSET)); getreg32(spi->base + SAM_SPI_IMR_OFFSET));
spivdbg(" CSR0:%08x CSR1:%08x CSR2:%08x CSR3:%08x\n", spivdbg(" CSR0:%08x CSR1:%08x CSR2:%08x CSR3:%08x\n",
spi_getreg(spi, SAM_SPI_CSR0_OFFSET), getreg32(spi->base + SAM_SPI_CSR0_OFFSET),
spi_getreg(spi, SAM_SPI_CSR1_OFFSET), getreg32(spi->base + SAM_SPI_CSR1_OFFSET),
spi_getreg(spi, SAM_SPI_CSR2_OFFSET), getreg32(spi->base + SAM_SPI_CSR2_OFFSET),
spi_getreg(spi, SAM_SPI_CSR3_OFFSET)); getreg32(spi->base + SAM_SPI_CSR3_OFFSET));
spivdbg(" WPCR:%08x WPSR:%08x\n", spivdbg(" WPCR:%08x WPSR:%08x\n",
spi_getreg(spi, SAM_SPI_WPCR_OFFSET), getreg32(spi->base + SAM_SPI_WPCR_OFFSET),
spi_getreg(spi, SAM_SPI_WPSR_OFFSET)); getreg32(spi->base + SAM_SPI_WPSR_OFFSET));
} }
#endif #endif
@ -642,7 +635,7 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
uint32_t dlybs; uint32_t dlybs;
uint32_t dlybct; uint32_t dlybct;
uint32_t regval; uint32_t regval;
uint32_t regaddr; unsigned int offset;
spivdbg("cs=%d frequency=%d\n", spics->cs, frequency); 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 */ /* Save the new scbr value */
regaddr = spi->csraddr[spics->cs]; offset = (unsigned int)g_csroffset[spics->cs];
regval = getreg32(regaddr); regval = spi_getreg(spi, offset);
regval &= ~(SPI_CSR_SCBR_MASK | SPI_CSR_DLYBS_MASK | SPI_CSR_DLYBCT_MASK); regval &= ~(SPI_CSR_SCBR_MASK | SPI_CSR_DLYBS_MASK | SPI_CSR_DLYBCT_MASK);
regval |= scbr << SPI_CSR_SCBR_SHIFT; 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; dlybct = SAM_SPI_CLOCK / 200000 / 32;
regval |= dlybct << SPI_CSR_DLYBCT_SHIFT; regval |= dlybct << SPI_CSR_DLYBCT_SHIFT;
putreg32(regval, regaddr); spi_putreg(spi, regval, offset);
/* Calculate the new actual frequency */ /* Calculate the new actual frequency */
actual = SAM_SPI_CLOCK / scbr; 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 */ /* 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_spics_s *spics = (struct sam_spics_s *)dev;
struct sam_spidev_s *spi = spi_device(spics); struct sam_spidev_s *spi = spi_device(spics);
uint32_t regval; uint32_t regval;
uint32_t regaddr; unsigned int offset;
spivdbg("cs=%d mode=%d\n", spics->cs, mode); 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 * 3 1 0
*/ */
regaddr = spi->csraddr[spics->cs]; offset = (unsigned int)g_csroffset[spics->cs];
regval = getreg32(regaddr); regval = spi_getreg(spi, offset);
regval &= ~(SPI_CSR_CPOL | SPI_CSR_NCPHA); regval &= ~(SPI_CSR_CPOL | SPI_CSR_NCPHA);
switch (mode) switch (mode)
@ -795,8 +788,8 @@ static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode)
return; return;
} }
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 mode so that subsequent re-configurations will be faster */ /* 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_spics_s *spics = (struct sam_spics_s *)dev;
struct sam_spidev_s *spi = spi_device(spics); struct sam_spidev_s *spi = spi_device(spics);
uint32_t regaddr;
uint32_t regval; uint32_t regval;
unsigned int offset;
spivdbg("cs=%d nbits=%d\n", spics->cs, nbits); spivdbg("cs=%d nbits=%d\n", spics->cs, nbits);
DEBUGASSERT(spics && nbits > 7 && nbits < 17); DEBUGASSERT(spics && nbits > 7 && nbits < 17);
@ -846,13 +839,13 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
#endif #endif
/* Yes... Set number of bits appropriately */ /* Yes... Set number of bits appropriately */
regaddr = spi->csraddr[spics->cs]; offset = (unsigned int)g_csroffset[spics->cs];
regval = getreg32(regaddr); regval = spi_getreg(spi, offset);
regval &= ~SPI_CSR_BITS_MASK; regval &= ~SPI_CSR_BITS_MASK;
regval |= SPI_CSR_BITS(nbits); 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 */ /* 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 csno = (port & __SPI_CS_MASK) >> __SPI_CS_SHIFT;
int spino = (port & __SPI_SPI_MASK) >> __SPI_SPI_SHIFT; int spino = (port & __SPI_SPI_MASK) >> __SPI_SPI_SHIFT;
irqstate_t flags; irqstate_t flags;
#ifndef CONFIG_SPI_OWNBUS
uint32_t regval;
unsigned int offset;
#endif
/* The support SAM parts have only a single SPI port */ /* 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"); 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; return &spics->spidev;
} }
#endif /* CONFIG_SAMA5_SPI0 || CONFIG_SAMA5_SPI1 */ #endif /* CONFIG_SAMA5_SPI0 || CONFIG_SAMA5_SPI1 */