diff --git a/arch/arm/src/imx/imx_cspi.h b/arch/arm/src/imx/imx_cspi.h index ffe02c659c..a42ca296ad 100755 --- a/arch/arm/src/imx/imx_cspi.h +++ b/arch/arm/src/imx/imx_cspi.h @@ -50,41 +50,108 @@ /* CSPI Register Offsets ************************************************************/ -#define CSPI_SPIRXD_OFFSET 0x0000 -#define CSPI_SPITXD_OFFSET 0x0004 -#define CSPI_SPICONT1_OFFSET 0x0008 -#define CSPI_INTCS_OFFSET 0x000c -#define CSPI_SPITEST_OFFSET 0x0010 -#define CSPI_SPISPCR_OFFSET 0x0014 -#define CSPI_SPIDMA_OFFSET 0x0018 -#define CSPI_SPIRESET_OFFSET 0x001c +#define CSPI_RXD_OFFSET 0x0000 /* Receive Data Register */ +#define CSPI_TXD_OFFSET 0x0004 /* Transmit Data Register */ +#define CSPI_CTRL_OFFSET 0x0008 /* Control Register */ +#define CSPI_INTCS_OFFSET 0x000c /* Interrupt Control/Status Register */ +#define CSPI_TEST_OFFSET 0x0010 /* Test Register */ +#define CSPI_SPCR_OFFSET 0x0014 /* Sample Period Control Register */ +#define CSPI_DMA_OFFSET 0x0018 /* DMA Control Register */ +#define CSPI_RESET_OFFSET 0x001c /* Soft Reset Register */ /* CSPI Register Addresses **********************************************************/ /* CSPI1 */ -#define IMX_CSPI1_SPIRXD (IMX_CSPI1_VBASE + CSPI_SPIRXD_OFFSET) -#define IMX_CSPI1_SPITXD (IMX_CSPI1_VBASE + CSPI_SPITXD_OFFSET) -#define IMX_CSPI1_SPICONT1 (IMX_CSPI1_VBASE + CSPI_SPICONT1_OFFSET) -#define IMX_CSPI1_INTCS (IMX_CSPI1_VBASE + CSPI_INTCS_OFFSET) -#define IMX_CSPI1_SPITEST (IMX_CSPI1_VBASE + CSPI_SPITEST_OFFSET) -#define IMX_CSPI1_SPISPCR (IMX_CSPI1_VBASE + CSPI_SPISPCR_OFFSET) -#define IMX_CSPI1_SPIDMA (IMX_CSPI1_VBASE + CSPI_SPIDMA_OFFSET) -#define IMX_CSPI1_SPIRESET (IMX_CSPI1_VBASE + CSPI_SPIRESET_OFFSET) +#define IMX_CSPI1_RXD (IMX_CSPI1_VBASE + CSPI_RXD_OFFSET) +#define IMX_CSPI1_TXD (IMX_CSPI1_VBASE + CSPI_TXD_OFFSET) +#define IMX_CSPI1_CTRL (IMX_CSPI1_VBASE + CSPI_CTRL_OFFSET) +#define IMX_CSPI1_INTCS (IMX_CSPI1_VBASE + CSPI_INTCS_OFFSET) +#define IMX_CSPI1_SPITEST (IMX_CSPI1_VBASE + CSPI_TEST_OFFSET) +#define IMX_CSPI1_SPISPCR (IMX_CSPI1_VBASE + CSPI_SPCR_OFFSET) +#define IMX_CSPI1_SPIDMA (IMX_CSPI1_VBASE + CSPI_DMA_OFFSET) +#define IMX_CSPI1_SPIRESET (IMX_CSPI1_VBASE + CSPI_RESET_OFFSET) /* CSPI1 */ -#define IMX_CSPI2_SPIRXD (IMX_CSPI2_VBASE + CSPI_SPIRXD_OFFSET) -#define IMX_CSPI2_SPITXD (IMX_CSPI2_VBASE + CSPI_SPITXD_OFFSET) -#define IMX_CSPI2_SPICONT1 (IMX_CSPI2_VBASE + CSPI_SPICONT1_OFFSET) -#define IMX_CSPI2_INTCS (IMX_CSPI2_VBASE + CSPI_INTCS_OFFSET) -#define IMX_CSPI2_SPITEST (IMX_CSPI2_VBASE + CSPI_SPITEST_OFFSET) -#define IMX_CSPI2_SPISPCR (IMX_CSPI2_VBASE + CSPI_SPISPCR_OFFSET) -#define IMX_CSPI2_SPIDMA (IMX_CSPI2_VBASE + CSPI_SPIDMA_OFFSET) -#define IMX_CSPI2_SPIRESET (IMX_CSPI2_VBASE + CSPI_SPIRESET_OFFSET) +#define IMX_CSPI2_RXD (IMX_CSPI2_VBASE + CSPI_RXD_OFFSET) +#define IMX_CSPI2_TXD (IMX_CSPI2_VBASE + CSPI_TXD_OFFSET) +#define IMX_CSPI2_CTRL (IMX_CSPI2_VBASE + CSPI_CTRL_OFFSET) +#define IMX_CSPI2_INTCS (IMX_CSPI2_VBASE + CSPI_INTCS_OFFSET) +#define IMX_CSPI2_SPITEST (IMX_CSPI2_VBASE + CSPI_TEST_OFFSET) +#define IMX_CSPI2_SPISPCR (IMX_CSPI2_VBASE + CSPI_SPCR_OFFSET) +#define IMX_CSPI2_SPIDMA (IMX_CSPI2_VBASE + CSPI_DMA_OFFSET) +#define IMX_CSPI2_SPIRESET (IMX_CSPI2_VBASE + CSPI_RESET_OFFSET) /* CSPI Register Bit Definitions ****************************************************/ +/* CSPI Control Register */ + +#define CSPI_CTRL_DATARATE_SHIFT 13 +#define CSPI_CTRL_DATARATE_MASK (7 << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_CTRL_DIV4 (0 << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_CTRL_DIV8 (1 << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_CTRL_DIV16 (2 << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_CTRL_DIV32 (3 << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_CTRL_DIV64 (4 << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_CTRL_DIV128 (5 << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_CTRL_DIV256 (6 << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_CTRL_DIV512 (7 << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_CTRL_DRCTL_SHIFT 11 +#define CSPI_CTRL_DRCTL_MASK (3 << CSPI_CTRL_DRCTL_SHIFT) +#define CSPI_CTRL_DRCTL_IGNRDY (0 << CSPI_CTRL_DRCTL_SHIFT) +#define CSPI_CTRL_DRCTL_FALLING (1 << CSPI_CTRL_DRCTL_SHIFT) +#define CSPI_CTRL_DRCTL_ACTVLOW (2 << CSPI_CTRL_DRCTL_SHIFT) +#define CSPI_CTRL_MODE (1 << 10) +#define CSPI_CTRL_SPIEN (1 << 9) +#define CSPI_CTRL_XCH (1 << 8) +#define CSPI_CTRL_SSPOL (1 << 7) +#define CSPI_CTRL_SSCTL (1 << 6) +#define CSPI_CTRL_PHA (1 << 5) +#define CSPI_CTRL_POL (1 << 4) +#define CSPI_CTRL_BITCOUNT_SHIFT 0 +#define CSPI_CTRL_BITCOUNT_MASK (15 << CSPI_CTRL_BITCOUNT_SHIFT) + +/* CSPI Interrrupt Control/Status Register */ + +#define CSPI_INTCS_TE (1 << 0) /* Bit 0: TXFIFO Empty Status */ +#define CSPI_INTCS_TH (1 << 1) /* Bit 1: TXFIFO Half Status */ +#define CSPI_INTCS_TF (1 << 2) /* Bit 2: TXFIFO Full Status */ +#define CSPI_INTCS_RR (1 << 3) /* Bit 3: RXFIFO Data Ready Status */ +#define CSPI_INTCS_RH (1 << 4) /* Bit 4: RXFIFO Half Status */ +#define CSPI_INTCS_RF (1 << 5) /* Bit 5: RXFIFO Full Status */ +#define CSPI_INTCS_RO (1 << 6) /* Bit 6: RXFIFO Overflow */ +#define CSPI_INTCS_BO (1 << 7) /* Bit 7: Bit Count Overflow */ +#define CSPI_INTCS_TEEN (1 << 8) /* Bit 8: TXFIFO Empty Interrupt Enable */ +#define CSPI_INTCS_THEN (1 << 9) /* Bit 9: TXFIFO Half Interrupt Enable */ +#define CSPI_INTCS_TFEN (1 << 10) /* Bit 10: TXFIFO Full Interrupt Enable */ +#define CSPI_INTCS_RREN (1 << 11) /* Bit 11: RXFIFO Data Ready Interrupt Enable */ +#define CSPI_INTCS_RHEN (1 << 12) /* Bit 12: RXFIFO Half Interrupt Enable */ +#define CSPI_INTCS_RFEN (1 << 13) /* Bit 13: RXFIFO Full Interrupt Enable */ +#define CSPI_INTCS_ROEN (1 << 14) /* BIT 14: RXFIFO Overflow Interrupt Enable */ +#define CSPI_INTCS_BOEN (1 << 15) /* Bit 15: Bit Count Overflow Interrupt Enable */ + +/* CSPI Sample Period Control Register */ + +#define CSPI_SPCR_WAIT_SHIFT 0 +#define CSPI_SPCR_WAIT_MASK (0x7ff << CSPI_CTRL_DATARATE_SHIFT) +#define CSPI_SPCR_CSRC (1 << 15) /* Bit 15: 1:32768 or 32 kHz clock source */ + +/* CSPI DMA Control Register */ + +#define CSPI_DMA_RHDMA (1 << 4) /* Bit 4: RXFIFO Half Status */ +#define CSPI_DMA_RFDMA (1 << 5) /* Bit 5: RXFIFO Full Status */ +#define CSPI_DMA_TEDMA (1 << 6) /* Bit 6: TXFIFO Empty Status */ +#define CSPI_DMA_THDMA (1 << 7) /* Bit 7: TXFIFO Half Status */ +#define CSPI_DMA_RHDEN (1 << 12) /* Bit 12: Enable RXFIFO Half DMA Request */ +#define CSPI_DMA_RFDEN (1 << 13) /* Bit 13: Enables RXFIFO Full DMA Request */ +#define CSPI_DMA_TEDEN (1 << 14) /* Bit 14: Enable TXFIFO Empty DMA Request */ +#define CSPI_DMA_THDEN (1 << 15) /* Bit 15: Enable TXFIFO Half DMA Request */ + +/* Soft Reset Register */ + +#define CSPI_RESET_START (1 << 0) /* Bit 0: Execute soft reset */ + /************************************************************************************ * Inline Functions ************************************************************************************/ diff --git a/arch/arm/src/imx/imx_gpio.h b/arch/arm/src/imx/imx_gpio.h index 661021a90f..e8da7c46fe 100755 --- a/arch/arm/src/imx/imx_gpio.h +++ b/arch/arm/src/imx/imx_gpio.h @@ -550,6 +550,7 @@ static inline void imxgpio_clroutput(int port, int bit) extern void imxgpio_configoutput(int port, int bit, int value); extern void imxgpio_configinput(int port, int bit); + extern void imxgpio_configpfoutput(int port, int bit); extern void imxgpio_configpfinput(int port, int bit); diff --git a/arch/arm/src/imx/imx_spi.c b/arch/arm/src/imx/imx_spi.c index eea7d108d3..a408ba9b8f 100755 --- a/arch/arm/src/imx/imx_spi.c +++ b/arch/arm/src/imx/imx_spi.c @@ -88,6 +88,11 @@ struct imx_spidev_s { const struct spi_ops_s *ops; /* Common SPI operations */ uint32 base; /* SPI register base address */ + uint32 frequency; /* Current desired SCLK frequency */ + uint32 actual; /* Current actual SCLK frequency */ + ubyte mode; /* Current mode */ + ubyte nbytes; /* Current number of bits per word */ + ubyte irq; /* SPI IRQ number */ }; /**************************************************************************** @@ -97,7 +102,7 @@ struct imx_spidev_s /* SPI helpers */ static inline uint32 spi_getreg(struct imx_spidev_s *priv, unsigned int offset); -static inline void spi_readreg(struct imx_spidev_s *priv, unsigned int offset, uint32 value); +static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, uint32 value); static ubyte spi_waitspif(struct imx_spidev_s *priv); static ubyte spi_transfer(struct imx_spidev_s *priv, ubyte ch); @@ -134,12 +139,14 @@ static struct imx_spidev_s g_spidev[] = { .ops = &g_spiops, .base = IMX_CSPI1_VBASE + .irq = IMX_IRQ_CSPI1, }, #endif #ifndef CONFIG_SPI1_DISABLE { .ops = &g_spiops, .base = IMX_CSPI2_VBASE + .irq = IMX_IRQ_CSPI2, }, #endif }; @@ -188,7 +195,7 @@ static inline uint32 spi_getreg(struct imx_spidev_s *priv, unsigned int offset) * ****************************************************************************/ -static inline void spi_readreg(struct imx_spidev_s *priv, unsigned int offset, uint32 value) +static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, uint32 value) { putreg32(value, priv->base + offset); } @@ -270,8 +277,66 @@ static ubyte spi_transfer(struct imx_spidev_s *priv, ubyte ch) static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency) { struct imx_spidev_s *priv = (struct imx_spidev_s *)dev; -#error "Missing logic" - return frequency; + uint32 actual = priv->actual; + + if (priv & frequency != priv->frequency) + { + uint32 freqbits; + uint32 regval; + + if (frequency >= PERCLK2 / 4) + { + freqbits = CSPI_CTRL_DIV4; + actual = PERCLK2 / 4; + } + else if (frequency >= PERCLK2 / 8) + { + freqbits = CSPI_CTRL_DIV8; + actual = PERCLK2 / 8; + } + else if (frequency >= PERCLK2 / 16) + { + freqbits = CSPI_CTRL_DIV16; + actual = PERCLK2 / 16; + } + else if (frequency >= PERCLK2 / 32) + { + freqbits = CSPI_CTRL_DIV32; + actual = PERCLK2 / 32; + } + else if (frequency >= PERCLK2 / 64) + { + freqbits = CSPI_CTRL_DIV64; + actual = PERCLK2 / 64; + } + else if (frequency >= PERCLK2 / 128) + { + freqbits = CSPI_CTRL_DIV128; + actual = PERCLK2 / 128; + } + else if (frequency >= PERCLK2 / 256) + { + freqbits = CSPI_CTRL_DIV256; + actual = PERCLK2 / 256; + } + else /*if (frequency >= PERCLK2 / 512) */ + { + freqbits = CSPI_CTRL_DIV512; + actual = PERCLK2 / 512; + } + + /* Then set the selected frequency */ + + regval = spi_regreg(priv, CSPI_CTRL_OFFSET); + regval &= ~(CSPI_CTRL_DATARATE_MASK); + regval |= freqbits; + spi_putreg(priv, CSPI_CTRL_OFFSET, regval); + + priv->frequency = frequency; + priv->actual = actual; + } + + return actual; } /**************************************************************************** @@ -292,35 +357,42 @@ static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency) static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) { struct imx_spidev_s *priv = (struct imx_spidev_s *)dev; - uint32 modebits; - ubyte regval; - - /* Select the CTL register bits based on the selected mode */ - - switch (mode) + if (priv & mode != priv->mode) { - case SPIDEV_MODE0: /* CPOL=0 CHPHA=0 */ -#error "Missing logic" - break; + uint32 modebits; + uint32 regval; - case SPIDEV_MODE1: /* CPOL=0 CHPHA=1 */ -#error "Missing logic" - break; + /* Select the CTL register bits based on the selected mode */ - case SPIDEV_MODE2: /* CPOL=1 CHPHA=0 */ -#error "Missing logic" - break; + switch (mode) + { + case SPIDEV_MODE0: /* CPOL=0 CHPHA=0 */ + modebits = 0; + break; - case SPIDEV_MODE3: /* CPOL=1 CHPHA=1 */ -#error "Missing logic" - break; + case SPIDEV_MODE1: /* CPOL=0 CHPHA=1 */ + modebits = CSPI_CTRL_PHA; + break; - default: - return; + case SPIDEV_MODE2: /* CPOL=1 CHPHA=0 */ + modebits = CSPI_CTRL_POL; + break; + + case SPIDEV_MODE3: /* CPOL=1 CHPHA=1 */ + modebits = CSPI_CTRL_PHA|CSPI_CTRL_POL; + break; + + default: + return; + } + + /* Then set the selected mode */ + + regval = spi_regreg(priv, CSPI_CTRL_OFFSET); + regval &= ~(CSPI_CTRL_PHA|CSPI_CTRL_POL); + regval |= modebits; + spi_putreg(priv, CSPI_CTRL_OFFSET, regval); } - - /* Then set the selected mode */ -#error "Missing logic" } /**************************************************************************** @@ -442,8 +514,14 @@ FAR struct spi_dev_s *up_spiinitialize(int port) priv = &g_spidev[SPI1_NDX]; - /* Configure SPI1 GPIOs */ -#error "Missing logic" + /* Configure SPI1 GPIOs (NOTE that SS is not initialized here, the + * logic in this file makes no assumptions about chip select) + */ + + imxgpio_configpfinput(GPIOC, 13); /* Port C, pin 13: RDY */ + imxgpio_configpfoutput(GPIOC, 14); /* Port C, pin 14: SCLK */ + imxgpio_configpfinput(GPIOC, 16); /* Port C, pin 16: MISO */ + imxgpio_configpfoutput(GPIOC, 17); /* Port C, pin 17: MOSI */ break; #endif @@ -454,7 +532,48 @@ FAR struct spi_dev_s *up_spiinitialize(int port) priv = &g_spidev[SPI2_NDX]; /* Configure SPI1 GPIOs */ -#error "Missing logic" + /* SCLK: AIN of Port A, pin 0 -OR- AIN of Port D, pin 7 */ + +#if 1 + imxgpio_configoutput(GPIOA, 0); /* Set GIUS=1 OCR=0 DIR=OUT */ +#else + imxgpio_configoutput(GPIOD, 7); /* Set GIUS=1 OCR=0 DIR=OUT */ +#endif + + /* SS: AIN of Port A, pin 17 -OR- AIN of Port D, pin 8.(NOTE that SS + * is not initialized here, the logic in this file makes no assumptions + * about chip select) + */ + + /* RXD: AOUT of Port A, pin 1 -OR- AOUT of Port D, pin 9 */ + +#if 1 + imxgpio_configinput(GPIOA, 1); /* Set GIUS=1 OCR=0 DIR=IN */ + + /* Select input from SPI2_RXD_0 pin (AOUT Port A, pin 1) */ + + regval = getreg32(IMX_SC_FMCR); + regval &= ~FMCR_SPI2_RXDSEL; + putreg32(regval, IMX_SC_FMCR); +#else + imxgpio_configinput(GPIOD, 9); /* Set GIUS=1 OCR=0 DIR=IN */ + + /* Select input from SPI2_RXD_1 pin (AOUT Port D, pin 9) */ + + regval = getreg32(IMX_SC_FMCR); + regval |= FMCR_SPI2_RXDSEL; + putreg32(regval, IMX_SC_FMCR); +#endif + + /* TXD: BIN of Port D, pin 31 -OR- AIN of Port D, pin 10 */ + +#if 1 + imxgpio_configinput(GPIOD, 31); + imxgpio_ocrbin(GPIOD, 31); + imxgpio_dirout(GPIOD, 31); +#else + imxgpio_configoutput(GPIOD, 10); +#endif break; #endif @@ -465,16 +584,53 @@ FAR struct spi_dev_s *up_spiinitialize(int port) /* Disable SPI */ #error "Missing logic" - /* Set the initial clock frequency for indentification mode < 400kHz */ + /* Initialize control rebistger: min frequency, ignore ready, master mode, mode=0, 8-bit */ + + spi_putreg(priv, IMX_CSPI_CTRL_OFFSET, + CSPI_CTRL_DIV512 | /* Lowest frequency */ + CSPI_CTRL_DRCTL_IGNRDY | /* Ignore ready */ + CSPI_CTRL_MODE | /* Master mode */ + (7 << CSPI_CTRL_BITCOUNT_SHIFT)); /* 8-bit data */ + + /* Make sure state agrees with data */ + + priv->mode = SPIDEV_MODE0; + priv->nbits = 8; + + /* Set the initial clock frequency for identification mode < 400kHz */ spi_setfrequency((FAR struct spi_dev_s *)priv, 400000); - /* Enable the SPI. - * NOTE 1: Interrupts are not used in this driver version. - * NOTE 2: Initial mode is mode=0. + /* Enable interrupts on data ready (and certain error conditions */ + + spi_putreg(priv, CSPI_INTCS_OFFSET, + CSPI_INTCS_RREN | /* RXFIFO Data Ready Interrupt Enable */ + CSPI_INTCS_ROEN | /* RXFIFO Overflow Interrupt Enable */ + CSPI_INTCS_BOEN); /* Bit Count Overflow Interrupt Enable */ + + /* Set the clock source=bit clock and number of clocks inserted between + * transactions = 2. */ -#error "Missing logic" + spi_putreg(priv, CSPI_SPCR_OFFSET, 2); + + /* No DMA */ + + spi_putreg(priv, CSPI_DMA_OFFSET, 0); + + /* Attach the interrupt */ + + irq_attach(priv->irq, (xcpt_t)imx_spinterrupt); + + /* Enable SPI */ + + regval = spi_getreg(priv, IMX_CSPI_CTRL_OFFSET); + regval |= CSPI_CTRL_SPIEN; + spi_putreg(priv, IMX_CSPI_CTRL_OFFSET, regval); + + /* Enable SPI interrupts */ + + up_enable_irq(priv->irq); return (FAR struct spi_dev_s *)priv; } diff --git a/arch/arm/src/imx/imx_system.h b/arch/arm/src/imx/imx_system.h index f5af05cd0f..fe575cf414 100755 --- a/arch/arm/src/imx/imx_system.h +++ b/arch/arm/src/imx/imx_system.h @@ -156,6 +156,18 @@ /* SC Register Bit Definitions ******************************************************/ + +#define FMCR_SDCS_SEL (1 << 0) /* Bit 0: 1:CSD0 selected */ +#define FMCR_SDCS1_SEL (1 << 1) /* Bit 1: 1:CSD1 selected */ +#define FMCR_EXT_BREN (1 << 2) /* Bit 2: 1:External bus request enabled */ +#define FMCR_SSI_TXCLKSEL (1 << 3) /* Bit 3: 1:Input from Port B[19] SIM_CLK pin */ +#define FMCR_SSI_TXFSSEL (1 << 4) /* Bit 4: 1:Input from Port B[18] SIM_RST pin */ +#define FMCR_SSI_RXDATSEL (1 << 5) /* Bit 5: 1:Input from Port B[16] SIM_TX pin */ +#define FMCR_SSI_RXCLKSEL (1 << 6) /* Bit 6: 1:Input from Port B[15] SIM_PD pin */ +#define FMCR_SSI_RXFSSEL (1 << 7) /* Bit 7: 1:Input from Port B[14] SIM_SVEN pin */ +#define FMCR_SPI2_RXDSEL (1 << 8) /* Bit 8: 1:Input from SPI2_RXD_1 pin + * (AOUT of Port D[9]) */ + /* SDRAMC Register Offsets **********************************************************/ #define SDRAMC_SDCTL0_OFFSET 0x0000