linux/drivers/spi/spi-atmel.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Driver for Atmel AT32 and AT91 SPI Controllers
 *
 * Copyright (C) 2006 Atmel Corporation
 */

#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/of.h>

#include <linux/io.h>
#include <linux/gpio/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/iopoll.h>
#include <trace/events/spi.h>

/* SPI register offsets */
#define SPI_CR
#define SPI_MR
#define SPI_RDR
#define SPI_TDR
#define SPI_SR
#define SPI_IER
#define SPI_IDR
#define SPI_IMR
#define SPI_CSR0
#define SPI_CSR1
#define SPI_CSR2
#define SPI_CSR3
#define SPI_FMR
#define SPI_FLR
#define SPI_VERSION
#define SPI_RPR
#define SPI_RCR
#define SPI_TPR
#define SPI_TCR
#define SPI_RNPR
#define SPI_RNCR
#define SPI_TNPR
#define SPI_TNCR
#define SPI_PTCR
#define SPI_PTSR

/* Bitfields in CR */
#define SPI_SPIEN_OFFSET
#define SPI_SPIEN_SIZE
#define SPI_SPIDIS_OFFSET
#define SPI_SPIDIS_SIZE
#define SPI_SWRST_OFFSET
#define SPI_SWRST_SIZE
#define SPI_LASTXFER_OFFSET
#define SPI_LASTXFER_SIZE
#define SPI_TXFCLR_OFFSET
#define SPI_TXFCLR_SIZE
#define SPI_RXFCLR_OFFSET
#define SPI_RXFCLR_SIZE
#define SPI_FIFOEN_OFFSET
#define SPI_FIFOEN_SIZE
#define SPI_FIFODIS_OFFSET
#define SPI_FIFODIS_SIZE

/* Bitfields in MR */
#define SPI_MSTR_OFFSET
#define SPI_MSTR_SIZE
#define SPI_PS_OFFSET
#define SPI_PS_SIZE
#define SPI_PCSDEC_OFFSET
#define SPI_PCSDEC_SIZE
#define SPI_FDIV_OFFSET
#define SPI_FDIV_SIZE
#define SPI_MODFDIS_OFFSET
#define SPI_MODFDIS_SIZE
#define SPI_WDRBT_OFFSET
#define SPI_WDRBT_SIZE
#define SPI_LLB_OFFSET
#define SPI_LLB_SIZE
#define SPI_PCS_OFFSET
#define SPI_PCS_SIZE
#define SPI_DLYBCS_OFFSET
#define SPI_DLYBCS_SIZE

/* Bitfields in RDR */
#define SPI_RD_OFFSET
#define SPI_RD_SIZE

/* Bitfields in TDR */
#define SPI_TD_OFFSET
#define SPI_TD_SIZE

/* Bitfields in SR */
#define SPI_RDRF_OFFSET
#define SPI_RDRF_SIZE
#define SPI_TDRE_OFFSET
#define SPI_TDRE_SIZE
#define SPI_MODF_OFFSET
#define SPI_MODF_SIZE
#define SPI_OVRES_OFFSET
#define SPI_OVRES_SIZE
#define SPI_ENDRX_OFFSET
#define SPI_ENDRX_SIZE
#define SPI_ENDTX_OFFSET
#define SPI_ENDTX_SIZE
#define SPI_RXBUFF_OFFSET
#define SPI_RXBUFF_SIZE
#define SPI_TXBUFE_OFFSET
#define SPI_TXBUFE_SIZE
#define SPI_NSSR_OFFSET
#define SPI_NSSR_SIZE
#define SPI_TXEMPTY_OFFSET
#define SPI_TXEMPTY_SIZE
#define SPI_SPIENS_OFFSET
#define SPI_SPIENS_SIZE
#define SPI_TXFEF_OFFSET
#define SPI_TXFEF_SIZE
#define SPI_TXFFF_OFFSET
#define SPI_TXFFF_SIZE
#define SPI_TXFTHF_OFFSET
#define SPI_TXFTHF_SIZE
#define SPI_RXFEF_OFFSET
#define SPI_RXFEF_SIZE
#define SPI_RXFFF_OFFSET
#define SPI_RXFFF_SIZE
#define SPI_RXFTHF_OFFSET
#define SPI_RXFTHF_SIZE
#define SPI_TXFPTEF_OFFSET
#define SPI_TXFPTEF_SIZE
#define SPI_RXFPTEF_OFFSET
#define SPI_RXFPTEF_SIZE

/* Bitfields in CSR0 */
#define SPI_CPOL_OFFSET
#define SPI_CPOL_SIZE
#define SPI_NCPHA_OFFSET
#define SPI_NCPHA_SIZE
#define SPI_CSAAT_OFFSET
#define SPI_CSAAT_SIZE
#define SPI_BITS_OFFSET
#define SPI_BITS_SIZE
#define SPI_SCBR_OFFSET
#define SPI_SCBR_SIZE
#define SPI_DLYBS_OFFSET
#define SPI_DLYBS_SIZE
#define SPI_DLYBCT_OFFSET
#define SPI_DLYBCT_SIZE

