diff --git a/arch/arm/src/kinetis/kinetis_spi.c b/arch/arm/src/kinetis/kinetis_spi.c index b7c603b51257f..98ddc9766f842 100644 --- a/arch/arm/src/kinetis/kinetis_spi.c +++ b/arch/arm/src/kinetis/kinetis_spi.c @@ -134,7 +134,7 @@ static inline void spi_putreg8(struct kinetis_spidev_s *priv, uint8_t offset, uint8_t value); static inline uint16_t spi_readword(struct kinetis_spidev_s *priv); static inline void spi_writeword(struct kinetis_spidev_s *priv, - uint16_t word); + uint16_t word, bool first_word); static inline void spi_run(struct kinetis_spidev_s *priv, bool enable); @@ -559,11 +559,14 @@ static inline void spi_write_control(struct kinetis_spidev_s *priv, * Name: spi_writeword * * Description: - * Write one 16 bit word to SPI TX FIFO + * Write one word to SPI TX FIFO or single-entry buffer. + * In non-FIFO mode, performs 32-bit write including control bits. + * In FIFO-enabled mode, writes only the data (control handled separately). * * Input Parameters: * priv - Device-specific state data * word - word to send + * first_word - Flag to set control in case of FIFO disabled * * Returned Value: * None @@ -571,15 +574,36 @@ static inline void spi_write_control(struct kinetis_spidev_s *priv, ****************************************************************************/ static inline void spi_writeword(struct kinetis_spidev_s *priv, - uint16_t word) + uint16_t word, bool first_word) { + uint32_t mcr = spi_getreg(priv, KINETIS_SPI_MCR_OFFSET); + uint32_t pushr_val; + /* Wait until there is space in the fifo */ spi_wait_status(priv, SPI_SR_TFFF); - /* Write the data to transmitted to the SPI Data Register */ + if (mcr & SPI_MCR_DIS_TXF) + { + /* FIFO disabled: 32-bit write including control + data */ + + pushr_val = SPI_PUSHR_TXDATA(word); + + if (first_word) + { + /* Set Control word */ + + pushr_val |= SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_CTCNT; + } + + spi_putreg(priv, KINETIS_SPI_PUSHR_OFFSET, pushr_val); + } + else + { + /* FIFO enabled: write only data; control handled separately */ - spi_putreg16(priv, KINETIS_SPI_PUSHR_OFFSET, SPI_PUSHR_TXDATA(word)); + spi_putreg16(priv, KINETIS_SPI_PUSHR_OFFSET, SPI_PUSHR_TXDATA(word)); + } } /**************************************************************************** @@ -964,16 +988,27 @@ static uint16_t spi_send_data(struct kinetis_spidev_s *priv, uint16_t wd, bool last) { uint16_t ret; + uint32_t mcr = spi_getreg(priv, KINETIS_SPI_MCR_OFFSET); + bool first_word = false; - /* On first write set control word and start transfer */ + /* Start module and write control if FIFO enabled on first transfer */ - if (0 == (spi_getreg(priv, KINETIS_SPI_SR_OFFSET) & SPI_SR_TXRXS)) + if ((spi_getreg(priv, KINETIS_SPI_SR_OFFSET) & SPI_SR_TXRXS) == 0) { spi_run(priv, true); - spi_write_control(priv, SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_CTCNT); + first_word = true; + + if ((mcr & SPI_MCR_DIS_TXF) == 0) + { + /* FIFO enabled: safe to write control separately */ + + spi_write_control(priv, SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_CTCNT); + } + + /* Non-FIFO mode: first_word flag used in spi_writeword() */ } - spi_writeword(priv, wd); + spi_writeword(priv, wd, first_word); ret = spi_readword(priv); if (!last) @@ -1037,15 +1072,14 @@ static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd) * ****************************************************************************/ -#if !defined(CONFIG_STM32_SPI_DMA) || defined(CONFIG_STM32_SPI_DMATHRESHOLD) -# if !defined(CONFIG_KINETIS_SPI_DMA) +#if !defined(CONFIG_KINETIS_SPI_DMA) static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, void *rxbuffer, size_t nwords) -# else +#else static void spi_exchange_nodma(struct spi_dev_s *dev, const void *txbuffer, void *rxbuffer, size_t nwords) -# endif +#endif { struct kinetis_spidev_s *priv = (struct kinetis_spidev_s *)dev; uint8_t *brxptr = (uint8_t *)rxbuffer; @@ -1117,7 +1151,6 @@ static void spi_exchange_nodma(struct spi_dev_s *dev, } } } -#endif /* !defined(CONFIG_STM32_SPI_DMA) || defined(CONFIG_STM32_SPI_DMATHRESHOLD) */ /**************************************************************************** * Name: spi_exchange (with DMA capability) @@ -1620,13 +1653,13 @@ struct spi_dev_s *kinetis_spibus_initialize(int port) * Peripheral Chip Select Strobe - Peripheral Chip Select[5] signal * Receive FIFO Overflow Overwrite - Ignore incoming * Chip Select x Inactive State - High - * Doze - Disabled + * Doze - Disabled * Module Disable - Enables the module clocks. * Disable Transmit FIFO - yes * Disable Receive FIFO - yes * Clear TX FIFO - No * Clear RX FIFO - No - * Sample Point - 0 clocks between edge and sample + * Sample Point - 0 clocks between edge and sample * */ diff --git a/boards/arm/kinetis/freedom-k64f/include/board.h b/boards/arm/kinetis/freedom-k64f/include/board.h index 84b33c3261a98..6718de6ef268f 100644 --- a/boards/arm/kinetis/freedom-k64f/include/board.h +++ b/boards/arm/kinetis/freedom-k64f/include/board.h @@ -297,4 +297,17 @@ #define PIN_I2C0_SCL PIN_I2C0_SCL_4 #define PIN_I2C0_SDA PIN_I2C0_SDA_4 +/* SPI Bus 0 + * + * Arduino Pin FRDM-K64F J1 Connector + * ------------------------ ----------------------- + * SPI CLK, Arduino D13 Pin 94, PTD1, SPI0_SCK + * SPI MISO, Arduino D12 Pin 95, PTD3, SPI0_SOUT + * SPI MOSI, Arduino D11 Pin 96, PTD2, SPI0_SIN + */ + +#define PIN_SPI0_SCK PIN_SPI0_SCK_3 +#define PIN_SPI0_SIN PIN_SPI0_SIN_3 +#define PIN_SPI0_OUT PIN_SPI0_SOUT_3 + #endif /* __BOARDS_ARM_FREEDOM_K64F_INCLUDE_BOARD_H */ diff --git a/boards/arm/kinetis/freedom-k64f/src/freedom-k64f.h b/boards/arm/kinetis/freedom-k64f/src/freedom-k64f.h index ae0450dad58c1..d6c57b9a3edfb 100644 --- a/boards/arm/kinetis/freedom-k64f/src/freedom-k64f.h +++ b/boards/arm/kinetis/freedom-k64f/src/freedom-k64f.h @@ -213,6 +213,9 @@ #define GPIO_LED_G (GPIO_LOWDRIVE | GPIO_OUTPUT_ONE | PIN_PORTE | PIN26) #define GPIO_LED_B (GPIO_LOWDRIVE | GPIO_OUTPUT_ONE | PIN_PORTB | PIN21) +/* SPI CS, Arduino D10 Pin 93, PTD0, PIN_SPI0_PCS0_2 */ +#define GPIO_SPI0_CS (GPIO_LOWDRIVE | GPIO_OUTPUT_ONE | PIN_PORTC | PIN4) + /**************************************************************************** * Public Data ****************************************************************************/ diff --git a/boards/arm/kinetis/freedom-k64f/src/k64_boot.c b/boards/arm/kinetis/freedom-k64f/src/k64_boot.c index afd5a8e9ee462..57f95848d85a5 100644 --- a/boards/arm/kinetis/freedom-k64f/src/k64_boot.c +++ b/boards/arm/kinetis/freedom-k64f/src/k64_boot.c @@ -51,7 +51,7 @@ void kinetis_boardinitialize(void) { -#if defined(CONFIG_KINETIS_SPI1) || defined(CONFIG_KINETIS_SPI2) +#if defined(CONFIG_KINETIS_SPI0) || defined(CONFIG_KINETIS_SPI1) || defined(CONFIG_KINETIS_SPI2) /* Configure SPI chip selects if 1) SPI is not disabled, and 2) * the weak function k64_spidev_initialize() has been brought into the * link. diff --git a/boards/arm/kinetis/freedom-k64f/src/k64_bringup.c b/boards/arm/kinetis/freedom-k64f/src/k64_bringup.c index d9d8b2992b0d1..9b050d49938a0 100644 --- a/boards/arm/kinetis/freedom-k64f/src/k64_bringup.c +++ b/boards/arm/kinetis/freedom-k64f/src/k64_bringup.c @@ -48,6 +48,9 @@ # define LED_DRIVER_PATH "/dev/userleds" #endif +#include + +#include "kinetis_spi.h" #include "freedom-k64f.h" #if defined(CONFIG_BOARDCTL) || defined(CONFIG_BOARD_LATE_INITIALIZE) @@ -102,6 +105,19 @@ int k64_bringup(void) k64_i2cdev_initialize(); #endif +#ifdef CONFIG_KINETIS_SPI0 + struct spi_dev_s *spi0; + spi0 = kinetis_spibus_initialize(0); + + if (!spi0) + { + syslog(LOG_ERR, "ERROR:FAILED to initialize SPI port 0\n"); + return -ENODEV; + } + + spi_register(spi0, 0); +#endif + #ifdef HAVE_MMCSD /* Initialize the SDHC driver */ diff --git a/boards/arm/kinetis/freedom-k64f/src/k64_spi.c b/boards/arm/kinetis/freedom-k64f/src/k64_spi.c index b25d3033e9427..6e59bc40b2bbf 100644 --- a/boards/arm/kinetis/freedom-k64f/src/k64_spi.c +++ b/boards/arm/kinetis/freedom-k64f/src/k64_spi.c @@ -57,7 +57,7 @@ void weak_function k64_spidev_initialize(void) { -# warning "Missing logic" + kinetis_pinconfig(GPIO_SPI0_CS); } /**************************************************************************** @@ -98,7 +98,7 @@ void kinetis_spi0select(struct spi_dev_s *dev, uint32_t devid, { spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); -# warning "Missing logic" + kinetis_gpiowrite(GPIO_SPI0_CS, !selected); } uint8_t kinetis_spi0status(struct spi_dev_s *dev, uint32_t devid)