diff options
author | Maureen Helm <maureen.helm@nxp.com> | 2017-01-14 14:22:34 -0600 |
---|---|---|
committer | Kumar Gala <kumar.gala@linaro.org> | 2017-01-23 15:15:54 -0600 |
commit | 8769cd585ed1f6d664ae65923419a45e9d26390a (patch) | |
tree | e825253d398a4b6a20c3155c6b2a1593e6d0e81c /drivers | |
parent | 4279bf1c0375337090074e12736844e3ed13cf8a (diff) |
spi: k64: Remove the k64 spi driver
Now that we have a more generic mcux spi driver that can be used across
multiple Kinetis SoCs, remove the specific k64 spi driver.
Jira: ZEP-1374
Change-Id: Ifc324374f305837f5e3d2cfd7ad30d3608865b5b
Signed-off-by: Maureen Helm <maureen.helm@nxp.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/spi/spi_k64.c | 1138 | ||||
-rw-r--r-- | drivers/spi/spi_k64_priv.h | 166 |
4 files changed, 0 insertions, 1313 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9202726c0..e9c530e5b 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -33,14 +33,6 @@ config SPI_QMSI_SS SPI driver implementation using QMSI library. This instance is for the Sensor Subsystem. -config SPI_K64 - bool - prompt "Freescale K64-based SPI controller driver" - depends on SPI && SOC_MK64F12 - default n - help - Enable support for Freescale K64-based SPI controllers. - config SPI_INTEL bool prompt "Intel SPI controller driver" diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index f794d0b6a..e346406a9 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -3,4 +3,3 @@ obj-$(CONFIG_SPI_DW) += spi_dw.o obj-$(CONFIG_SPI_MCUX) += spi_mcux.o obj-$(CONFIG_SPI_QMSI) += spi_qmsi.o obj-$(CONFIG_SPI_QMSI_SS) += spi_qmsi_ss.o -obj-$(CONFIG_SPI_K64) += spi_k64.o diff --git a/drivers/spi/spi_k64.c b/drivers/spi/spi_k64.c deleted file mode 100644 index 01d52083d..000000000 --- a/drivers/spi/spi_k64.c +++ /dev/null @@ -1,1138 +0,0 @@ -/* spi_k64.c - Driver implementation for K64 SPI controller */ - -/* - * Copyright (c) 2015-2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Portions of this file are derived from material that is - * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <errno.h> - -#include <kernel.h> -#include <arch/cpu.h> - -#include <misc/util.h> -#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL -#include <logging/sys_log.h> -#include <board.h> -#include <init.h> - -#include <sys_io.h> -#include <limits.h> -#include <power.h> - -#include <spi.h> -#include <spi/spi_k64.h> -#include "spi_k64_priv.h" - -#if (CONFIG_SYS_LOG_SPI_LEVEL == 4) -#define DBG_COUNTER_INIT() \ - uint32_t __cnt = 0 -#define DBG_COUNTER_INC() \ - (__cnt++) -#define DBG_COUNTER_RESULT() \ - (__cnt) -#else -#define DBG_COUNTER_INIT() {; } -#define DBG_COUNTER_INC() {; } -#define DBG_COUNTER_RESULT() 0 -#endif - -/* SPI protocol frequency = K64 bus clock frequency, in hz */ - -#define SPI_K64_PROTOCOL_FREQ (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / \ - CONFIG_K64_BUS_CLOCK_DIVIDER) - -/* SPI protocol period, in ns */ - -#define SPI_K64_PROTOCOL_PERIOD_NS (NSEC_PER_SEC/SPI_K64_PROTOCOL_FREQ) - -/* # of possible SPI baud rate and delay prescaler and scaler values */ - -#define SPI_K64_NUM_PRESCALERS 4 -#define SPI_K64_NUM_SCALERS 16 - -#define SPI_K64_FIFO_MAX 0x40 - -/* - * SPI baud rate prescaler and scaler values, indexed by the clocking and timing - * attribute register (CTAR) parameters CTAR[PBR] and CTAR[BR], respectively. - */ - -static const uint32_t baud_rate_prescaler[] = { 2, 3, 5, 7 }; -static const uint32_t baud_rate_scaler[] = { - 2, 4, 6, 8, 16, 32, 64, 128, 256, 512, - 1024, 2048, 4096, 8192, 16384, 32768 -}; -/* - * SPI delay prescaler and scaler values, indexed by clocking and timing - * attribute register (CTAR) parameter pairs: - * CTAR[PCSSCK]/CTAR[CSSCK] for the PCS to SCK delay, - * CTAR[PASC]/CTAR[ASC] for the after SCK delay, and - * CTAR[PDT]/CTAR[DT] for the after transfer delay. - */ - -static const uint32_t delay_prescaler[] = { 1, 3, 5, 7 }; -static const uint32_t delay_scaler[] = { - 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, - 2048, 4096, 8192, 16384, 32768, 65536 -}; - - -/** - * @brief Halt SPI module operation. - * @param dev Pointer to the device structure for the driver instance - * @return None. - */ -static inline void spi_k64_halt(struct device *dev) -{ - const struct spi_k64_config *info = dev->config->config_info; - - /* Ensure module operation is stopped */ - - sys_set_bit((info->regs + SPI_K64_REG_MCR), SPI_K64_MCR_HALT_BIT); - - while (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TXRXS) { - SYS_LOG_DBG("SPI Controller dev %p is running. Waiting for " - "Halt.", dev); - } - -} - -/** - * @brief Enable SPI module operation. - * @param dev Pointer to the device structure for the driver instance - * @return None. - */ -static inline void spi_k64_start(struct device *dev) -{ - const struct spi_k64_config *info = dev->config->config_info; - - /* Allow module operation */ - - sys_clear_bit((info->regs + SPI_K64_REG_MCR), SPI_K64_MCR_HALT_BIT); - -} - -/** - * @brief Set a SPI baud rate nearest to the desired rate, without exceeding it. - * @param baud_rate The desired baud rate. - * @param ctar_ptr Pointer to clocking and timing attribute storage. - * @return The calculated baud rate or 0 if an error occurred. - */ -static uint32_t spi_k64_set_baud_rate(uint32_t baud_rate, uint32_t *ctar_ptr) -{ - /* - * The 'volatile' attribute is added to some of the variables in this - * function to prevent bad code generation by gcc toolchains for ARM - * when an optimization setting above -O0 is used. - * - * Specifically, a register is loaded with the constant 0 and is used as - * the divisor in a following divide instruction, resulting in a - * divide-by-zero exception. - * This issue has been seen with gcc versions 4.8.1 and 5.2.0. - */ - - /* prescaler values,CTAR[PBR] */ - uint32_t prescaler; - volatile uint32_t best_prescaler; - /* scaler values, CTAR[BR] */ - uint32_t scaler; - volatile uint32_t best_scaler; - /* doubler values,CTAR[DBR]-1 */ - uint32_t dbr, best_dbr; - /* baud rate */ - uint32_t calc_baud_rate; - volatile uint32_t best_baud_rate; - /* calculated differences */ - uint32_t diff, min_diff; - - min_diff = 0xFFFFFFFFU; - best_dbr = 1; - - /* - * Master mode is assumed. - * - * Find the combination of prescaler, scaler and doubler factors that - * results in the baud rate closest to the requested value, without - * exceeding it. - */ - - SYS_LOG_DBG(""); - - /* - * Initialize the prescaler and scaler to their maximum values to calculate - * the minimum baud rate and check if it is greater than the desired rate. - */ - - best_prescaler = SPI_K64_NUM_PRESCALERS - 1; - best_scaler = SPI_K64_NUM_SCALERS - 1; - best_baud_rate = SPI_K64_PROTOCOL_PERIOD_NS / - (baud_rate_prescaler[best_prescaler] * - baud_rate_prescaler[best_scaler]); - - if (best_baud_rate > baud_rate) { - SYS_LOG_ERR("Minimum baud rate %d is greater than " - "desired rate %d", best_baud_rate, baud_rate); - - return 0; - } - - - /* - * Note that no further combinations are checked if the calculated baud rate - * equals the requested baud rate. - */ - - for (prescaler = 0; - (prescaler < SPI_K64_NUM_PRESCALERS) && min_diff; - prescaler++) { - - for (scaler = 0; (scaler < SPI_K64_NUM_SCALERS) && min_diff; scaler++) { - - for (dbr = 1; (dbr < 3) && min_diff; dbr++) { - - calc_baud_rate = ((SPI_K64_PROTOCOL_FREQ * dbr) / - (baud_rate_prescaler[prescaler] * - baud_rate_scaler[scaler])); - - /* ensure the rate will not exceed the one requested */ - - if (baud_rate >= calc_baud_rate) { - - diff = baud_rate - calc_baud_rate; - - if (min_diff > diff) { - - /* a better match was found */ - - min_diff = diff; - best_prescaler = prescaler; - best_scaler = scaler; - best_baud_rate = calc_baud_rate; - best_dbr = dbr; - } - - } - - } - - } - - } - - /* save the best baud rate dbr, prescaler and scaler */ - - *ctar_ptr = *ctar_ptr | SPI_K64_CTAR_DBR_SET(best_dbr - 1) | - SPI_K64_CTAR_PBR_SET(best_prescaler) | best_scaler; - - /* return the actual baud rate */ - - SYS_LOG_DBG("%d bps desired, %d bps set", baud_rate, best_baud_rate); - - return best_baud_rate; -} - -/** - * @brief Set the specified delay nearest to the desired value, but not lower. - * @param delay_id The delay identifier. - * @param delay_ns The desired delay value, in ns. - * @param ctar_ptr Pointer to clocking and timing attribute storage. - * @return The calculated delay or 0 if an error occurred. - */ -static uint32_t spi_k64_set_delay(enum spi_k64_delay_id delay_id, - uint32_t delay_ns, - uint32_t *ctar_ptr) -{ - /* - * The 'volatile' attribute is added to some of the variables in this - * function to prevent bad code generation by gcc toolchains for ARM - * when an optimization setting above -O0 is used. - * - * Specifically, a register is loaded with the constant 0 and is used as - * the divisor in a following divide instruction, resulting in a - * divide-by-zero exception. - * This issue has been seen with gcc versions 4.8.1 and 5.2.0. - */ - - uint32_t prescaler; /* prescaler values */ - volatile uint32_t best_prescaler; - uint32_t scaler; /* scaler values */ - volatile uint32_t best_scaler; - uint32_t calc_delay; /* delay values */ - volatile uint32_t best_delay; - uint32_t diff, min_diff; /* difference values */ - - SYS_LOG_DBG(""); - - /* - * This function can calculate the clocking and timing attribute register - * (CTAR) values for: - * - PCS to SCK delay prescaler (PCSSCK) and scaler (CSSCK), - * - After SCK delay prescaler (PASC) and scaler (ASC), or - * - Delay after transfer prescaler (PDT) and scaler (DT). - */ - - if ((delay_id != DELAY_PCS_TO_SCK) && (delay_id != DELAY_AFTER_SCK) && - (delay_id != DELAY_AFTER_XFER)) { - - SYS_LOG_ERR("Unknown delay type %d", delay_id); - - return 0; - } - - /* - * Initialize the prescaler and scaler to their maximum values to calculate - * the maximum delay and check if it is less than the desired delay. - */ - - best_prescaler = SPI_K64_NUM_PRESCALERS - 1; - best_scaler = SPI_K64_NUM_SCALERS - 1; - best_delay = SPI_K64_PROTOCOL_PERIOD_NS * delay_prescaler[best_prescaler] * - delay_scaler[best_scaler]; - - if (best_delay < delay_ns) { - SYS_LOG_ERR("Maximum delay %d does meet desired minimum of %d", - best_delay, delay_ns); - - return 0; - } - - min_diff = 0xFFFFFFFFU; - - /* - * Check if the minimum delay (prescaler value = 1, scaler value = 2) is - * greater than the desired delay. If so, set the prescaler and scaler to - * their associated minimum in the CTAR (0). - */ - - calc_delay = SPI_K64_PROTOCOL_PERIOD_NS * 2; - - if (calc_delay >= delay_ns) { - best_prescaler = 0; - best_scaler = 0; - min_diff = 0; /* skip remaining calculations */ - } - - - /* - * Note that no further combinations are checked if the calculated delay - * equals the requested delay. - */ - - for (prescaler = 0; - (prescaler < SPI_K64_NUM_PRESCALERS) && min_diff; - prescaler++) { - - for (scaler = 0; (scaler < SPI_K64_NUM_SCALERS) && min_diff; scaler++) { - - calc_delay = SPI_K64_PROTOCOL_PERIOD_NS * - delay_prescaler[prescaler] * delay_scaler[scaler]; - - /* ensure the delay is at least as long as the one requested */ - - if (calc_delay >= delay_ns) { - - diff = calc_delay - delay_ns; - - if (min_diff > diff) { - - /* a better match was found */ - - min_diff = diff; - best_prescaler = prescaler; - best_scaler = scaler; - best_delay = calc_delay; - } - - } - - } - - } - - /* save the best delay prescaler and scaler */ - - switch (delay_id) { - - case DELAY_PCS_TO_SCK: - *ctar_ptr = *ctar_ptr | SPI_K64_CTAR_PCSSCK_SET(best_prescaler) | - SPI_K64_CTAR_CSSCK_SET(best_scaler); - SYS_LOG_DBG("DELAY_PCS_TO_SCK"); - break; - - case DELAY_AFTER_SCK: - *ctar_ptr = *ctar_ptr | SPI_K64_CTAR_PASC_SET(best_prescaler) | - SPI_K64_CTAR_ASC_SET(best_scaler); - SYS_LOG_DBG("DELAY_AFTER_SCK"); - break; - - case DELAY_AFTER_XFER: - *ctar_ptr = *ctar_ptr | SPI_K64_CTAR_PDT_SET(best_prescaler) | - SPI_K64_CTAR_DT_SET(best_scaler); - SYS_LOG_DBG("DELAY_AFTER_XFER"); - break; - - default: - break; - - } - - /* return the actual delay */ - - SYS_LOG_DBG("%d delay desired, %d delay set", delay_ns, best_delay); - - return best_delay; -} - - -/** - * @brief Configure the SPI host controller for operating against slaves - * @param dev Pointer to the device structure for the driver instance - * @param config Pointer to the application provided configuration - * - * @return 0 if successful, another DEV_* code otherwise. - */ -static int spi_k64_configure(struct device *dev, struct spi_config *config) -{ - const struct spi_k64_config *info = dev->config->config_info; - struct spi_k64_data *spi_data = dev->driver_data; - uint32_t flags = config->config; - uint32_t mcr; /* mode configuration attributes, for MCR */ - uint32_t ctar = 0; /* clocking and timing attributes, for CTAR */ - uint32_t frame_sz; /* frame size, in bits */ - - SYS_LOG_DBG("dev %p (regs @ 0x%x) config 0x%x, freq 0x%x", - dev, info->regs, config->config, config->max_sys_freq); - - /* Disable transfer operations during configuration */ - - spi_k64_halt(dev); - - /* - * Set the common configuration: - * Master mode, normal SPI transfers, PCS strobe disabled, - * Rx overflow data ignored, PCSx inactive low signal, Doze disabled, - * Rx/Tx FIFOs enabled. - * - * Also, keep transfers disabled. - */ - - mcr = SPI_K64_MCR_MSTR | SPI_K64_MCR_HALT; - - /* Set PCSx signal polarities and continuous SCK, as requested */ - - mcr |= (SPI_K64_MCR_PCSIS_SET(SPI_PCS_POL_GET(flags)) | - SPI_K64_MCR_CONT_SCKE_SET(SPI_CONT_SCK_GET(flags))); - - sys_write32(mcr, (info->regs + SPI_K64_REG_MCR)); - - - /* Set clocking and timing parameters */ - - - /* SCK polarity and phase, and bit order of data */ - - if (flags & SPI_MODE_CPOL) { - ctar |= SPI_K64_CTAR_CPOL; - } - - if (flags & SPI_MODE_CPHA) { - ctar |= SPI_K64_CTAR_CPHA; - } - - if (flags & SPI_TRANSFER_MASK) { - ctar |= SPI_K64_CTAR_LSBFE; - } - - /* - * Frame size is limited to 16 bits (vs. 8 bit value in struct spi_config), - * programmed as: (frame_size - 1) - */ - - frame_sz = SPI_WORD_SIZE_GET(flags); - if (frame_sz > SPI_K64_WORD_SIZE_MAX) { - SYS_LOG_ERR("Frame size not supported: %u", frame_sz); - return -ENOTSUP; - } - - spi_data->frame_sz = frame_sz; - - ctar |= (SPI_K64_CTAR_FRMSZ_SET(frame_sz - 1)); - - /* Set baud rate and signal timing parameters (delays) */ - - if (spi_k64_set_baud_rate(config->max_sys_freq, &ctar) == 0) { - SYS_LOG_ERR("Cannot set baud rate"); - return -ENOTSUP; - } - - /* - * Set signal timing parameters (delays): - * - PCS to SCK delay is set to the minimum, CTAR[PCSSCK] = CTAR[CSSCK] = 0; - * - After SCK delay is set to at least half of the baud rate period, - * (using the combination of CTAR[PASC] and CTAR[ASC]); and - * - Delay after transfer is set to the minimum, CTAR[PDT] = CTAR[DT] = 0. - */ - - if (spi_k64_set_delay(DELAY_AFTER_SCK, - (NSEC_PER_SEC / 2) / config->max_sys_freq, - &ctar) == 0) { - SYS_LOG_ERR("Cannot set delay"); - return -ENOTSUP; - } - - - SYS_LOG_DBG("MCR: 0x%x CTAR0: 0x%x", mcr, ctar); - - sys_write32(ctar, (info->regs + SPI_K64_REG_CTAR0)); - - /* Initialize Tx/Rx parameters */ - - spi_data->tx_buf = spi_data->rx_buf = NULL; - spi_data->tx_buf_len = spi_data->rx_buf_len = 0; - - /* Store continuous slave/PCS signal selection mode */ - - spi_data->cont_pcs_sel = SPI_CONT_PCS_GET(flags); - - return 0; -} - -/** - * @brief Select a slave to transmit data to. - * - * @param dev Pointer to the device structure for the driver instance - * @param slave An integer identifying the slave, where the bit values denote: - * 0 - Negate the associated PCS signal - * 1 - Assert the associated PCS signal - * - * Note: The polarity of each PCS signal is defined by the Peripheral Chip - * Select inactive state setting, MCR[PCSIS], determined by the configuration - * data parameter to spi_configure()/spi_k64_configure(). - * - * @return 0 if successful, another DEV_* code otherwise. - */ -static int spi_k64_slave_select(struct device *dev, uint32_t slave) -{ - struct spi_k64_data *spi_data = dev->driver_data; - - /* - * Note that the number of valid PCS signals differs for each - * K64 SPI module: - * - SPI0 uses PCS0-5; - * - SPI1 uses PCS0-3; - * - SPI2 uses PCS0-1; - */ - - SYS_LOG_DBG("slave 0x%x selected for dev %p", (uint8_t)slave, dev); - - spi_data->pcs = (uint8_t)slave; - - return 0; -} - -/** - * @brief Read and/or write a defined amount of data through an SPI driver - * - * @param dev Pointer to the device structure for the driver instance - * @param tx_buf Memory buffer that data should be transferred from - * @param tx_buf_len Size of the memory buffer available for reading from - * @param rx_buf Memory buffer that data should be transferred to - * @param rx_buf_len Size of the memory buffer available for writing to - * - * @return 0 if successful, another DEV_* code otherwise. - */ -static int spi_k64_transceive(struct device *dev, - const void *tx_buf, uint32_t tx_buf_len, - void *rx_buf, uint32_t rx_buf_len) -{ - const struct spi_k64_config *info = dev->config->config_info; - struct spi_k64_data *spi_data = dev->driver_data; - uint32_t int_config; /* interrupt configuration */ - uint32_t mcr; - - SYS_LOG_DBG("dev %p, txbuf %p txlen %u rxbuf %p rxlen %u", - dev, tx_buf, tx_buf_len, rx_buf, rx_buf_len); - - /* Check Tx FIFO status */ - - if (tx_buf_len && - ((sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TFFF) == 0)) { - - SYS_LOG_ERR("Tx FIFO is already full"); - return -EBUSY; - } - - /** - * Clear RX and TX FIFO - */ - mcr = sys_read32(info->regs + SPI_K64_REG_MCR); - mcr |= (SPI_K64_MCR_CLR_RXF | SPI_K64_MCR_CLR_TXF); - - if (rx_buf == NULL || rx_buf_len == 0) { - /* Ignore incoming data */ - mcr |= SPI_K64_MCR_ROOE; - } else { - mcr &= ~SPI_K64_MCR_ROOE; - } - sys_write32(mcr, (info->regs + SPI_K64_REG_MCR)); - - /* Clear all status flags */ - sys_write32(SPI_K64_SR_TCF | SPI_K64_SR_TXRXS | SPI_K64_SR_EOQF - | SPI_K64_SR_TFUF | SPI_K64_SR_TFFF - | SPI_K64_SR_RFOF | SPI_K64_SR_RFDF, - (info->regs + SPI_K64_REG_SR)); - - /* Set buffers info */ - spi_data->tx_buf = tx_buf; - spi_data->tx_buf_len = tx_buf_len; - spi_data->rx_buf = rx_buf; - spi_data->rx_buf_len = rx_buf_len; - spi_data->xfer_len = max(tx_buf_len, rx_buf_len); - SYS_LOG_DBG("dev %p, number of transfers %d", dev, spi_data->xfer_len); - - /* enable transfer operations - must be done before enabling interrupts */ - spi_k64_start(dev); - - int_config = sys_read32(info->regs + SPI_K64_REG_RSER); - /* Enable Transmit FIFO Fill interrupt request */ - int_config |= SPI_K64_RSER_TFFF_RE; - - if (rx_buf != NULL && rx_buf_len != 0) { - /* Enable Receive FIFO Drain and Overflow interrupt requests */ - int_config |= SPI_K64_RSER_RFDF_RE | SPI_K64_RSER_RFOF_RE; - } - - sys_write32(int_config, (info->regs + SPI_K64_REG_RSER)); - - /* wait for transfer to complete */ - k_sem_take(&spi_data->device_sync_sem, K_FOREVER); - - /* check completion status */ - if (spi_data->error) { - spi_data->error = 0; - return -EIO; - } - - return 0; -} - -/** - * @brief SPI module data push (write) operation. - * @param dev Pointer to the device structure for the driver instance - * @return None. - */ -static void spi_k64_push_data(struct device *dev) -{ - const struct spi_k64_config *info = dev->config->config_info; - struct spi_k64_data *spi_data = dev->driver_data; - uint32_t data = 0xff | SPI_K64_PUSHR_PCS_SET(spi_data->pcs); - uint32_t status; - DBG_COUNTER_INIT(); - - SYS_LOG_DBG(""); - - do { /* initial status already checked by spi_k64_isr() */ - - /* - * Check if the RX FIFO is full and leave the push loop - * if necessary. - */ - if (spi_data->rx_buf != NULL) { - status = sys_read32(info->regs + SPI_K64_REG_SR); - status &= SPI_K64_SR_RXCTR_MSK; - if (status == SPI_K64_FIFO_MAX) { - break; - } - } - - if (spi_data->xfer_len == 0) { - break; - } - - if (spi_data->tx_buf && (spi_data->tx_buf_len > 0)) { - - if (spi_data->frame_sz > CHAR_BIT) { - - /* get 2nd byte with frame sizes larger than 8 bits */ - - data = (uint32_t)(*(uint16_t *)(spi_data->tx_buf)); - - spi_data->tx_buf += 2; - spi_data->tx_buf_len -= 2; - DBG_COUNTER_INC(); - DBG_COUNTER_INC(); - - } else { - - data = (uint32_t)(*(spi_data->tx_buf)); - - spi_data->tx_buf++; - spi_data->tx_buf_len--; - DBG_COUNTER_INC(); - - } - } - - /* Write data to the selected slave */ - if (spi_data->cont_pcs_sel && (spi_data->xfer_len > 1)) { - /* set continuous PCS enabling */ - data |= SPI_K64_PUSHR_CONT_SET(spi_data->cont_pcs_sel); - } - sys_write32(data, (info->regs + SPI_K64_REG_PUSHR)); - spi_data->xfer_len--; - - /* Clear interrupt */ - sys_write32(SPI_K64_SR_TFFF, (info->regs + SPI_K64_REG_SR)); - - } while (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TFFF); - - SYS_LOG_DBG("Pushed: %d", DBG_COUNTER_RESULT()); -} - -/** - * @brief SPI module data pull (read) operation. - * @param dev Pointer to the device structure for the driver instance - * @return None. - */ -static void spi_k64_pull_data(struct device *dev) -{ - const struct spi_k64_config *info = dev->config->config_info; - struct spi_k64_data *spi_data = dev->driver_data; - uint16_t data; - DBG_COUNTER_INIT(); - - SYS_LOG_DBG(""); - - do { /* initial status already checked by spi_k64_isr() */ - - /* - * Always drain the fifo to prevent overflow when - * rx_buf_len < tx_buf_len. - */ - data = (uint16_t)sys_read32(info->regs + SPI_K64_REG_POPR); - - /* Clear interrupt */ - sys_write32(SPI_K64_SR_RFDF, (info->regs + SPI_K64_REG_SR)); - - if (spi_data->rx_buf == NULL) { - break; - } - - if ((spi_data->frame_sz > CHAR_BIT) && - (spi_data->rx_buf_len > 1)) { - - /* store 2nd byte with frame sizes larger than 8 bits */ - *((uint16_t *)(spi_data->rx_buf)) = data; - spi_data->rx_buf += 2; - spi_data->rx_buf_len -= 2; - DBG_COUNTER_INC(); - DBG_COUNTER_INC(); - - } else if (spi_data->rx_buf_len != 0) { - - *(spi_data->rx_buf) = (uint8_t)data; - spi_data->rx_buf++; - spi_data->rx_buf_len--; - DBG_COUNTER_INC(); - } - - } while (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_RFDF); - - SYS_LOG_DBG("Pulled: %d", DBG_COUNTER_RESULT()); -} - -/** - * @brief Complete SPI module data transfer operations. - * @param dev Pointer to the device structure for the driver instance - * @param error Error condition (0 = no error, otherwise an error occurred) - * @return None. - */ -static void spi_k64_complete(struct device *dev, uint32_t error) -{ - struct spi_k64_data *spi_data = dev->driver_data; - const struct spi_k64_config *info = dev->config->config_info; - uint32_t int_config; /* interrupt configuration */ - - if (error) { - - SYS_LOG_ERR("spi_k64_complete - ERROR condition\n"); - - goto complete; - } - - /* Check for a completed transfer */ - if (spi_data->xfer_len != 0) { - return; - } - if (spi_data->rx_buf && (spi_data->rx_buf_len != 0)) { - return; - } - SYS_LOG_DBG("Transfer completed, disable interrupts"); - -complete: - - /* disable all interrupts */ - int_config = sys_read32(info->regs + SPI_K64_REG_RSER); - int_config &= ~(SPI_K64_RSER_TFFF_RE - | SPI_K64_RSER_RFDF_RE - | SPI_K64_RSER_RFOF_RE); - sys_write32(int_config, (info->regs + SPI_K64_REG_RSER)); - - spi_data->tx_buf = spi_data->rx_buf = NULL; - spi_data->tx_buf_len = spi_data->rx_buf_len = 0; - spi_data->xfer_len = 0; - - /* Disable transfer operations */ - - spi_k64_halt(dev); - - /* Save status */ - - spi_data->error = error; - - /* Signal completion */ - - k_sem_give(&spi_data->device_sync_sem); -} - -/** - * @brief SPI module interrupt handler. - * @param arg Pointer to the device structure for the driver instance - * @return None. - */ -void spi_k64_isr(void *arg) -{ - struct device *dev = arg; - const struct spi_k64_config *info = dev->config->config_info; - uint32_t error = 0; - uint32_t status; - uint32_t int_config; - - status = sys_read32(info->regs + SPI_K64_REG_SR); - int_config = sys_read32(info->regs + SPI_K64_REG_RSER); - - SYS_LOG_DBG("dev %p, SR 0x%x, RSER 0x%x", dev, status, int_config); - - if (status & SPI_K64_SR_TFUF) { - SYS_LOG_ERR("Tx underflow\n"); - error = 1; - - } else if ((status & SPI_K64_SR_RFOF) && - (int_config & SPI_K64_RSER_RFOF_RE)) { - SYS_LOG_ERR("Rx overflow\n"); - error = 1; - - } else { - if (status & SPI_K64_SR_TFFF) { - spi_k64_push_data(dev); - } - - if (status & SPI_K64_SR_RFDF) { - spi_k64_pull_data(dev); - } - } - - /* finish processing, if data transfer is complete */ - spi_k64_complete(dev, error); -} - -static const struct spi_driver_api k64_spi_api = { - .configure = spi_k64_configure, - .slave_select = spi_k64_slave_select, - .transceive = spi_k64_transceive, -}; - -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT -/** - * @brief API to set device power state - * - * This function simply sets the device power state in driver_data - * - * @param dev Device struct - * @param power_state device power state to be saved - * @return N/A - */ -static void spi_k64_set_power_state(struct device *dev, uint32_t power_state) -{ - struct spi_k64_data *context = dev->driver_data; - - context->device_power_state = power_state; -} -#else -#define spi_k64_set_power_state(...) -#endif - -int spi_k64_init(struct device *dev) -{ - const struct spi_k64_config *info = dev->config->config_info; - struct spi_k64_data *data = dev->driver_data; - uint32_t mcr; - - /* Enable module clocking */ - - sys_set_bit(info->clk_gate_reg, info->clk_gate_bit); - - /* - * Ensure module operation is stopped and enabled before writing anything - * more to the registers. - * (Clear MCR[MDIS] and set MCR[HALT].) - */ - - SYS_LOG_DBG("halt"); - mcr = SPI_K64_MCR_HALT; - sys_write32(mcr, (info->regs + SPI_K64_REG_MCR)); - - while (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TXRXS) { - SYS_LOG_DBG("SPI Controller dev %p is running. Waiting for " - "Halt.", dev); - } - - /* Clear Tx and Rx FIFOs */ - - mcr |= (SPI_K64_MCR_CLR_RXF | SPI_K64_MCR_CLR_TXF); - - SYS_LOG_DBG("fifo clr"); - sys_write32(mcr, (info->regs + SPI_K64_REG_MCR)); - - /* Set master mode */ - - mcr = SPI_K64_MCR_MSTR | SPI_K64_MCR_HALT; - SYS_LOG_DBG("Set master mode"); - sys_write32(mcr, (info->regs + SPI_K64_REG_MCR)); - - /* Disable SPI module interrupt generation */ - - SYS_LOG_DBG("Disable irq"); - sys_write32(0, (info->regs + SPI_K64_REG_RSER)); - - /* Clear status */ - - SYS_LOG_DBG("Clear status"); - sys_write32((SPI_K64_SR_RFDF | SPI_K64_SR_RFOF | SPI_K64_SR_TFUF | - SPI_K64_SR_EOQF | SPI_K64_SR_TCF), - (info->regs + SPI_K64_REG_SR)); - - /* Set up the synchronous call mechanism */ - - k_sem_init(&data->device_sync_sem, 0, UINT_MAX); - - /* Configure and enable SPI module IRQs */ - - info->config_func(); - - spi_k64_set_power_state(dev, DEVICE_PM_ACTIVE_STATE); - - irq_enable(info->irq); - - SYS_LOG_DBG("K64 SPI Driver initialized on device: %p", dev); - - /* operation remains disabled (MCR[HALT] = 1)*/ - - return 0; -} - -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT -/** - * @brief API to get device power state - * - * This function simply returns the device power state - * from driver_data - * - * @param dev Device struct - * @return device power state - */ -static uint32_t spi_k64_get_power_state(struct device *dev) -{ - struct spi_k64_data *context = dev->driver_data; - - return context->device_power_state; -} -/** - * @brief Suspend SPI host controller operations. - * @param dev Pointer to the device structure for the driver instance - * @return 0 if successful, a negative errno value otherwise. - */ -static int spi_k64_suspend(struct device *dev) -{ - const struct spi_k64_config *info = dev->config->config_info; - - SYS_LOG_DBG("dev %p", dev); - - if (sys_read32(info->regs + SPI_K64_REG_SR) & SPI_K64_SR_TXRXS) - return -EBUSY; - - /* disable module */ - - sys_set_bit((info->regs + SPI_K64_REG_MCR), SPI_K64_MCR_MDIS_BIT); - - spi_k64_set_power_state(dev, DEVICE_PM_SUSPEND_STATE); - - irq_disable(info->irq); - - return 0; -} - -/** - * @brief Resume SPI host controller operations. - * @param dev Pointer to the device structure for the driver instance - * @return 0 if successful, a negative errno value otherwise. - */ -static int spi_k64_resume_from_suspend(struct device *dev) -{ - const struct spi_k64_config *info = dev->config->config_info; - - SYS_LOG_DBG("dev %p", dev); - - /* enable module */ - - sys_clear_bit((info->regs + SPI_K64_REG_MCR), SPI_K64_MCR_MDIS_BIT); - - spi_k64_set_power_state(dev, DEVICE_PM_ACTIVE_STATE); - - irq_enable(info->irq); - - return 0; -} - -/* -* Implements the driver control management functionality -* the *context may include IN data or/and OUT data -*/ -static int spi_k64_device_ctrl(struct device *dev, uint32_t ctrl_command, - void *context) -{ - if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { - if (*((uint32_t *)context) == DEVICE_PM_SUSPEND_STATE) { - return spi_k64_suspend(dev); - } else if (*((uint32_t *)context) == DEVICE_PM_ACTIVE_STATE) { - return spi_k64_resume_from_suspend(dev); - } - } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { - *((uint32_t *)context) = spi_k64_get_power_state(dev); - return 0; - } - - return 0; -} -#else -#define spi_k64_set_power_state(...) -#endif - -/* system bindings */ -#ifdef CONFIG_SPI_0 - -void spi_config_0_irq(void); - -struct spi_k64_data spi_k64_data_port_0; - -static const struct spi_k64_config spi_k64_config_0 = { - .regs = SPI_K64_0_BASE_ADDR, - .clk_gate_reg = SPI_K64_0_CLK_GATE_REG_ADDR, - .clk_gate_bit = SPI_K64_0_CLK_GATE_REG_BIT, - .irq = SPI_K64_0_IRQ, - .config_func = spi_config_0_irq -}; - -DEVICE_DEFINE(spi_k64_port_0, CONFIG_SPI_0_NAME, spi_k64_init, - spi_k64_device_ctrl, &spi_k64_data_port_0, - &spi_k64_config_0, POST_KERNEL, - CONFIG_SPI_INIT_PRIORITY, &k64_spi_api); - - -void spi_config_0_irq(void) -{ - IRQ_CONNECT(SPI_K64_0_IRQ, CONFIG_SPI_0_IRQ_PRI, - spi_k64_isr, DEVICE_GET(spi_k64_port_0), 0); -} - -#endif /* CONFIG_SPI_0 */ - - -#ifdef CONFIG_SPI_1 - -void spi_config_1_irq(void); - -struct spi_k64_data spi_k64_data_port_1; - -static const struct spi_k64_config spi_k64_config_1 = { - .regs = SPI_K64_1_BASE_ADDR, - .clk_gate_reg = SPI_K64_1_CLK_GATE_REG_ADDR, - .clk_gate_bit = SPI_K64_1_CLK_GATE_REG_BIT, - .irq = SPI_K64_1_IRQ, - .config_func = spi_config_1_irq -}; - -DEVICE_DEFINE(spi_k64_port_1, CONFIG_SPI_1_NAME, spi_k64_init, - spi_k64_device_ctrl, &spi_k64_data_port_1, - &spi_k64_config_1, POST_KERNEL, - CONFIG_SPI_INIT_PRIORITY, &k64_spi_api); - - -void spi_config_1_irq(void) -{ - IRQ_CONNECT(SPI_K64_1_IRQ, CONFIG_SPI_1_IRQ_PRI, - spi_k64_isr, DEVICE_GET(spi_k64_port_1), 0); -} - -#endif /* CONFIG_SPI_1 */ - - -#ifdef CONFIG_SPI_2 - -void spi_config_2_irq(void); - -struct spi_k64_data spi_k64_data_port_2; - -static const struct spi_k64_config spi_k64_config_2 = { - .regs = SPI_K64_2_BASE_ADDR, - .clk_gate_reg = SPI_K64_2_CLK_GATE_REG_ADDR, - .clk_gate_bit = SPI_K64_2_CLK_GATE_REG_BIT, - .irq = SPI_K64_2_IRQ, - .config_func = spi_config_2_irq -}; - -DEVICE_DEFINE(spi_k64_port_2, CONFIG_SPI_2_NAME, spi_k64_init, - spi_k64_device_ctrl, &spi_k64_data_port_2, - &spi_k64_config_2, POST_KERNEL, - CONFIG_SPI_INIT_PRIORITY, &k64_spi_api); - - -void spi_config_2_irq(void) -{ - IRQ_CONNECT(SPI_K64_2_IRQ, CONFIG_SPI_2_IRQ_PRI, - spi_k64_isr, DEVICE_GET(spi_k64_port_2), 0); -} - -#endif /* CONFIG_SPI_2 */ diff --git a/drivers/spi/spi_k64_priv.h b/drivers/spi/spi_k64_priv.h deleted file mode 100644 index 02718f035..000000000 --- a/drivers/spi/spi_k64_priv.h +++ /dev/null @@ -1,166 +0,0 @@ -/* spi_k64_priv.h - Freescale K64 SPI driver private definitions */ - -/* - * Copyright (c) 2015-2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __SPI_K64_PRIV_H__ -#define __SPI_K64_PRIV_H__ - -typedef void (*spi_k64_config_t)(void); - -struct spi_k64_config { - uint32_t regs; /* base address of SPI module registers */ - uint32_t clk_gate_reg; /* SPI module's clock gate register addr. */ - uint32_t clk_gate_bit; /* SPI module's clock gate bit position */ - uint32_t irq; /* SPI module IRQ number */ - spi_k64_config_t config_func; /* IRQ configuration function pointer */ -}; - -struct spi_k64_data { - uint8_t frame_sz; /* frame/word size, in bits */ - uint8_t cont_pcs_sel; /* continuous slave/PCS selection enable */ - uint8_t pcs; /* slave/PCS selection */ - const uint8_t *tx_buf; - uint32_t tx_buf_len; - uint8_t *rx_buf; - uint32_t rx_buf_len; - uint32_t xfer_len; - struct k_sem device_sync_sem; /* sync call information */ - uint8_t error; /* error condition */ -#ifdef CONFIG_DEVICE_POWER_MANAGEMENT - uint32_t device_power_state; -#endif -}; - -/* Data transfer signal timing delays */ - -enum spi_k64_delay_id { - DELAY_PCS_TO_SCK, - DELAY_AFTER_SCK, - DELAY_AFTER_XFER -}; - -/* Register offsets */ - -#define SPI_K64_REG_MCR (0x00) -#define SPI_K64_REG_TCR (0x08) -#define SPI_K64_REG_CTAR0 (0x0C) -#define SPI_K64_REG_CTAR1 (0x10) -#define SPI_K64_REG_SR (0x2C) -#define SPI_K64_REG_RSER (0x30) -#define SPI_K64_REG_PUSHR (0x34) -#define SPI_K64_REG_POPR (0x38) -#define SPI_K64_REG_TXFR0 (0x3C) -#define SPI_K64_REG_RXFR0 (0x7C) - -/* Module Control Register (MCR) settings */ - -#define SPI_K64_MCR_HALT (0x1) -#define SPI_K64_MCR_HALT_BIT (0) - -#define SPI_K64_MCR_SMPL_PT_MSK (0x3 << 8) - -#define SPI_K64_MCR_CLR_RXF (0x1 << 10) -#define SPI_K64_MCR_CLR_TXF (0x1 << 11) -#define SPI_K64_MCR_DIS_RXF (0x1 << 12) -#define SPI_K64_MCR_DIS_TXF (0x1 << 13) -#define SPI_K64_MCR_MDIS (0x1 << 14) -#define SPI_K64_MCR_MDIS_BIT (14) -#define SPI_K64_MCR_DOZE (0x1 << 15) - -#define SPI_K64_MCR_PCSIS_MSK (0x3F << 16) -#define SPI_K64_MCR_PCSIS_SET(pcsis) ((pcsis) << 16) - -#define SPI_K64_MCR_ROOE (0x1 << 24) -#define SPI_K64_MCR_PCSSE (0x1 << 25) -#define SPI_K64_MCR_MTFE (0x1 << 26) -#define SPI_K64_MCR_FRZ (0x1 << 27) - -#define SPI_K64_MCR_DCONF_MSK (0x3 << 28) - -#define SPI_K64_MCR_CONT_SCKE (0x1 << 30) -#define SPI_K64_MCR_CONT_SCKE_SET(cont) ((cont) << 30) - -#define SPI_K64_MCR_MSTR (0x1 << 31) - -/* Clock and Transfer Attributes Register (CTAR) settings */ - -#define SPI_K64_CTAR_BR_MSK (0xF) - -#define SPI_K64_CTAR_DT_MSK (0xF << 4) -#define SPI_K64_CTAR_DT_SET(dt) ((dt) << 4) -#define SPI_K64_CTAR_ASC_MSK (0xF << 8) -#define SPI_K64_CTAR_ASC_SET(asc) ((asc) << 8) -#define SPI_K64_CTAR_CSSCK_MSK (0xF << 12) -#define SPI_K64_CTAR_CSSCK_SET(cssck) ((cssck) << 12) - -#define SPI_K64_CTAR_PBR_MSK (0x3 << 16) -#define SPI_K64_CTAR_PBR_SET(pbr) ((pbr) << 16) - -#define SPI_K64_CTAR_PDT_MSK (0xF << 18) -#define SPI_K64_CTAR_PDT_SET(pdt) ((pdt) << 18) -#define SPI_K64_CTAR_PASC_MSK (0xF << 20) -#define SPI_K64_CTAR_PASC_SET(pasc) ((pasc) << 20) -#define SPI_K64_CTAR_PCSSCK_MSK (0xF << 22) -#define SPI_K64_CTAR_PCSSCK_SET(pcssck) ((pcssck) << 22) - -#define SPI_K64_CTAR_LSBFE (0x1 << 24) -#define SPI_K64_CTAR_CPHA (0x1 << 25) -#define SPI_K64_CTAR_CPOL (0x1 << 26) - -#define SPI_K64_CTAR_FRMSZ_MSK (0xF << 27) -#define SPI_K64_CTAR_FRMSZ_SET(sz) ((sz) << 27) - -#define SPI_K64_CTAR_DBR (0x1 << 31) -#define SPI_K64_CTAR_DBR_SET(dbr) ((dbr) << 31) - -/* Status Register (SR) settings */ - -#define SPI_K64_SR_POPNXTPTR_MSK (0xF) -#define SPI_K64_SR_RXCTR_MSK (0xF << 4) -#define SPI_K64_SR_TXNXTPTR_MSK (0xF << 8) -#define SPI_K64_SR_TXCTR_MSK (0xF << 12) - -#define SPI_K64_SR_RFDF (0x1 << 17) -#define SPI_K64_SR_RFOF (0x1 << 19) -#define SPI_K64_SR_TFFF (0x1 << 25) -#define SPI_K64_SR_TFUF (0x1 << 27) -#define SPI_K64_SR_EOQF (0x1 << 28) -#define SPI_K64_SR_TXRXS (0x1 << 30) -#define SPI_K64_SR_TCF (0x1 << 31) - -/* DMA/Interrupt Request Select and Enable Register (RSER) settings */ - -#define SPI_K64_RSER_RFDF_DIRS (0x1 << 16) -#define SPI_K64_RSER_RFDF_RE (0x1 << 17) -#define SPI_K64_RSER_RFOF_RE (0x1 << 19) -#define SPI_K64_RSER_TFFF_DIRS (0x1 << 24) -#define SPI_K64_RSER_TFFF_RE (0x1 << 25) -#define SPI_K64_RSER_TFUF_RE (0x1 << 27) -#define SPI_K64_RSER_EOQF_RE (0x1 << 28) -#define SPI_K64_RSER_TCF_RE (0x1 << 31) - -/* Push Tx FIFO Register (PUSHR) settings */ - -#define SPI_K64_PUSHR_TXDATA_MSK (0xFF) -#define SPI_K64_PUSHR_PCS_MSK (0x3F << 16) -#define SPI_K64_PUSHR_PCS_SET(pcs) ((pcs) << 16) - -#define SPI_K64_PUSHR_CTCNT (0x1 << 26) -#define SPI_K64_PUSHR_EOQ (0x1 << 27) - -#define SPI_K64_PUSHR_CTAS_MSK (0x7 << 28) - -#define SPI_K64_PUSHR_CONT (0x1 << 31) -#define SPI_K64_PUSHR_CONT_SET(cont) ((cont) << 31) - -/* Tx FIFO Register (TXFR) settings */ - -#define SPI_K64_TXFR_TXDATA_MSK (0xFFFF) -#define SPI_K64_TXFR_TXCMD_MSK (0xFFFF << 16) - - -#endif /* __SPI_K64_PRIV_H__ */ |