arch/mips/src/pic32mz/pic32mz-spi.c: Fix SPI Mode selection. CKE is the inversion of the CPHA.

This commit is contained in:
Ouss4 2019-07-21 15:57:06 -06:00 committed by Gregory Nutt
parent 1812d6f515
commit 145970a266
2 changed files with 107 additions and 82 deletions

View File

@ -77,10 +77,10 @@
#define PIC32MZ_SPI_BRGSET_OFFSET 0x0038 /* SPI baud rate set register */ #define PIC32MZ_SPI_BRGSET_OFFSET 0x0038 /* SPI baud rate set register */
#define PIC32MZ_SPI_BRGINV_OFFSET 0x003c /* SPI baud rate invert register */ #define PIC32MZ_SPI_BRGINV_OFFSET 0x003c /* SPI baud rate invert register */
#define PIC32MZ_SPI_CON2_OFFSET 0x0040 /* SPI control register 2*/ #define PIC32MZ_SPI_CON2_OFFSET 0x0040 /* SPI control register 2 */
#define PIC32MZ_SPI_CON2CLR_OFFSET 0x0040 /* SPI control register 2*/ #define PIC32MZ_SPI_CON2CLR_OFFSET 0x0044 /* SPI control clear register 2 */
#define PIC32MZ_SPI_CON2SET_OFFSET 0x0040 /* SPI control register 2*/ #define PIC32MZ_SPI_CON2SET_OFFSET 0x0048 /* SPI control set register 2 */
#define PIC32MZ_SPI_CON2INV_OFFSET 0x0040 /* SPI control register 2*/ #define PIC32MZ_SPI_CON2INV_OFFSET 0x004c /* SPI control invert register 2 */
/* SPI Peripheral Addresses *************************************************/ /* SPI Peripheral Addresses *************************************************/

View File

