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 */