/* Bitfields in RCR */
#define SPI_RXCTR_OFFSET
#define SPI_RXCTR_SIZE

/* Bitfields in TCR */
#define SPI_TXCTR_OFFSET
#define SPI_TXCTR_SIZE

/* Bitfields in RNCR */
#define SPI_RXNCR_OFFSET
#define SPI_RXNCR_SIZE

/* Bitfields in TNCR */
#define SPI_TXNCR_OFFSET
#define SPI_TXNCR_SIZE

/* Bitfields in PTCR */
#define SPI_RXTEN_OFFSET
#define SPI_RXTEN_SIZE
#define SPI_RXTDIS_OFFSET
#define SPI_RXTDIS_SIZE
#define SPI_TXTEN_OFFSET
#define SPI_TXTEN_SIZE
#define SPI_TXTDIS_OFFSET
#define SPI_TXTDIS_SIZE

/* Bitfields in FMR */
#define SPI_TXRDYM_OFFSET
#define SPI_TXRDYM_SIZE
#define SPI_RXRDYM_OFFSET
#define SPI_RXRDYM_SIZE
#define SPI_TXFTHRES_OFFSET
#define SPI_TXFTHRES_SIZE
#define SPI_RXFTHRES_OFFSET
#define SPI_RXFTHRES_SIZE

/* Bitfields in FLR */
#define SPI_TXFL_OFFSET
#define SPI_TXFL_SIZE
#define SPI_RXFL_OFFSET
#define SPI_RXFL_SIZE

/* Constants for BITS */
#define SPI_BITS_8_BPT
#define SPI_BITS_9_BPT
#define SPI_BITS_10_BPT
#define SPI_BITS_11_BPT
#define SPI_BITS_12_BPT
#define SPI_BITS_13_BPT
#define SPI_BITS_14_BPT
#define SPI_BITS_15_BPT
#define SPI_BITS_16_BPT
#define SPI_ONE_DATA
#define SPI_TWO_DATA
#define SPI_FOUR_DATA

/* Bit manipulation macros */
#define SPI_BIT(name)
#define SPI_BF(name, value)
#define SPI_BFEXT(name, value)
#define SPI_BFINS(name, value, old)

/* Register access macros */
#define spi_readl(port, reg)
#define spi_writel(port, reg, value)
#define spi_writew(port, reg, value)

/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
 * cache operations; better heuristics consider wordsize and bitrate.
 */
#define DMA_MIN_BYTES

#define AUTOSUSPEND_TIMEOUT

struct atmel_spi_caps {};

/*
 * The core SPI transfer engine just talks to a register bank to set up
 * DMA transfers; transfer queue progress is driven by IRQs.  The clock
 * framework provides the base clock, subdivided for each spi_device.
 */
struct atmel_spi {};

/* Controller-specific per-slave state */
struct atmel_spi_device {};

#define SPI_MAX_DMA_XFER
#define INVALID_DMA_ADDRESS

/*
 * This frequency can be anything supported by the controller, but to avoid
 * unnecessary delay, the highest possible frequency is chosen.
 *
 * This frequency is the highest possible which is not interfering with other
 * chip select registers (see Note for Serial Clock Bit Rate configuration in
 * Atmel-11121F-ATARM-SAMA5D3-Series-Datasheet_02-Feb-16, page 1283)
 */
#define DUMMY_MSG_FREQUENCY
/*
 * 8 bits is the minimum data the controller is capable of sending.
 *
 * This message can be anything as it should not be treated by any SPI device.
 */
#define DUMMY_MSG

/*
 * Version 2 of the SPI controller has
 *  - CR.LASTXFER
 *  - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero)
 *  - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
 *  - SPI_CSRx.CSAAT
 *  - SPI_CSRx.SBCR allows faster clocking
 */
static bool atmel_spi_is_v2(struct atmel_spi *as)
{}

/*
 * Send a dummy message.
 *
 * This is sometimes needed when using a CS GPIO to force clock transition when
 * switching between devices with different polarities.
 */
static void atmel_spi_send_dummy(struct atmel_spi *as, struct spi_device *spi, int chip_select)
{}


/*
 * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
 * they assume that spi slave device state will not change on deselect, so
 * that automagic deselection is OK.  ("NPCSx rises if no data is to be
 * transmitted")  Not so!  Workaround uses nCSx pins as GPIOs; or newer
 * controllers have CSAAT and friends.
 *
 * Even controller newer than ar91rm9200, using GPIOs can make sens as
 * it lets us support active-high chipselects despite the controller's
 * belief that only active-low devices/systems exists.
 *
 * However, at91rm9200 has a second erratum whereby nCS0 doesn't work
 * right when driven with GPIO.  ("Mode Fault does not allow more than one
 * Master on Chip Select 0.")  No workaround exists for that ... so for
 * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
 * and (c) will trigger that first erratum in some cases.
 *
 * When changing the clock polarity, the SPI controller waits for the next
 * transmission to enforce the default clock state. This may be an issue when
 * using a GPIO as Chip Select: the clock level is applied only when the first
 * packet is sent, once the CS has already been asserted. The workaround is to
 * avoid this by sending a first (dummy) message before toggling the CS state.
 */
