ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/linux/drivers/spi/spi-asr.h b/marvell/linux/drivers/spi/spi-asr.h
new file mode 100644
index 0000000..6521b5e
--- /dev/null
+++ b/marvell/linux/drivers/spi/spi-asr.h
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support for asr spi controller
+ *
+ * Copyright (C) 2019 ASR Micro Limited
+ *
+ * Tim Wang <timwang@asrmicro.com>
+ */
+
+#ifndef _SPI_ASR_H
+#define _SPI_ASR_H
+
+#include <linux/atomic.h>
+#include <linux/dmaengine.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/sizes.h>
+#include <linux/spi/spi.h>
+#include <linux/pm_qos.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/spi/spi-mem.h>
+
+/* ASR 180x/190x SPI Registers */
+#define TOP_CTRL 0x00 /* SSP Top Control Register */
+#define FIFO_CTRL 0x04 /* SSP FIFO Control Register */
+#define INT_EN 0x08 /* SSP Interrupt Enable Register */
+#define TO 0x0C /* SSP Time Out Register */
+#define DATAR 0x10 /* SSP Data Register */
+#define STATUS 0x14 /* SSP Stauts Register */
+#define PSP_CTRL 0x18 /* SSP Programmable Serial Protocal Control Register */
+#define NET_WORK_CTRL 0x1C /* SSP NET Work Control Register */
+#define NET_WORK_STATUS 0x20 /* SSP Net Work Status Register */
+#define RWOT_CTRL 0x24 /* SSP RWOT Control Register */
+#define RWOT_CCM 0x28 /* SSP RWOT Counter Cycles Match Register */
+#define RWOT_CVWRn 0x2C /* SSP RWOT Counter Value Write for Read Request Register */
+#define MISC_CTRL 0x30
+
+/* 0x00 TOP_CTRL */
+#define TOP_TTELP (1 << 18)
+#define TOP_TTE (1 << 17)
+#define TOP_SCFR (1 << 16)
+#define TOP_IFS (1 << 15)
+#define TOP_HOLD_FRAME_LOW (1 << 14)
+#define TOP_TRAIL (1 << 13)
+#define TOP_LBM (1 << 12)
+#define TOP_SPH (1 << 11)
+#define TOP_SPO (1 << 10)
+#define TOP_DSS(x) ((x - 1) << 5)
+#define TOP_DSS_MASK (0x1F << 5)
+#define TOP_SFRMDIR (1 << 4)
+#define TOP_SCLKDIR (1 << 3)
+#define TOP_FRF_MASK (0x3 << 1)
+#define TOP_FRF_Motorola (0x0 << 1) /* Motorola's Serial Peripheral Interface (SPI) */
+#define TOP_FRF_TI (0x1 << 1) /* Texas Instruments' Synchronous Serial Protocol (SSP) */
+#define TOP_FRF_National (0x2 << 1) /* National Microwire */
+#define TOP_FRF_PSP (0x3 << 1) /* Programmable Serial Protocol(PSP) */
+#define TOP_SSE (1 << 0)
+
+/* 0x04 FIFO_CTRL */
+#define FIFO_STRF (1 << 19)
+#define FIFO_EFWR (1 << 18)
+#define FIFO_RXFIFO_AUTO_FULL_CTRL (1 << 17)
+#define FIFO_FPCKE (1 << 16)
+#define FIFO_TXFIFO_WR_ENDIAN_MASK (0x3 << 14)
+#define FIFO_RXFIFO_RD_ENDIAN_MASK (0x3 << 12)
+#define FIFO_WR_ENDIAN_16BITS (1 << 14) /* Swap first 16 bits and last 16 bits */
+#define FIFO_WR_ENDIAN_8BITS (2 << 14) /* Swap all 4 bytes */
+#define FIFO_RD_ENDIAN_16BITS (1 << 12) /* Swap first 16 bits and last 16 bits */
+#define FIFO_RD_ENDIAN_8BITS (2 << 12) /* Swap all 4 bytes */
+#define FIFO_RSRE (1 << 11)
+#define FIFO_TSRE (1 << 10)
+
+/* 0x08 INT_EN */
+#define INT_EN_EBCEI (1 << 6)
+#define INT_EN_TIM (1 << 5)
+#define INT_EN_RIM (1 << 4)
+#define INT_EN_TIE (1 << 3)
+#define INT_EN_RIE (1 << 2)
+#define INT_EN_TINTE (1 << 1)
+#define INT_EN_PINTE (1 << 0)
+
+/* 0x0C TO */
+#define TIMEOUT(x) ((x) << 0)
+
+/* 0x10 DATAR */
+#define DATA(x) ((x) << 0)
+
+/* 0x14 STATUS */
+#define STATUS_OSS (1 << 23)
+#define STATUS_TX_OSS (1 << 22)
+#define STATUS_BCE (1 << 21)
+#define STATUS_ROR (1 << 20)
+#define STATUS_RNE (1 << 14)
+#define STATUS_RFS (1 << 13)
+#define STATUS_TUR (1 << 12)
+#define STATUS_TNF (1 << 6)
+#define STATUS_TFS (1 << 5)
+#define STATUS_EOC (1 << 4)
+#define STATUS_TINT (1 << 3)
+#define STATUS_PINT (1 << 2)
+#define STATUS_CSS (1 << 1)
+#define STATUS_BSY (1 << 0)
+
+/* 0x18 PSP_CTRL */
+#define PSP_EDMYSTOP(x) ((x) << 27)
+#define PSP_EMYSTOP(x) ((x) << 25)
+#define PSP_EDMYSTRT(x) ((x) << 23)
+#define PSP_DMYSTRT(x) ((x) << 21)
+#define PSP_STRTDLY(x) ((x) << 18)
+#define PSP_SFRMWDTH(x) ((x) << 12)
+#define PSP_SFRMDLY(x) ((x) << 5)
+#define PSP_SFRMP (1 << 4)
+#define PSP_FSRT (1 << 3)
+#define PSP_ETDS (1 << 2)
+#define PSP_SCMODE(x) ((x) << 0)
+
+/* 0x1C NET_WORK_CTRL */
+#define RTSA(x) ((x) << 12)
+#define RTSA_MASK (0xFF << 12)
+#define TTSA(x) ((x) << 4)
+#define TTSA_MASK (0xFF << 4)
+#define NET_FRDC(x) ((x) << 1)
+#define NET_WORK_MODE (1 << 0)
+
+/* 0x20 NET_WORK_STATUS */
+#define NET_SATUS_NMBSY (1 << 3)
+#define NET_STATUS_TSS(x) ((x) << 0)
+
+/* 0x24 RWOT_CTRL */
+#define RWOT_MASK_RWOT_LAST_SAMPLE (1 << 4)
+#define RWOT_CLR_RWOT_CYCLE (1 << 3)
+#define RWOT_SET_RWOT_CYCLE (1 << 2)
+#define RWOT_CYCLE_RWOT_EN (1 << 1)
+#define RWOT_RWOT (1 << 0)
+
+#define PIO_FIFO_ENTRY_NUM (32)
+
+enum asr_ssp_type {
+ SSP_UNDEFINED = 0,
+ ASR_SSP,
+};
+
+struct spi_driver_data {
+ /* Driver model hookup */
+ struct platform_device *pdev;
+
+ /* SSP Info */
+ struct ssp_device *ssp;
+
+ /* SPI framework hookup */
+ enum asr_ssp_type ssp_type;
+ struct spi_master *master;
+
+ /* ASR hookup */
+ struct asr_spi_master *master_info;
+
+ /* SSP register addresses */
+ void __iomem *ioaddr;
+ u32 ssdr_physical;
+
+ /* SSP masks*/
+ u32 dma_fifo_ctrl;
+ u32 dma_top_ctrl;
+ u32 int_cr;
+ u32 dma_cr;
+ u32 clear_sr;
+ u32 mask_sr;
+
+ /* SPI feature control */
+ u8 pio_cs_auto_deasert;
+ u8 pio_interval_us;
+ u8 one_cycle_delay;
+ u8 cs_comb_ctrl;
+ u32 hold_frame_low;
+ u32 master_rxfifo_timeout;
+ u32 slave_rxfifo_timeout;
+ u32 slave_rxtimer_to_ms;
+
+ /* Message Transfer pump */
+ struct tasklet_struct pump_transfers;
+
+ /* DMA engine support */
+ struct dma_chan *rx_chan;
+ struct dma_chan *tx_chan;
+ struct sg_table rx_sgt;
+ struct sg_table tx_sgt;
+ int rx_nents;
+ int tx_nents;
+ void *dummy;
+ atomic_t dma_running;
+
+ /* Current message transfer state info */
+ struct spi_message *cur_msg;
+ struct spi_transfer *cur_transfer;
+ struct chip_data *cur_chip;
+ size_t len;
+ void *tx;
+ void *tx_end;
+ void *rx;
+ void *rx_end;
+ int dma_mapped;
+ dma_addr_t rx_dma;
+ dma_addr_t tx_dma;
+ size_t rx_map_len;
+ size_t tx_map_len;
+ u8 n_bytes;
+ int (*write)(struct spi_driver_data *drv_data);
+ int (*read)(struct spi_driver_data *drv_data);
+ irqreturn_t (*transfer_handler)(struct spi_driver_data *drv_data);
+ void (*cs_control)(u32 command);
+ struct pm_qos_request qos_idle;
+ int qos_idle_value;
+ struct clk *clk;
+ int irq;
+ u8 unqueued_transfer;
+ u8 no_tasklet;
+ u8 xfer_way;
+ u8 cs_assert;
+ struct completion dma_completion;
+ /* Support RX FIFO auto full control and endian swap */
+ unsigned int ssp_enhancement;
+ unsigned char slave_mode;
+ struct timer_list slave_rx_timer;
+};
+
+enum {
+ XFER_NONE = 0,
+ XFER_PUMP = 1,
+ XFER_UNQUEUE = 2,
+ XFER_SPIMEM = 3,
+};
+
+struct chip_data {
+ u32 top_ctrl;
+ u32 fifo_ctrl;
+ u32 timeout;
+ u8 n_bytes;
+ u32 dma_burst_size;
+ u32 threshold;
+ u32 dma_threshold;
+ u8 enable_dma;
+ union {
+ int gpio_cs;
+ unsigned int frm;
+ };
+ int gpio_cs_inverted;
+ int (*write)(struct spi_driver_data *drv_data);
+ int (*read)(struct spi_driver_data *drv_data);
+ void (*cs_control)(u32 command);
+};
+
+static inline u32 asr_spi_read(const struct spi_driver_data *drv_data,
+ unsigned reg)
+{
+ return __raw_readl(drv_data->ioaddr + reg);
+}
+
+static inline void asr_spi_write(const struct spi_driver_data *drv_data,
+ unsigned reg, u32 val)
+{
+ __raw_writel(val, drv_data->ioaddr + reg);
+}
+
+#define START_STATE ((void *)0)
+#define RUNNING_STATE ((void *)1)
+#define DONE_STATE ((void *)2)
+#define ERROR_STATE ((void *)-1)
+
+#define IS_DMA_ALIGNED(x) IS_ALIGNED((unsigned long)(x), DMA_ALIGNMENT)
+#define DMA_ALIGNMENT 64
+
+extern int asr_spi_flush(struct spi_driver_data *drv_data);
+extern void *asr_spi_next_transfer(struct spi_driver_data *drv_data);
+extern void asr_spi_pump_transfers(struct spi_driver_data *drv_data);
+
+/*
+ * Select the right DMA implementation.
+ */
+#define MAX_DMA_LEN SZ_512K
+#define DEFAULT_DMA_FIFO_CTRL (FIFO_TSRE | FIFO_RSRE)
+#define DEFAULT_DMA_TOP_CTRL (TOP_TRAIL)
+
+extern bool asr_spi_dma_is_possible(size_t len);
+extern int asr_spi_map_dma_buffers(struct spi_driver_data *drv_data);
+extern irqreturn_t asr_spi_dma_transfer(struct spi_driver_data *drv_data);
+extern void asr_spi_slave_sw_timeout_callback(struct spi_driver_data *drv_data);
+extern int asr_spi_dma_prepare(struct spi_driver_data *drv_data, u32 dma_burst);
+extern void asr_spi_dma_start(struct spi_driver_data *drv_data);
+extern int asr_spi_dma_setup(struct spi_driver_data *drv_data);
+extern void asr_spi_dma_release(struct spi_driver_data *drv_data);
+extern int asr_spi_set_dma_burst_and_threshold(struct chip_data *chip,
+ struct spi_device *spi,
+ u8 bits_per_word,
+ u32 *burst_code,
+ u32 *threshold);
+
+#define RX_THRESH_DFLT 8
+#define TX_THRESH_DFLT 8
+/* 0x14 */
+#define STATUS_TFL_MASK (0x1f << 7) /* Transmit FIFO Level mask */
+#define STATUS_TFL_BASE (7)
+#define STATUS_RFL_MASK (0x1f << 15) /* Receive FIFO Level mask */
+#define STATUS_RFL_BASE (15)
+/* 0x4 */
+#define FIFO_TFT (0x0000001F) /* Transmit FIFO Threshold (mask) */
+#define FIFO_TxTresh(x) (((x) - 1) << 0) /* level [1..32] */
+#define FIFO_RFT (0x000003E0) /* Receive FIFO Threshold (mask) */
+#define FIFO_RxTresh(x) (((x) - 1) << 5) /* level [1..32] */
+
+struct ssp_device {
+ struct platform_device *pdev;
+ struct list_head node;
+
+ struct clk *clk;
+ void __iomem *mmio_base;
+ unsigned long phys_base;
+
+ const char *label;
+ int port_id;
+ int type;
+ int use_count;
+ int irq;
+ int drcmr_rx;
+ int drcmr_tx;
+
+ struct device_node *of_node;
+};
+
+/**
+ * asr_ssp_write_reg - Write to a SSP register
+ *
+ * @dev: SSP device to access
+ * @reg: Register to write to
+ * @val: Value to be written.
+ */
+static inline void asr_ssp_write_reg(struct ssp_device *dev, u32 reg, u32 val)
+{
+ __raw_writel(val, dev->mmio_base + reg);
+}
+
+/**
+ * asr_ssp_read_reg - Read from a SSP register
+ *
+ * @dev: SSP device to access
+ * @reg: Register to read from
+ */
+static inline u32 asr_ssp_read_reg(struct ssp_device *dev, u32 reg)
+{
+ return __raw_readl(dev->mmio_base + reg);
+}
+
+static inline void asr_ssp_free(struct ssp_device *ssp) {}
+#define ASR_CS_ASSERT (0x01)
+#define ASR_CS_DEASSERT (0x02)
+
+struct dma_chan;
+
+/* device.platform_data for SSP controller devices */
+struct asr_spi_master {
+ u16 num_chipselect;
+ u8 enable_dma;
+
+ /* DMA engine specific config */
+ bool (*dma_filter)(struct dma_chan *chan, void *param);
+ void *tx_param;
+ void *rx_param;
+
+ /* For sound ssp controller */
+ struct ssp_device ssp;
+};
+
+/* spi_board_info.controller_data for SPI slave devices,
+ * copied to spi_device.platform_data ... mostly for dma tuning
+ */
+struct asr_spi_chip {
+ u8 tx_threshold;
+ u8 tx_hi_threshold;
+ u8 rx_threshold;
+ u8 dma_burst_size;
+ u32 timeout;
+ u8 enable_loopback;
+ int gpio_cs;
+ int using_gpio_cs;
+ void (*cs_control)(u32 command);
+};
+#endif /* _SPI_ASR_H */