@ -63,6 +63,7 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* All SPI peripherals are clocked by PBCLK2 */ /* All SPI peripherals are clocked by PBCLK2 */
#define BOARD_PBCLOCK BOARD_PBCLK2 #define BOARD_PBCLOCK BOARD_PBCLK2
@ -70,6 +71,7 @@
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
/* This structure describes the fixed (ROM-able) configuration of the SPI /* This structure describes the fixed (ROM-able) configuration of the SPI
* peripheral. * peripheral.
*/ */
@ -110,6 +112,7 @@ struct pic32mz_dev_s
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
/* Low-level register access */ /* Low-level register access */
#ifdef CONFIG_PIC32MZ_SPI_REGDEBUG #ifdef CONFIG_PIC32MZ_SPI_REGDEBUG
@ -137,7 +140,8 @@ static void spi_exchange8(FAR struct pic32mz_dev_s *priv,
/* SPI methods */ /* SPI methods */
static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
static void spi_setbits(FAR struct spi_dev_s *dev, int nbits); static void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch);
@ -195,13 +199,16 @@ static const struct pic32mz_config_s g_spi1config =
#endif #endif
.sdipps = BOARD_SDI1_PPS, .sdipps = BOARD_SDI1_PPS,
.sdopps = PPS_OUTPUT_REGVAL(BOARD_SDO1_PPS), .sdopps = PPS_OUTPUT_REGVAL(BOARD_SDO1_PPS),
.sdoreg = PPS_OUTPUT_REGADDR(BOARD_SDO1_PPS), .sdoreg = PPS_OUTPUT_REGADDR(BOARD_SDO1_PPS)
}; };
static struct pic32mz_dev_s g_spi1dev = static struct pic32mz_dev_s g_spi1dev =
{ {
.spidev = { &g_spi1ops }, .spidev =
.config = &g_spi1config, {
&g_spi1ops
},
.config = &g_spi1config
}; };
#endif #endif
@ -246,7 +253,10 @@ static const struct pic32mz_config_s g_spi2config =
static struct pic32mz_dev_s g_spi2dev = static struct pic32mz_dev_s g_spi2dev =
{ {
.spidev = { &g_spi2ops }, .spidev =
{
&g_spi2ops
},
.config = &g_spi2config, .config = &g_spi2config,
}; };
#endif #endif
@ -292,7 +302,10 @@ static const struct pic32mz_config_s g_spi3config =
static struct pic32mz_dev_s g_spi3dev = static struct pic32mz_dev_s g_spi3dev =
{ {
.spidev = { &g_spi3ops }, .spidev =
{
&g_spi3ops
},
.config = &g_spi3config, .config = &g_spi3config,
}; };
#endif #endif
@ -338,7 +351,10 @@ static const struct pic32mz_config_s g_spi4config =
static struct pic32mz_dev_s g_spi4dev = static struct pic32mz_dev_s g_spi4dev =
{ {
.spidev = { &g_spi4ops }, .spidev =
{
&g_spi4ops
},
.config = &g_spi4config, .config = &g_spi4config,
}; };
#endif #endif
@ -384,7 +400,10 @@ static const struct pic32mz_config_s g_spi5config =
static struct pic32mz_dev_s g_spi5dev = static struct pic32mz_dev_s g_spi5dev =
{ {
.spidev = { &g_spi5ops }, .spidev =
{
&g_spi5ops
},
.config = &g_spi5config, .config = &g_spi5config,
}; };
#endif #endif
@ -430,7 +449,10 @@ static const struct pic32mz_config_s g_spi6config =
static struct pic32mz_dev_s g_spi6dev = static struct pic32mz_dev_s g_spi6dev =
{ {
.spidev = { &g_spi6ops }, .spidev =
{
&g_spi6ops
},
.config = &g_spi6config, .config = &g_spi6config,
}; };
#endif #endif
@ -482,7 +504,7 @@ static bool spi_checkreg(struct pic32mz_dev_s *priv, uintptr_t regaddr,
{ {
/* Yes... show how many times we did it */ /* Yes... show how many times we did it */
_info("...[Repeats %d times]...\n", priv->ntimes); spiinfo("...[Repeats %d times]...\n", priv->ntimes);
} }
/* Save information about the new access */ /* Save information about the new access */
@ -532,7 +554,7 @@ static uint32_t spi_getreg(FAR struct pic32mz_dev_s *priv,
{ {
/* Yes.. */ /* Yes.. */
_info("%08lx->%08lx\n", spiinfo("%08lx->%08lx\n",
(unsigned long)regaddr, (unsigned long)regval); (unsigned long)regaddr, (unsigned long)regval);
} }
@ -574,7 +596,7 @@ static void spi_putaddr(FAR struct pic32mz_dev_s *priv, uintptr_t regaddr,
{ {
/* Yes.. */ /* Yes.. */
_info("%08lx<-%08lx\n", spiinfo("%08lx<-%08lx\n",
(unsigned long)regaddr, (unsigned long)regval); (unsigned long)regaddr, (unsigned long)regval);
} }
@ -641,7 +663,7 @@ static void spi_exchange8(FAR struct pic32mz_dev_s *priv,
spiinfo("nbytes: %d\n", nbytes); spiinfo("nbytes: %d\n", nbytes);
while (nbytes) while (nbytes)
{ {
/* Write the data to transmitted to the SPI Data Register */ /* Write the data to be transmitted to the SPI Data Register */
if (txbuffer) if (txbuffer)
{ {
@ -663,7 +685,8 @@ static void spi_exchange8(FAR struct pic32mz_dev_s *priv,
while ((spi_getreg(priv, PIC32MZ_SPI_STAT_OFFSET) & SPI_STAT_SPIRBE) != 0); while ((spi_getreg(priv, PIC32MZ_SPI_STAT_OFFSET) & SPI_STAT_SPIRBE) != 0);
#else #else
/* Wait for the SPIRBF bit in the SPI Status Register to be set to 1. In /* Wait for the SPIRBF bit in the SPI Status Register to be set to 1. In
* normal mode, the SPIRBF bit will be set when receive data is available. * normal mode, the SPIRBF bit will be set when receive data is
* available.
*/ */
while ((spi_getreg(priv, PIC32MZ_SPI_STAT_OFFSET) & SPI_STAT_SPIRBF) == 0); while ((spi_getreg(priv, PIC32MZ_SPI_STAT_OFFSET) & SPI_STAT_SPIRBF) == 0);
@ -822,7 +845,8 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct pic32mz_dev_s *priv = (FAR struct pic32mz_dev_s *)dev; FAR struct pic32mz_dev_s *priv = (FAR struct pic32mz_dev_s *)dev;
uint32_t divisor; uint32_t divisor;
@ -901,7 +925,6 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
{ {
FAR struct pic32mz_dev_s *priv = (FAR struct pic32mz_dev_s *)dev; FAR struct pic32mz_dev_s *priv = (FAR struct pic32mz_dev_s *)dev;
uint32_t regval;
spiinfo("Old mode: %d New mode: %d\n", priv->mode, mode); spiinfo("Old mode: %d New mode: %d\n", priv->mode, mode);
@ -928,7 +951,7 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
* *
* CON Register mapping: * CON Register mapping:
* CPOL=0 corresponds to CON:CKP=0; CPOL=1 corresponds to CON:CKP=1 * CPOL=0 corresponds to CON:CKP=0; CPOL=1 corresponds to CON:CKP=1
* CPHA=0 corresponds to CON:CKE=1; CPHA=1 corresponds to CON:CKE=1 * CPHA=0 corresponds to CON:CKE=1; CPHA=1 corresponds to CON:CKE=0
* *
* In addition, the CON register supports SMP: SPI Data Input Sample * In addition, the CON register supports SMP: SPI Data Input Sample
* Phase bit: * Phase bit:
@ -939,24 +962,26 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
* Which is hardcoded to 1. * Which is hardcoded to 1.
*/ */
regval = spi_getreg(priv, PIC32MZ_SPI_CON_OFFSET);
regval &= ~(SPI_CON_CKP | SPI_CON_CKE);
switch (mode) switch (mode)
{ {
case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */ case SPIDEV_MODE0: /* CPOL=0; CPHA=0 => CKP=0; CKE=1 */
spi_putreg(priv, PIC32MZ_SPI_CONCLR_OFFSET, SPI_CON_CKP);
spi_putreg(priv, PIC32MZ_SPI_CONSET_OFFSET, SPI_CON_CKE);
break; break;
case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */ case SPIDEV_MODE1: /* CPOL=0; CPHA=1 => CKP=0; CKE=0 */
regval |= SPI_CON_CKE; spi_putreg(priv, PIC32MZ_SPI_CONCLR_OFFSET, SPI_CON_CKP);
spi_putreg(priv, PIC32MZ_SPI_CONCLR_OFFSET, SPI_CON_CKE);
break; break;
case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */ case SPIDEV_MODE2: /* CPOL=1; CPHA=0 => CKP=1; CKE=1 */
regval |= SPI_CON_CKP; spi_putreg(priv, PIC32MZ_SPI_CONSET_OFFSET, SPI_CON_CKP);
spi_putreg(priv, PIC32MZ_SPI_CONSET_OFFSET, SPI_CON_CKE);
break; break;
case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */ case SPIDEV_MODE3: /* CPOL=1; CPHA=1 => CKP=1; CKE=0 */
regval |= (SPI_CON_CKP | SPI_CON_CKE); spi_putreg(priv, PIC32MZ_SPI_CONSET_OFFSET, SPI_CON_CKP);
spi_putreg(priv, PIC32MZ_SPI_CONCLR_OFFSET, SPI_CON_CKE);
break; break;
default: default:
@ -964,10 +989,9 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
return; return;
} }
spi_putreg(priv, PIC32MZ_SPI_CON_OFFSET, regval); spiinfo("CON: %08x\n", spi_getreg(priv, PIC32MZ_SPI_CON_OFFSET));
spiinfo("CON: %08x\n", regval);
/* Save the mode so that subsequent re-configuratins will be faster */ /* Save the mode so that subsequent re-configurations will be faster */
priv->mode = mode; priv->mode = mode;
} }
@ -1009,11 +1033,11 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
} }
else if (nbits == 16) else if (nbits == 16)
{ {
setting = SPI_CON_MODE_8BIT; setting = SPI_CON_MODE_16BIT;
} }
else if (nbits == 32) else if (nbits == 32)
{ {
setting = SPI_CON_MODE_8BIT; setting = SPI_CON_MODE_32BIT;
} }
else else
{ {
@ -1024,7 +1048,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
regval = spi_getreg(priv, PIC32MZ_SPI_CON_OFFSET); regval = spi_getreg(priv, PIC32MZ_SPI_CON_OFFSET);
regval &= ~SPI_CON_MODE_MASK; regval &= ~SPI_CON_MODE_MASK;
regval |= setting; regval |= setting;
regval = spi_getreg(priv, PIC32MZ_SPI_CON_OFFSET); spi_putreg(priv, PIC32MZ_SPI_CON_OFFSET, regval);
spiinfo("CON: %08x\n", regval); spiinfo("CON: %08x\n", regval);
/* Save the selection so the subsequence re-configurations will be /* Save the selection so the subsequence re-configurations will be
@ -1095,8 +1119,8 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* Input Parameters: * Input Parameters:
* dev - Device-specific state data * dev - Device-specific state data
* txbuffer - A pointer to the buffer of data to be sent * txbuffer - A pointer to the buffer of data to be sent
* rxbuffer - A pointer to the buffer in which to recieve data * rxbuffer - A pointer to the buffer in which to receive data
* nwords - the length of data that to be exchanged in units of words. * nwords - The length of data that to be exchanged in units of words.
* The wordsize is determined by the number of bits-per-word * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into * packed into uint8_t's; if nbits >8, the data is packed into
@ -1167,7 +1191,7 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
* *
* Input Parameters: * Input Parameters:
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to recieve data * buffer - A pointer to the buffer in which to receive data
* nwords - the length of data that can be received in the buffer in * nwords - the length of data that can be received in the buffer in
* number of words. The wordsize is determined by the number of * number of words. The wordsize is determined by the number of
* bits-per-word selected for the SPI interface. If nbits <= 8, * bits-per-word selected for the SPI interface. If nbits <= 8,
@ -1200,10 +1224,10 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
* Initialize the selected SPI port * Initialize the selected SPI port
* *
* Input Parameters: * Input Parameters:
* Port number (for hardware that has mutiple SPI interfaces) * Port number (for hardware that has multiple SPI interfaces)
* *
* Returned Value: * Returned Value:
* Valid SPI device structure reference on succcess; a NULL on failure * Valid SPI device structure reference on success; a NULL on failure
* *
****************************************************************************/ ****************************************************************************/
@ -1338,7 +1362,8 @@ FAR struct spi_dev_s *pic32mz_spibus_initialize(int port)
* board-specific pic32mz_spiNselect() interface. * board-specific pic32mz_spiNselect() interface.
*/ */
regval = (SPI_CON_MSTEN | SPI_CON_SMP | SPI_CON_MODE_8BIT | SPI_CON_ON); regval = (SPI_CON_MSTEN | SPI_CON_SMP | SPI_CON_MODE_8BIT |
SPI_CON_CKE | SPI_CON_ON);
/* Set the ENHBUF bit if using Enhanced Buffer mode. */ /* Set the ENHBUF bit if using Enhanced Buffer mode. */