static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
{}

static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
{}

static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock)
{}

static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock)
{}

static inline bool atmel_spi_is_vmalloc_xfer(struct spi_transfer *xfer)
{}

static inline bool atmel_spi_use_dma(struct atmel_spi *as,
				struct spi_transfer *xfer)
{}

static bool atmel_spi_can_dma(struct spi_controller *host,
			      struct spi_device *spi,
			      struct spi_transfer *xfer)
{}

static int atmel_spi_dma_slave_config(struct atmel_spi *as, u8 bits_per_word)
{}

static int atmel_spi_configure_dma(struct spi_controller *host,
				   struct atmel_spi *as)
{}

static void atmel_spi_stop_dma(struct spi_controller *host)
{}

static void atmel_spi_release_dma(struct spi_controller *host)
{}

/* This function is called by the DMA driver from tasklet context */
static void dma_callback(void *data)
{}

/*
 * Next transfer using PIO without FIFO.
 */
static void atmel_spi_next_xfer_single(struct spi_controller *host,
				       struct spi_transfer *xfer)
{}

/*
 * Next transfer using PIO with FIFO.
 */
static void atmel_spi_next_xfer_fifo(struct spi_controller *host,
				     struct spi_transfer *xfer)
{}

/*
 * Next transfer using PIO.
 */
static void atmel_spi_next_xfer_pio(struct spi_controller *host,
				    struct spi_transfer *xfer)
{}

/*
 * Submit next transfer for DMA.
 */
static int atmel_spi_next_xfer_dma_submit(struct spi_controller *host,
				struct spi_transfer *xfer,
				u32 *plen)
{}

static void atmel_spi_next_xfer_data(struct spi_controller *host,
				struct spi_transfer *xfer,
				dma_addr_t *tx_dma,
				dma_addr_t *rx_dma,
				u32 *plen)
{}

static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
				    struct spi_device *spi,
				    struct spi_transfer *xfer)
{}

/*
 * Submit next transfer for PDC.
 * lock is held, spi irq is blocked
 */
static void atmel_spi_pdc_next_xfer(struct spi_controller *host,
					struct spi_transfer *xfer)
{}

/*
 * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
 *  - The buffer is either valid for CPU access, else NULL
 *  - If the buffer is valid, so is its DMA address
 */
static int
atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
{}

static void atmel_spi_dma_unmap_xfer(struct spi_controller *host,
				     struct spi_transfer *xfer)
{}

static void atmel_spi_disable_pdc_transfer(struct atmel_spi *as)
{}

static void
atmel_spi_pump_single_data(struct atmel_spi *as, struct spi_transfer *xfer)
{}

static void
atmel_spi_pump_fifo_data(struct atmel_spi *as, struct spi_transfer *xfer)
{}

/* Called from IRQ
 *
 * Must update "current_remaining_bytes" to keep track of data
 * to transfer.
 */
static void
atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
{}

/* Interrupt
 *
 */
static irqreturn_t
atmel_spi_pio_interrupt(int irq, void *dev_id)
{}

static irqreturn_t
atmel_spi_pdc_interrupt(int irq, void *dev_id)
{}

static int atmel_word_delay_csr(struct spi_device *spi, struct atmel_spi *as)
{}

static void initialize_native_cs_for_gpio(struct atmel_spi *as)
{}

static int atmel_spi_setup(struct spi_device *spi)
{}

static void atmel_spi_set_cs(struct spi_device *spi, bool enable)
{}

static int atmel_spi_one_transfer(struct spi_controller *host,
					struct spi_device *spi,
					struct spi_transfer *xfer)
{}

static void atmel_spi_cleanup(struct spi_device *spi)
{}

static inline unsigned int atmel_get_version(struct atmel_spi *as)
{}

static void atmel_get_caps(struct atmel_spi *as)
{}

static void atmel_spi_init(struct atmel_spi *as)
{}

static int atmel_spi_probe(struct platform_device *pdev)
{}

static void atmel_spi_remove(struct platform_device *pdev)
{}

static int atmel_spi_runtime_suspend(struct device *dev)
{}

static int atmel_spi_runtime_resume(struct device *dev)
{}

static int atmel_spi_suspend(struct device *dev)
{}

static int atmel_spi_resume(struct device *dev)
{}

static const struct dev_pm_ops atmel_spi_pm_ops =;

static const struct of_device_id atmel_spi_dt_ids[] =;

MODULE_DEVICE_TABLE(of, atmel_spi_dt_ids);

static struct platform_driver atmel_spi_driver =;
module_platform_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();
MODULE_ALIAS();