mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 22:41:07 +08:00
z20x: SPI and timer fixes
arch/z80/src/ez80/ez80_spi.c: Add logic checks to eliminate unnecessary SPI reconfiguration. arch/z80/src/ez80/ez80_timerisr.c and arch/z80/src/ez80/ez80f92.h: Fix numerous places where configurations began with CONFIGS_ instead of CONFIG_
This commit is contained in:
committed by
Abdelatif Guettouche
parent
8b1dc2825f
commit
797e45d6bf
@@ -136,6 +136,12 @@ static struct spi_dev_s g_spidev =
|
||||
|
||||
static sem_t g_exclsem = SEM_INITIALIZER(1);
|
||||
|
||||
/* These are used to perform reconfigurations only when necessary. */
|
||||
|
||||
static uint32_t g_spi_frequency;
|
||||
static uint32_t g_spi_actual;
|
||||
static enum spi_mode_e g_spi_mode = SPIDEV_MODE3;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@@ -195,44 +201,48 @@ 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)
|
||||
{
|
||||
uint32_t actual;
|
||||
uint32_t brg;
|
||||
|
||||
spiinfo("frequency: %lu\n", (unsigned long)frequency);
|
||||
|
||||
/* We want select divisor to provide the highest frequency (SPIR) that does
|
||||
* NOT exceed the requested frequency.:
|
||||
*
|
||||
* SPIR <= System Clock Frequency / (2 * BRG)
|
||||
*
|
||||
* So
|
||||
*
|
||||
* BRG >= System Clock Frequency / (2 * SPIR)
|
||||
*/
|
||||
|
||||
brg = ((EZ80_SYS_CLK_FREQ + 1) / 2 + frequency - 1) / frequency;
|
||||
|
||||
/* "When configured as a Master, the 16-bit divisor value must be between
|
||||
* 0003h and FFFFh, inclusive. When configured as a Slave, the 16-bit
|
||||
* divisor value must be between 0004h and FFFFh, inclusive."
|
||||
*/
|
||||
|
||||
if (brg < 3)
|
||||
if (frequency != g_spi_frequency)
|
||||
{
|
||||
brg = 3;
|
||||
}
|
||||
else if (brg > 0xffff)
|
||||
{
|
||||
brg = 0xffff;
|
||||
uint32_t brg;
|
||||
|
||||
spiinfo("frequency: %lu\n", (unsigned long)frequency);
|
||||
|
||||
/* We want select divisor to provide the highest frequency (SPIR) that
|
||||
* does NOT exceed the requested frequency.:
|
||||
*
|
||||
* SPIR <= System Clock Frequency / (2 * BRG)
|
||||
*
|
||||
* So
|
||||
*
|
||||
* BRG >= System Clock Frequency / (2 * SPIR)
|
||||
*/
|
||||
|
||||
brg = ((EZ80_SYS_CLK_FREQ + 1) / 2 + frequency - 1) / frequency;
|
||||
|
||||
/* "When configured as a Master, the 16-bit divisor value must be
|
||||
* between 0003h and FFFFh, inclusive. When configured as a Slave, the
|
||||
* 16-bit divisor value must be between 0004h and FFFFh, inclusive."
|
||||
*/
|
||||
|
||||
if (brg < 3)
|
||||
{
|
||||
brg = 3;
|
||||
}
|
||||
else if (brg > 0xffff)
|
||||
{
|
||||
brg = 0xffff;
|
||||
}
|
||||
|
||||
outp(EZ80_SPI_BRG_L, brg & 0xff);
|
||||
outp(EZ80_SPI_BRG_H, (brg >> 8) & 0xff);
|
||||
|
||||
g_spi_actual = ((EZ80_SYS_CLK_FREQ + 1) / 2 + brg - 1) / brg;
|
||||
|
||||
finfo("BRG=%lu Actual=%lu\n",
|
||||
(unsigned long)brg, (unsigned long)g_spi_actual);
|
||||
}
|
||||
|
||||
outp(EZ80_SPI_BRG_L, brg & 0xff);
|
||||
outp(EZ80_SPI_BRG_H, (brg >> 8) & 0xff);
|
||||
|
||||
actual = ((EZ80_SYS_CLK_FREQ + 1) / 2 + brg - 1) / brg;
|
||||
|
||||
finfo("BRG=%lu Actual=%lu\n", (unsigned long)brg, (unsigned long)actual);
|
||||
return actual;
|
||||
return g_spi_actual;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -252,41 +262,46 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
|
||||
|
||||
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
|
||||
{
|
||||
uint8_t modebits;
|
||||
uint8_t regval;
|
||||
|
||||
spiinfo("mode: %d\n", (int)mode);
|
||||
|
||||
/* Select the CTL register bits based on the selected mode */
|
||||
|
||||
switch (mode)
|
||||
if (mode != g_spi_mode)
|
||||
{
|
||||
case SPIDEV_MODE0: /* CPOL=0 CHPHA=0 */
|
||||
modebits = 0;
|
||||
break;
|
||||
uint8_t modebits;
|
||||
uint8_t regval;
|
||||
|
||||
case SPIDEV_MODE1: /* CPOL=0 CHPHA=1 */
|
||||
modebits = SPI_CTL_CPHA;
|
||||
break;
|
||||
spiinfo("mode: %d\n", (int)mode);
|
||||
|
||||
case SPIDEV_MODE2: /* CPOL=1 CHPHA=0 */
|
||||
modebits = SPI_CTL_CPOL;
|
||||
break;
|
||||
/* Select the CTL register bits based on the selected mode */
|
||||
|
||||
case SPIDEV_MODE3: /* CPOL=1 CHPHA=1 */
|
||||
modebits = (SPI_CTL_CPOL | SPI_CTL_CPHA);
|
||||
break;
|
||||
switch (mode)
|
||||
{
|
||||
case SPIDEV_MODE0: /* CPOL=0 CHPHA=0 */
|
||||
modebits = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
case SPIDEV_MODE1: /* CPOL=0 CHPHA=1 */
|
||||
modebits = SPI_CTL_CPHA;
|
||||
break;
|
||||
|
||||
case SPIDEV_MODE2: /* CPOL=1 CHPHA=0 */
|
||||
modebits = SPI_CTL_CPOL;
|
||||
break;
|
||||
|
||||
case SPIDEV_MODE3: /* CPOL=1 CHPHA=1 */
|
||||
modebits = (SPI_CTL_CPOL | SPI_CTL_CPHA);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Then set those bits in the CTL register */
|
||||
|
||||
regval = inp(EZ80_SPI_CTL);
|
||||
regval &= ~(SPI_CTL_CPOL | SPI_CTL_CPHA);
|
||||
regval |= modebits;
|
||||
outp(EZ80_SPI_CTL, regval);
|
||||
|
||||
g_spi_mode = mode;
|
||||
}
|
||||
|
||||
/* Then set those bits in the CTL register */
|
||||
|
||||
regval = inp(EZ80_SPI_CTL);
|
||||
regval &= ~(SPI_CTL_CPOL | SPI_CTL_CPHA);
|
||||
regval |= modebits;
|
||||
outp(EZ80_SPI_CTL, regval);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -394,8 +409,6 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
|
||||
uint8_t response;
|
||||
int ret;
|
||||
|
||||
spiinfo("ch: %04x\n", wd);
|
||||
|
||||
ret = spi_transfer((uint8_t)wd, &response);
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -403,6 +416,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
|
||||
return (uint16_t)0xff;
|
||||
}
|
||||
|
||||
spiinfo("ch: %04x response: %02x\n", wd, response);
|
||||
return (uint16_t)response;
|
||||
}
|
||||
|
||||
@@ -625,9 +639,12 @@ FAR struct spi_dev_s *ez80_spibus_initialize(int port)
|
||||
# error "Check GPIO initialization for this chip"
|
||||
#endif
|
||||
|
||||
/* Set the initial clock frequency for identification mode < 400kHz */
|
||||
/* Set the initial clock frequency for identification mode < 400kHz
|
||||
* and Mode 0.
|
||||
*/
|
||||
|
||||
spi_setfrequency(NULL, 400000);
|
||||
spi_setmode(NULL, SPIDEV_MODE0);
|
||||
|
||||
/* Enable the SPI.
|
||||
* NOTE 1: Interrupts are not used in this driver version.
|
||||
|
||||
@@ -51,7 +51,7 @@ static int ez80_timerisr(int irq, chipreg_t *regs, void *arg)
|
||||
{
|
||||
/* Read the appropriate timer0 register to clear the interrupt */
|
||||
|
||||
#ifdef CONFIGS_ARCH_CHIP_EZ80F91
|
||||
#ifdef CONFIG_ARCH_CHIP_EZ80F91
|
||||
inp(EZ80_TMR0_IIR);
|
||||
#else
|
||||
/* _EZ80190, _EZ80L92, _EZ80F92, _EZ80F93: PRT_IRQ, is set to 1 when the
|
||||
@@ -134,37 +134,41 @@ void up_timer_initialize(void)
|
||||
outp(EZ80_TMR0_RRH, (uint8_t)(reload >> 8));
|
||||
outp(EZ80_TMR0_RRL, (uint8_t)(reload));
|
||||
|
||||
#if defined(CONFIGS_ARCH_CHIP_EZ80F91)
|
||||
#if defined(CONFIG_ARCH_CHIP_EZ80F91)
|
||||
/* Clear any pending timer interrupts by reading the IIR register */
|
||||
|
||||
inp(EZ80_TMR0_IIR);
|
||||
#elif defined(CONFIGS_ARCH_CHIP_EZ80L92) || defined(CONFIGS_ARCH_CHIP_EZ80F92) || \
|
||||
defined(CONFIGS_ARCH_CHIP_EZ80F93)
|
||||
|
||||
#elif defined(CONFIG_ARCH_CHIP_EZ80L92) || defined(CONFIG_ARCH_CHIP_EZ80F92) || \
|
||||
defined(CONFIG_ARCH_CHIP_EZ80F93)
|
||||
/* Clear any pending timer interrupts by reading the CTL register */
|
||||
|
||||
inp(EZ80_TMR0_CTL);
|
||||
|
||||
#endif
|
||||
|
||||
/* Configure and enable the timer */
|
||||
|
||||
#if defined(_EZ80190)
|
||||
|
||||
outp(EZ80_TMR0_CTL, 0x5f);
|
||||
#elif defined(CONFIGS_ARCH_CHIP_EZ80F91)
|
||||
|
||||
#elif defined(CONFIG_ARCH_CHIP_EZ80F91)
|
||||
/* EZ80_TMRCTL_TIMEN: Bit 0: The programmable reload timer is enabled
|
||||
* EZ80_TMRCTL_RLD: Bit 1: Force reload
|
||||
* EZ80_TMRCTL_TIMCONT: Bit 2: The timer operates in CONTINUOUS mode.
|
||||
* EZ80_TMRCLKDIV_16: Bits 3-4: System clock divider = 16
|
||||
*/
|
||||
|
||||
outp(EZ80_TMR0_CTL, (EZ80_TMRCLKDIV_16 | EZ80_TMRCTL_TIMCONT |
|
||||
EZ80_TMRCTL_RLD | EZ80_TMRCTL_TIMEN));
|
||||
outp(EZ80_TMR0_CTL, (EZ80_TMRCTL_TIMEN | EZ80_TMRCTL_RLD |
|
||||
EZ80_TMRCTL_TIMCONT | EZ80_TMRCLKDIV_16));
|
||||
|
||||
/* Enable timer end-of-count interrupts */
|
||||
|
||||
outp(EZ80_TMR0_IER, EZ80_TMRIER_EOCEN);
|
||||
|
||||
#elif defined(CONFIGS_ARCH_CHIP_EZ80L92) || defined(CONFIGS_ARCH_CHIP_EZ80F92) || \
|
||||
defined(CONFIGS_ARCH_CHIP_EZ80F93)
|
||||
#elif defined(CONFIG_ARCH_CHIP_EZ80L92) || defined(CONFIG_ARCH_CHIP_EZ80F92) || \
|
||||
defined(CONFIG_ARCH_CHIP_EZ80F93)
|
||||
/* EZ80_TMRCTL_TIMEN: Bit 0: Programmable reload timer enabled.
|
||||
* EZ80_TMRCTL_RSTEN: Bit 1: Reload and start function enabled.
|
||||
* EZ80_TMRCLKDIV_4: Bits 2-3: Timer input clock divided by 4 (5Mhz)
|
||||
@@ -172,8 +176,9 @@ void up_timer_initialize(void)
|
||||
* EZ80_TMRCTL_EN: Bit 6: Enable timer interrupt requests
|
||||
*/
|
||||
|
||||
outp(EZ80_TMR0_CTL, (EZ80_TMRCTL_TIMEN | EZ80_TMRCTL_RSTEN |
|
||||
outp(EZ80_TMR0_CTL, (EZ80_TMRCTL_TIMEN | : |
|
||||
EZ80_TMRCLKDIV_4 | EZ80_TMRCTL_TIMCONT |
|
||||
EZ80_TMRCTL_EN);
|
||||
EZ80_TMRCTL_EN));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -39,10 +39,10 @@
|
||||
#define EZ80_OFFCHIPCS1 0xc00000 /* CS1: Off chip use (usually SRAM) */
|
||||
#define EZ80_ONCHIPSRAM 0xffe000 /* On-chip SRAM (4-8Kb) on reset */
|
||||
|
||||
#if defined(CONFIGS_ARCH_CHIP_EZ80L92)
|
||||
#if defined(CONFIG_ARCH_CHIP_EZ80L92)
|
||||
# define EZ80_FLASH_SIZE 0x020000 /* 128Kb on-chip flash */
|
||||
# define EZ80_SRAM_SIZE 0x002000 /* 8Kb on-chip sram */
|
||||
#elif defined(CONFIGS_ARCH_CHIP_EZ80L93)
|
||||
#elif defined(CONFIG_ARCH_CHIP_EZ80L93)
|
||||
# define EZ80_FLASH_SIZE 0x010000 /* 64Kb on-chip flash */
|
||||
# define EZ80_SRAM_SIZE 0x001000 /* 4Kb on-chip sram */
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user