162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2012 - 2014 Allwinner Tech
462306a36Sopenharmony_ci * Pan Nan <pannan@allwinnertech.com>
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2014 Maxime Ripard
762306a36Sopenharmony_ci * Maxime Ripard <maxime.ripard@free-electrons.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/bitfield.h>
1162306a36Sopenharmony_ci#include <linux/clk.h>
1262306a36Sopenharmony_ci#include <linux/delay.h>
1362306a36Sopenharmony_ci#include <linux/device.h>
1462306a36Sopenharmony_ci#include <linux/interrupt.h>
1562306a36Sopenharmony_ci#include <linux/io.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/of.h>
1862306a36Sopenharmony_ci#include <linux/platform_device.h>
1962306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2062306a36Sopenharmony_ci#include <linux/reset.h>
2162306a36Sopenharmony_ci#include <linux/dmaengine.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <linux/spi/spi.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define SUN6I_AUTOSUSPEND_TIMEOUT	2000
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define SUN6I_FIFO_DEPTH		128
2862306a36Sopenharmony_ci#define SUN8I_FIFO_DEPTH		64
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define SUN6I_GBL_CTL_REG		0x04
3162306a36Sopenharmony_ci#define SUN6I_GBL_CTL_BUS_ENABLE		BIT(0)
3262306a36Sopenharmony_ci#define SUN6I_GBL_CTL_MASTER			BIT(1)
3362306a36Sopenharmony_ci#define SUN6I_GBL_CTL_TP			BIT(7)
3462306a36Sopenharmony_ci#define SUN6I_GBL_CTL_RST			BIT(31)
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define SUN6I_TFR_CTL_REG		0x08
3762306a36Sopenharmony_ci#define SUN6I_TFR_CTL_CPHA			BIT(0)
3862306a36Sopenharmony_ci#define SUN6I_TFR_CTL_CPOL			BIT(1)
3962306a36Sopenharmony_ci#define SUN6I_TFR_CTL_SPOL			BIT(2)
4062306a36Sopenharmony_ci#define SUN6I_TFR_CTL_CS_MASK			0x30
4162306a36Sopenharmony_ci#define SUN6I_TFR_CTL_CS(cs)			(((cs) << 4) & SUN6I_TFR_CTL_CS_MASK)
4262306a36Sopenharmony_ci#define SUN6I_TFR_CTL_CS_MANUAL			BIT(6)
4362306a36Sopenharmony_ci#define SUN6I_TFR_CTL_CS_LEVEL			BIT(7)
4462306a36Sopenharmony_ci#define SUN6I_TFR_CTL_DHB			BIT(8)
4562306a36Sopenharmony_ci#define SUN6I_TFR_CTL_SDC			BIT(11)
4662306a36Sopenharmony_ci#define SUN6I_TFR_CTL_FBS			BIT(12)
4762306a36Sopenharmony_ci#define SUN6I_TFR_CTL_SDM			BIT(13)
4862306a36Sopenharmony_ci#define SUN6I_TFR_CTL_XCH			BIT(31)
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#define SUN6I_INT_CTL_REG		0x10
5162306a36Sopenharmony_ci#define SUN6I_INT_CTL_RF_RDY			BIT(0)
5262306a36Sopenharmony_ci#define SUN6I_INT_CTL_TF_ERQ			BIT(4)
5362306a36Sopenharmony_ci#define SUN6I_INT_CTL_RF_OVF			BIT(8)
5462306a36Sopenharmony_ci#define SUN6I_INT_CTL_TC			BIT(12)
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#define SUN6I_INT_STA_REG		0x14
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define SUN6I_FIFO_CTL_REG		0x18
5962306a36Sopenharmony_ci#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_MASK	0xff
6062306a36Sopenharmony_ci#define SUN6I_FIFO_CTL_RF_DRQ_EN		BIT(8)
6162306a36Sopenharmony_ci#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS	0
6262306a36Sopenharmony_ci#define SUN6I_FIFO_CTL_RF_RST			BIT(15)
6362306a36Sopenharmony_ci#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_MASK	0xff
6462306a36Sopenharmony_ci#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS	16
6562306a36Sopenharmony_ci#define SUN6I_FIFO_CTL_TF_DRQ_EN		BIT(24)
6662306a36Sopenharmony_ci#define SUN6I_FIFO_CTL_TF_RST			BIT(31)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#define SUN6I_FIFO_STA_REG		0x1c
6962306a36Sopenharmony_ci#define SUN6I_FIFO_STA_RF_CNT_MASK		GENMASK(7, 0)
7062306a36Sopenharmony_ci#define SUN6I_FIFO_STA_TF_CNT_MASK		GENMASK(23, 16)
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#define SUN6I_CLK_CTL_REG		0x24
7362306a36Sopenharmony_ci#define SUN6I_CLK_CTL_CDR2_MASK			0xff
7462306a36Sopenharmony_ci#define SUN6I_CLK_CTL_CDR2(div)			(((div) & SUN6I_CLK_CTL_CDR2_MASK) << 0)
7562306a36Sopenharmony_ci#define SUN6I_CLK_CTL_CDR1_MASK			0xf
7662306a36Sopenharmony_ci#define SUN6I_CLK_CTL_CDR1(div)			(((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8)
7762306a36Sopenharmony_ci#define SUN6I_CLK_CTL_DRS			BIT(12)
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#define SUN6I_MAX_XFER_SIZE		0xffffff
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#define SUN6I_BURST_CNT_REG		0x30
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#define SUN6I_XMIT_CNT_REG		0x34
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#define SUN6I_BURST_CTL_CNT_REG		0x38
8662306a36Sopenharmony_ci#define SUN6I_BURST_CTL_CNT_STC_MASK		GENMASK(23, 0)
8762306a36Sopenharmony_ci#define SUN6I_BURST_CTL_CNT_DRM			BIT(28)
8862306a36Sopenharmony_ci#define SUN6I_BURST_CTL_CNT_QUAD_EN		BIT(29)
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define SUN6I_TXDATA_REG		0x200
9162306a36Sopenharmony_ci#define SUN6I_RXDATA_REG		0x300
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistruct sun6i_spi_cfg {
9462306a36Sopenharmony_ci	unsigned long		fifo_depth;
9562306a36Sopenharmony_ci	bool			has_clk_ctl;
9662306a36Sopenharmony_ci	u32			mode_bits;
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistruct sun6i_spi {
10062306a36Sopenharmony_ci	struct spi_master	*master;
10162306a36Sopenharmony_ci	void __iomem		*base_addr;
10262306a36Sopenharmony_ci	dma_addr_t		dma_addr_rx;
10362306a36Sopenharmony_ci	dma_addr_t		dma_addr_tx;
10462306a36Sopenharmony_ci	struct clk		*hclk;
10562306a36Sopenharmony_ci	struct clk		*mclk;
10662306a36Sopenharmony_ci	struct reset_control	*rstc;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	struct completion	done;
10962306a36Sopenharmony_ci	struct completion	dma_rx_done;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	const u8		*tx_buf;
11262306a36Sopenharmony_ci	u8			*rx_buf;
11362306a36Sopenharmony_ci	int			len;
11462306a36Sopenharmony_ci	const struct sun6i_spi_cfg *cfg;
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	return readl(sspi->base_addr + reg);
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic inline void sun6i_spi_write(struct sun6i_spi *sspi, u32 reg, u32 value)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	writel(value, sspi->base_addr + reg);
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic inline u32 sun6i_spi_get_rx_fifo_count(struct sun6i_spi *sspi)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	return FIELD_GET(SUN6I_FIFO_STA_RF_CNT_MASK, reg);
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic inline u32 sun6i_spi_get_tx_fifo_count(struct sun6i_spi *sspi)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	return FIELD_GET(SUN6I_FIFO_STA_TF_CNT_MASK, reg);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic inline void sun6i_spi_disable_interrupt(struct sun6i_spi *sspi, u32 mask)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	u32 reg = sun6i_spi_read(sspi, SUN6I_INT_CTL_REG);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	reg &= ~mask;
14662306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg);
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	u32 len;
15262306a36Sopenharmony_ci	u8 byte;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	/* See how much data is available */
15562306a36Sopenharmony_ci	len = sun6i_spi_get_rx_fifo_count(sspi);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	while (len--) {
15862306a36Sopenharmony_ci		byte = readb(sspi->base_addr + SUN6I_RXDATA_REG);
15962306a36Sopenharmony_ci		if (sspi->rx_buf)
16062306a36Sopenharmony_ci			*sspi->rx_buf++ = byte;
16162306a36Sopenharmony_ci	}
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	u32 cnt;
16762306a36Sopenharmony_ci	int len;
16862306a36Sopenharmony_ci	u8 byte;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	/* See how much data we can fit */
17162306a36Sopenharmony_ci	cnt = sspi->cfg->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	len = min((int)cnt, sspi->len);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	while (len--) {
17662306a36Sopenharmony_ci		byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
17762306a36Sopenharmony_ci		writeb(byte, sspi->base_addr + SUN6I_TXDATA_REG);
17862306a36Sopenharmony_ci		sspi->len--;
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
18562306a36Sopenharmony_ci	u32 reg;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
18862306a36Sopenharmony_ci	reg &= ~SUN6I_TFR_CTL_CS_MASK;
18962306a36Sopenharmony_ci	reg |= SUN6I_TFR_CTL_CS(spi_get_chipselect(spi, 0));
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	if (enable)
19262306a36Sopenharmony_ci		reg |= SUN6I_TFR_CTL_CS_LEVEL;
19362306a36Sopenharmony_ci	else
19462306a36Sopenharmony_ci		reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cistatic size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
20062306a36Sopenharmony_ci{
20162306a36Sopenharmony_ci	return SUN6I_MAX_XFER_SIZE - 1;
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic void sun6i_spi_dma_rx_cb(void *param)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	struct sun6i_spi *sspi = param;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	complete(&sspi->dma_rx_done);
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistatic int sun6i_spi_prepare_dma(struct sun6i_spi *sspi,
21262306a36Sopenharmony_ci				 struct spi_transfer *tfr)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	struct dma_async_tx_descriptor *rxdesc, *txdesc;
21562306a36Sopenharmony_ci	struct spi_master *master = sspi->master;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	rxdesc = NULL;
21862306a36Sopenharmony_ci	if (tfr->rx_buf) {
21962306a36Sopenharmony_ci		struct dma_slave_config rxconf = {
22062306a36Sopenharmony_ci			.direction = DMA_DEV_TO_MEM,
22162306a36Sopenharmony_ci			.src_addr = sspi->dma_addr_rx,
22262306a36Sopenharmony_ci			.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
22362306a36Sopenharmony_ci			.src_maxburst = 8,
22462306a36Sopenharmony_ci		};
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci		dmaengine_slave_config(master->dma_rx, &rxconf);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci		rxdesc = dmaengine_prep_slave_sg(master->dma_rx,
22962306a36Sopenharmony_ci						 tfr->rx_sg.sgl,
23062306a36Sopenharmony_ci						 tfr->rx_sg.nents,
23162306a36Sopenharmony_ci						 DMA_DEV_TO_MEM,
23262306a36Sopenharmony_ci						 DMA_PREP_INTERRUPT);
23362306a36Sopenharmony_ci		if (!rxdesc)
23462306a36Sopenharmony_ci			return -EINVAL;
23562306a36Sopenharmony_ci		rxdesc->callback_param = sspi;
23662306a36Sopenharmony_ci		rxdesc->callback = sun6i_spi_dma_rx_cb;
23762306a36Sopenharmony_ci	}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	txdesc = NULL;
24062306a36Sopenharmony_ci	if (tfr->tx_buf) {
24162306a36Sopenharmony_ci		struct dma_slave_config txconf = {
24262306a36Sopenharmony_ci			.direction = DMA_MEM_TO_DEV,
24362306a36Sopenharmony_ci			.dst_addr = sspi->dma_addr_tx,
24462306a36Sopenharmony_ci			.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
24562306a36Sopenharmony_ci			.dst_maxburst = 8,
24662306a36Sopenharmony_ci		};
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci		dmaengine_slave_config(master->dma_tx, &txconf);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci		txdesc = dmaengine_prep_slave_sg(master->dma_tx,
25162306a36Sopenharmony_ci						 tfr->tx_sg.sgl,
25262306a36Sopenharmony_ci						 tfr->tx_sg.nents,
25362306a36Sopenharmony_ci						 DMA_MEM_TO_DEV,
25462306a36Sopenharmony_ci						 DMA_PREP_INTERRUPT);
25562306a36Sopenharmony_ci		if (!txdesc) {
25662306a36Sopenharmony_ci			if (rxdesc)
25762306a36Sopenharmony_ci				dmaengine_terminate_sync(master->dma_rx);
25862306a36Sopenharmony_ci			return -EINVAL;
25962306a36Sopenharmony_ci		}
26062306a36Sopenharmony_ci	}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	if (tfr->rx_buf) {
26362306a36Sopenharmony_ci		dmaengine_submit(rxdesc);
26462306a36Sopenharmony_ci		dma_async_issue_pending(master->dma_rx);
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	if (tfr->tx_buf) {
26862306a36Sopenharmony_ci		dmaengine_submit(txdesc);
26962306a36Sopenharmony_ci		dma_async_issue_pending(master->dma_tx);
27062306a36Sopenharmony_ci	}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	return 0;
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic int sun6i_spi_transfer_one(struct spi_master *master,
27662306a36Sopenharmony_ci				  struct spi_device *spi,
27762306a36Sopenharmony_ci				  struct spi_transfer *tfr)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	struct sun6i_spi *sspi = spi_master_get_devdata(master);
28062306a36Sopenharmony_ci	unsigned int div, div_cdr1, div_cdr2, timeout;
28162306a36Sopenharmony_ci	unsigned int start, end, tx_time;
28262306a36Sopenharmony_ci	unsigned int trig_level;
28362306a36Sopenharmony_ci	unsigned int tx_len = 0, rx_len = 0, nbits = 0;
28462306a36Sopenharmony_ci	bool use_dma;
28562306a36Sopenharmony_ci	int ret = 0;
28662306a36Sopenharmony_ci	u32 reg;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	if (tfr->len > SUN6I_MAX_XFER_SIZE)
28962306a36Sopenharmony_ci		return -EINVAL;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	reinit_completion(&sspi->done);
29262306a36Sopenharmony_ci	reinit_completion(&sspi->dma_rx_done);
29362306a36Sopenharmony_ci	sspi->tx_buf = tfr->tx_buf;
29462306a36Sopenharmony_ci	sspi->rx_buf = tfr->rx_buf;
29562306a36Sopenharmony_ci	sspi->len = tfr->len;
29662306a36Sopenharmony_ci	use_dma = master->can_dma ? master->can_dma(master, spi, tfr) : false;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	/* Clear pending interrupts */
29962306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	/* Reset FIFO */
30262306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
30362306a36Sopenharmony_ci			SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	reg = 0;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	if (!use_dma) {
30862306a36Sopenharmony_ci		/*
30962306a36Sopenharmony_ci		 * Setup FIFO interrupt trigger level
31062306a36Sopenharmony_ci		 * Here we choose 3/4 of the full fifo depth, as it's
31162306a36Sopenharmony_ci		 * the hardcoded value used in old generation of Allwinner
31262306a36Sopenharmony_ci		 * SPI controller. (See spi-sun4i.c)
31362306a36Sopenharmony_ci		 */
31462306a36Sopenharmony_ci		trig_level = sspi->cfg->fifo_depth / 4 * 3;
31562306a36Sopenharmony_ci	} else {
31662306a36Sopenharmony_ci		/*
31762306a36Sopenharmony_ci		 * Setup FIFO DMA request trigger level
31862306a36Sopenharmony_ci		 * We choose 1/2 of the full fifo depth, that value will
31962306a36Sopenharmony_ci		 * be used as DMA burst length.
32062306a36Sopenharmony_ci		 */
32162306a36Sopenharmony_ci		trig_level = sspi->cfg->fifo_depth / 2;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci		if (tfr->tx_buf)
32462306a36Sopenharmony_ci			reg |= SUN6I_FIFO_CTL_TF_DRQ_EN;
32562306a36Sopenharmony_ci		if (tfr->rx_buf)
32662306a36Sopenharmony_ci			reg |= SUN6I_FIFO_CTL_RF_DRQ_EN;
32762306a36Sopenharmony_ci	}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	reg |= (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) |
33062306a36Sopenharmony_ci	       (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS);
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG, reg);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	/*
33562306a36Sopenharmony_ci	 * Setup the transfer control register: Chip Select,
33662306a36Sopenharmony_ci	 * polarities, etc.
33762306a36Sopenharmony_ci	 */
33862306a36Sopenharmony_ci	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	if (spi->mode & SPI_CPOL)
34162306a36Sopenharmony_ci		reg |= SUN6I_TFR_CTL_CPOL;
34262306a36Sopenharmony_ci	else
34362306a36Sopenharmony_ci		reg &= ~SUN6I_TFR_CTL_CPOL;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	if (spi->mode & SPI_CPHA)
34662306a36Sopenharmony_ci		reg |= SUN6I_TFR_CTL_CPHA;
34762306a36Sopenharmony_ci	else
34862306a36Sopenharmony_ci		reg &= ~SUN6I_TFR_CTL_CPHA;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	if (spi->mode & SPI_LSB_FIRST)
35162306a36Sopenharmony_ci		reg |= SUN6I_TFR_CTL_FBS;
35262306a36Sopenharmony_ci	else
35362306a36Sopenharmony_ci		reg &= ~SUN6I_TFR_CTL_FBS;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	/*
35662306a36Sopenharmony_ci	 * If it's a TX only transfer, we don't want to fill the RX
35762306a36Sopenharmony_ci	 * FIFO with bogus data
35862306a36Sopenharmony_ci	 */
35962306a36Sopenharmony_ci	if (sspi->rx_buf) {
36062306a36Sopenharmony_ci		reg &= ~SUN6I_TFR_CTL_DHB;
36162306a36Sopenharmony_ci		rx_len = tfr->len;
36262306a36Sopenharmony_ci	} else {
36362306a36Sopenharmony_ci		reg |= SUN6I_TFR_CTL_DHB;
36462306a36Sopenharmony_ci	}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	/* We want to control the chip select manually */
36762306a36Sopenharmony_ci	reg |= SUN6I_TFR_CTL_CS_MANUAL;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	if (sspi->cfg->has_clk_ctl) {
37262306a36Sopenharmony_ci		unsigned int mclk_rate = clk_get_rate(sspi->mclk);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci		/* Ensure that we have a parent clock fast enough */
37562306a36Sopenharmony_ci		if (mclk_rate < (2 * tfr->speed_hz)) {
37662306a36Sopenharmony_ci			clk_set_rate(sspi->mclk, 2 * tfr->speed_hz);
37762306a36Sopenharmony_ci			mclk_rate = clk_get_rate(sspi->mclk);
37862306a36Sopenharmony_ci		}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci		/*
38162306a36Sopenharmony_ci		 * Setup clock divider.
38262306a36Sopenharmony_ci		 *
38362306a36Sopenharmony_ci		 * We have two choices there. Either we can use the clock
38462306a36Sopenharmony_ci		 * divide rate 1, which is calculated thanks to this formula:
38562306a36Sopenharmony_ci		 * SPI_CLK = MOD_CLK / (2 ^ cdr)
38662306a36Sopenharmony_ci		 * Or we can use CDR2, which is calculated with the formula:
38762306a36Sopenharmony_ci		 * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
38862306a36Sopenharmony_ci		 * Wether we use the former or the latter is set through the
38962306a36Sopenharmony_ci		 * DRS bit.
39062306a36Sopenharmony_ci		 *
39162306a36Sopenharmony_ci		 * First try CDR2, and if we can't reach the expected
39262306a36Sopenharmony_ci		 * frequency, fall back to CDR1.
39362306a36Sopenharmony_ci		 */
39462306a36Sopenharmony_ci		div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz);
39562306a36Sopenharmony_ci		div_cdr2 = DIV_ROUND_UP(div_cdr1, 2);
39662306a36Sopenharmony_ci		if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
39762306a36Sopenharmony_ci			reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS;
39862306a36Sopenharmony_ci			tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2);
39962306a36Sopenharmony_ci		} else {
40062306a36Sopenharmony_ci			div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1));
40162306a36Sopenharmony_ci			reg = SUN6I_CLK_CTL_CDR1(div);
40262306a36Sopenharmony_ci			tfr->effective_speed_hz = mclk_rate / (1 << div);
40362306a36Sopenharmony_ci		}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci		sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
40662306a36Sopenharmony_ci	} else {
40762306a36Sopenharmony_ci		clk_set_rate(sspi->mclk, tfr->speed_hz);
40862306a36Sopenharmony_ci		tfr->effective_speed_hz = clk_get_rate(sspi->mclk);
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci		/*
41162306a36Sopenharmony_ci		 * Configure work mode.
41262306a36Sopenharmony_ci		 *
41362306a36Sopenharmony_ci		 * There are three work modes depending on the controller clock
41462306a36Sopenharmony_ci		 * frequency:
41562306a36Sopenharmony_ci		 * - normal sample mode           : CLK <= 24MHz SDM=1 SDC=0
41662306a36Sopenharmony_ci		 * - delay half-cycle sample mode : CLK <= 40MHz SDM=0 SDC=0
41762306a36Sopenharmony_ci		 * - delay one-cycle sample mode  : CLK >= 80MHz SDM=0 SDC=1
41862306a36Sopenharmony_ci		 */
41962306a36Sopenharmony_ci		reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
42062306a36Sopenharmony_ci		reg &= ~(SUN6I_TFR_CTL_SDM | SUN6I_TFR_CTL_SDC);
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci		if (tfr->effective_speed_hz <= 24000000)
42362306a36Sopenharmony_ci			reg |= SUN6I_TFR_CTL_SDM;
42462306a36Sopenharmony_ci		else if (tfr->effective_speed_hz >= 80000000)
42562306a36Sopenharmony_ci			reg |= SUN6I_TFR_CTL_SDC;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci		sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
42862306a36Sopenharmony_ci	}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	/* Finally enable the bus - doing so before might raise SCK to HIGH */
43162306a36Sopenharmony_ci	reg = sun6i_spi_read(sspi, SUN6I_GBL_CTL_REG);
43262306a36Sopenharmony_ci	reg |= SUN6I_GBL_CTL_BUS_ENABLE;
43362306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	/* Setup the transfer now... */
43662306a36Sopenharmony_ci	if (sspi->tx_buf) {
43762306a36Sopenharmony_ci		tx_len = tfr->len;
43862306a36Sopenharmony_ci		nbits = tfr->tx_nbits;
43962306a36Sopenharmony_ci	} else if (tfr->rx_buf) {
44062306a36Sopenharmony_ci		nbits = tfr->rx_nbits;
44162306a36Sopenharmony_ci	}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	switch (nbits) {
44462306a36Sopenharmony_ci	case SPI_NBITS_DUAL:
44562306a36Sopenharmony_ci		reg = SUN6I_BURST_CTL_CNT_DRM;
44662306a36Sopenharmony_ci		break;
44762306a36Sopenharmony_ci	case SPI_NBITS_QUAD:
44862306a36Sopenharmony_ci		reg = SUN6I_BURST_CTL_CNT_QUAD_EN;
44962306a36Sopenharmony_ci		break;
45062306a36Sopenharmony_ci	case SPI_NBITS_SINGLE:
45162306a36Sopenharmony_ci	default:
45262306a36Sopenharmony_ci		reg = FIELD_PREP(SUN6I_BURST_CTL_CNT_STC_MASK, tx_len);
45362306a36Sopenharmony_ci	}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	/* Setup the counters */
45662306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, reg);
45762306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, tfr->len);
45862306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	if (!use_dma) {
46162306a36Sopenharmony_ci		/* Fill the TX FIFO */
46262306a36Sopenharmony_ci		sun6i_spi_fill_fifo(sspi);
46362306a36Sopenharmony_ci	} else {
46462306a36Sopenharmony_ci		ret = sun6i_spi_prepare_dma(sspi, tfr);
46562306a36Sopenharmony_ci		if (ret) {
46662306a36Sopenharmony_ci			dev_warn(&master->dev,
46762306a36Sopenharmony_ci				 "%s: prepare DMA failed, ret=%d",
46862306a36Sopenharmony_ci				 dev_name(&spi->dev), ret);
46962306a36Sopenharmony_ci			return ret;
47062306a36Sopenharmony_ci		}
47162306a36Sopenharmony_ci	}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	/* Enable the interrupts */
47462306a36Sopenharmony_ci	reg = SUN6I_INT_CTL_TC;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	if (!use_dma) {
47762306a36Sopenharmony_ci		if (rx_len > sspi->cfg->fifo_depth)
47862306a36Sopenharmony_ci			reg |= SUN6I_INT_CTL_RF_RDY;
47962306a36Sopenharmony_ci		if (tx_len > sspi->cfg->fifo_depth)
48062306a36Sopenharmony_ci			reg |= SUN6I_INT_CTL_TF_ERQ;
48162306a36Sopenharmony_ci	}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg);
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	/* Start the transfer */
48662306a36Sopenharmony_ci	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
48762306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	tx_time = spi_controller_xfer_timeout(master, tfr);
49062306a36Sopenharmony_ci	start = jiffies;
49162306a36Sopenharmony_ci	timeout = wait_for_completion_timeout(&sspi->done,
49262306a36Sopenharmony_ci					      msecs_to_jiffies(tx_time));
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	if (!use_dma) {
49562306a36Sopenharmony_ci		sun6i_spi_drain_fifo(sspi);
49662306a36Sopenharmony_ci	} else {
49762306a36Sopenharmony_ci		if (timeout && rx_len) {
49862306a36Sopenharmony_ci			/*
49962306a36Sopenharmony_ci			 * Even though RX on the peripheral side has finished
50062306a36Sopenharmony_ci			 * RX DMA might still be in flight
50162306a36Sopenharmony_ci			 */
50262306a36Sopenharmony_ci			timeout = wait_for_completion_timeout(&sspi->dma_rx_done,
50362306a36Sopenharmony_ci							      timeout);
50462306a36Sopenharmony_ci			if (!timeout)
50562306a36Sopenharmony_ci				dev_warn(&master->dev, "RX DMA timeout\n");
50662306a36Sopenharmony_ci		}
50762306a36Sopenharmony_ci	}
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	end = jiffies;
51062306a36Sopenharmony_ci	if (!timeout) {
51162306a36Sopenharmony_ci		dev_warn(&master->dev,
51262306a36Sopenharmony_ci			 "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
51362306a36Sopenharmony_ci			 dev_name(&spi->dev), tfr->len, tfr->speed_hz,
51462306a36Sopenharmony_ci			 jiffies_to_msecs(end - start), tx_time);
51562306a36Sopenharmony_ci		ret = -ETIMEDOUT;
51662306a36Sopenharmony_ci	}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	if (ret && use_dma) {
52162306a36Sopenharmony_ci		dmaengine_terminate_sync(master->dma_rx);
52262306a36Sopenharmony_ci		dmaengine_terminate_sync(master->dma_tx);
52362306a36Sopenharmony_ci	}
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	return ret;
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
52962306a36Sopenharmony_ci{
53062306a36Sopenharmony_ci	struct sun6i_spi *sspi = dev_id;
53162306a36Sopenharmony_ci	u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	/* Transfer complete */
53462306a36Sopenharmony_ci	if (status & SUN6I_INT_CTL_TC) {
53562306a36Sopenharmony_ci		sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
53662306a36Sopenharmony_ci		complete(&sspi->done);
53762306a36Sopenharmony_ci		return IRQ_HANDLED;
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	/* Receive FIFO 3/4 full */
54162306a36Sopenharmony_ci	if (status & SUN6I_INT_CTL_RF_RDY) {
54262306a36Sopenharmony_ci		sun6i_spi_drain_fifo(sspi);
54362306a36Sopenharmony_ci		/* Only clear the interrupt _after_ draining the FIFO */
54462306a36Sopenharmony_ci		sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_RF_RDY);
54562306a36Sopenharmony_ci		return IRQ_HANDLED;
54662306a36Sopenharmony_ci	}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	/* Transmit FIFO 3/4 empty */
54962306a36Sopenharmony_ci	if (status & SUN6I_INT_CTL_TF_ERQ) {
55062306a36Sopenharmony_ci		sun6i_spi_fill_fifo(sspi);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci		if (!sspi->len)
55362306a36Sopenharmony_ci			/* nothing left to transmit */
55462306a36Sopenharmony_ci			sun6i_spi_disable_interrupt(sspi, SUN6I_INT_CTL_TF_ERQ);
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci		/* Only clear the interrupt _after_ re-seeding the FIFO */
55762306a36Sopenharmony_ci		sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TF_ERQ);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci		return IRQ_HANDLED;
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	return IRQ_NONE;
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_cistatic int sun6i_spi_runtime_resume(struct device *dev)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
56862306a36Sopenharmony_ci	struct sun6i_spi *sspi = spi_master_get_devdata(master);
56962306a36Sopenharmony_ci	int ret;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	ret = clk_prepare_enable(sspi->hclk);
57262306a36Sopenharmony_ci	if (ret) {
57362306a36Sopenharmony_ci		dev_err(dev, "Couldn't enable AHB clock\n");
57462306a36Sopenharmony_ci		goto out;
57562306a36Sopenharmony_ci	}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	ret = clk_prepare_enable(sspi->mclk);
57862306a36Sopenharmony_ci	if (ret) {
57962306a36Sopenharmony_ci		dev_err(dev, "Couldn't enable module clock\n");
58062306a36Sopenharmony_ci		goto err;
58162306a36Sopenharmony_ci	}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	ret = reset_control_deassert(sspi->rstc);
58462306a36Sopenharmony_ci	if (ret) {
58562306a36Sopenharmony_ci		dev_err(dev, "Couldn't deassert the device from reset\n");
58662306a36Sopenharmony_ci		goto err2;
58762306a36Sopenharmony_ci	}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG,
59062306a36Sopenharmony_ci			SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	return 0;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_cierr2:
59562306a36Sopenharmony_ci	clk_disable_unprepare(sspi->mclk);
59662306a36Sopenharmony_cierr:
59762306a36Sopenharmony_ci	clk_disable_unprepare(sspi->hclk);
59862306a36Sopenharmony_ciout:
59962306a36Sopenharmony_ci	return ret;
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_cistatic int sun6i_spi_runtime_suspend(struct device *dev)
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
60562306a36Sopenharmony_ci	struct sun6i_spi *sspi = spi_master_get_devdata(master);
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	reset_control_assert(sspi->rstc);
60862306a36Sopenharmony_ci	clk_disable_unprepare(sspi->mclk);
60962306a36Sopenharmony_ci	clk_disable_unprepare(sspi->hclk);
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	return 0;
61262306a36Sopenharmony_ci}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_cistatic bool sun6i_spi_can_dma(struct spi_master *master,
61562306a36Sopenharmony_ci			      struct spi_device *spi,
61662306a36Sopenharmony_ci			      struct spi_transfer *xfer)
61762306a36Sopenharmony_ci{
61862306a36Sopenharmony_ci	struct sun6i_spi *sspi = spi_master_get_devdata(master);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	/*
62162306a36Sopenharmony_ci	 * If the number of spi words to transfer is less or equal than
62262306a36Sopenharmony_ci	 * the fifo length we can just fill the fifo and wait for a single
62362306a36Sopenharmony_ci	 * irq, so don't bother setting up dma
62462306a36Sopenharmony_ci	 */
62562306a36Sopenharmony_ci	return xfer->len > sspi->cfg->fifo_depth;
62662306a36Sopenharmony_ci}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_cistatic int sun6i_spi_probe(struct platform_device *pdev)
62962306a36Sopenharmony_ci{
63062306a36Sopenharmony_ci	struct spi_master *master;
63162306a36Sopenharmony_ci	struct sun6i_spi *sspi;
63262306a36Sopenharmony_ci	struct resource *mem;
63362306a36Sopenharmony_ci	int ret = 0, irq;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
63662306a36Sopenharmony_ci	if (!master) {
63762306a36Sopenharmony_ci		dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
63862306a36Sopenharmony_ci		return -ENOMEM;
63962306a36Sopenharmony_ci	}
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	platform_set_drvdata(pdev, master);
64262306a36Sopenharmony_ci	sspi = spi_master_get_devdata(master);
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	sspi->base_addr = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
64562306a36Sopenharmony_ci	if (IS_ERR(sspi->base_addr)) {
64662306a36Sopenharmony_ci		ret = PTR_ERR(sspi->base_addr);
64762306a36Sopenharmony_ci		goto err_free_master;
64862306a36Sopenharmony_ci	}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
65162306a36Sopenharmony_ci	if (irq < 0) {
65262306a36Sopenharmony_ci		ret = -ENXIO;
65362306a36Sopenharmony_ci		goto err_free_master;
65462306a36Sopenharmony_ci	}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler,
65762306a36Sopenharmony_ci			       0, "sun6i-spi", sspi);
65862306a36Sopenharmony_ci	if (ret) {
65962306a36Sopenharmony_ci		dev_err(&pdev->dev, "Cannot request IRQ\n");
66062306a36Sopenharmony_ci		goto err_free_master;
66162306a36Sopenharmony_ci	}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	sspi->master = master;
66462306a36Sopenharmony_ci	sspi->cfg = of_device_get_match_data(&pdev->dev);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	master->max_speed_hz = 100 * 1000 * 1000;
66762306a36Sopenharmony_ci	master->min_speed_hz = 3 * 1000;
66862306a36Sopenharmony_ci	master->use_gpio_descriptors = true;
66962306a36Sopenharmony_ci	master->set_cs = sun6i_spi_set_cs;
67062306a36Sopenharmony_ci	master->transfer_one = sun6i_spi_transfer_one;
67162306a36Sopenharmony_ci	master->num_chipselect = 4;
67262306a36Sopenharmony_ci	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
67362306a36Sopenharmony_ci			    sspi->cfg->mode_bits;
67462306a36Sopenharmony_ci	master->bits_per_word_mask = SPI_BPW_MASK(8);
67562306a36Sopenharmony_ci	master->dev.of_node = pdev->dev.of_node;
67662306a36Sopenharmony_ci	master->auto_runtime_pm = true;
67762306a36Sopenharmony_ci	master->max_transfer_size = sun6i_spi_max_transfer_size;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
68062306a36Sopenharmony_ci	if (IS_ERR(sspi->hclk)) {
68162306a36Sopenharmony_ci		dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
68262306a36Sopenharmony_ci		ret = PTR_ERR(sspi->hclk);
68362306a36Sopenharmony_ci		goto err_free_master;
68462306a36Sopenharmony_ci	}
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	sspi->mclk = devm_clk_get(&pdev->dev, "mod");
68762306a36Sopenharmony_ci	if (IS_ERR(sspi->mclk)) {
68862306a36Sopenharmony_ci		dev_err(&pdev->dev, "Unable to acquire module clock\n");
68962306a36Sopenharmony_ci		ret = PTR_ERR(sspi->mclk);
69062306a36Sopenharmony_ci		goto err_free_master;
69162306a36Sopenharmony_ci	}
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	init_completion(&sspi->done);
69462306a36Sopenharmony_ci	init_completion(&sspi->dma_rx_done);
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	sspi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
69762306a36Sopenharmony_ci	if (IS_ERR(sspi->rstc)) {
69862306a36Sopenharmony_ci		dev_err(&pdev->dev, "Couldn't get reset controller\n");
69962306a36Sopenharmony_ci		ret = PTR_ERR(sspi->rstc);
70062306a36Sopenharmony_ci		goto err_free_master;
70162306a36Sopenharmony_ci	}
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	master->dma_tx = dma_request_chan(&pdev->dev, "tx");
70462306a36Sopenharmony_ci	if (IS_ERR(master->dma_tx)) {
70562306a36Sopenharmony_ci		/* Check tx to see if we need defer probing driver */
70662306a36Sopenharmony_ci		if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) {
70762306a36Sopenharmony_ci			ret = -EPROBE_DEFER;
70862306a36Sopenharmony_ci			goto err_free_master;
70962306a36Sopenharmony_ci		}
71062306a36Sopenharmony_ci		dev_warn(&pdev->dev, "Failed to request TX DMA channel\n");
71162306a36Sopenharmony_ci		master->dma_tx = NULL;
71262306a36Sopenharmony_ci	}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	master->dma_rx = dma_request_chan(&pdev->dev, "rx");
71562306a36Sopenharmony_ci	if (IS_ERR(master->dma_rx)) {
71662306a36Sopenharmony_ci		if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) {
71762306a36Sopenharmony_ci			ret = -EPROBE_DEFER;
71862306a36Sopenharmony_ci			goto err_free_dma_tx;
71962306a36Sopenharmony_ci		}
72062306a36Sopenharmony_ci		dev_warn(&pdev->dev, "Failed to request RX DMA channel\n");
72162306a36Sopenharmony_ci		master->dma_rx = NULL;
72262306a36Sopenharmony_ci	}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	if (master->dma_tx && master->dma_rx) {
72562306a36Sopenharmony_ci		sspi->dma_addr_tx = mem->start + SUN6I_TXDATA_REG;
72662306a36Sopenharmony_ci		sspi->dma_addr_rx = mem->start + SUN6I_RXDATA_REG;
72762306a36Sopenharmony_ci		master->can_dma = sun6i_spi_can_dma;
72862306a36Sopenharmony_ci	}
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	/*
73162306a36Sopenharmony_ci	 * This wake-up/shutdown pattern is to be able to have the
73262306a36Sopenharmony_ci	 * device woken up, even if runtime_pm is disabled
73362306a36Sopenharmony_ci	 */
73462306a36Sopenharmony_ci	ret = sun6i_spi_runtime_resume(&pdev->dev);
73562306a36Sopenharmony_ci	if (ret) {
73662306a36Sopenharmony_ci		dev_err(&pdev->dev, "Couldn't resume the device\n");
73762306a36Sopenharmony_ci		goto err_free_dma_rx;
73862306a36Sopenharmony_ci	}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(&pdev->dev, SUN6I_AUTOSUSPEND_TIMEOUT);
74162306a36Sopenharmony_ci	pm_runtime_use_autosuspend(&pdev->dev);
74262306a36Sopenharmony_ci	pm_runtime_set_active(&pdev->dev);
74362306a36Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	ret = devm_spi_register_master(&pdev->dev, master);
74662306a36Sopenharmony_ci	if (ret) {
74762306a36Sopenharmony_ci		dev_err(&pdev->dev, "cannot register SPI master\n");
74862306a36Sopenharmony_ci		goto err_pm_disable;
74962306a36Sopenharmony_ci	}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	return 0;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_cierr_pm_disable:
75462306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
75562306a36Sopenharmony_ci	sun6i_spi_runtime_suspend(&pdev->dev);
75662306a36Sopenharmony_cierr_free_dma_rx:
75762306a36Sopenharmony_ci	if (master->dma_rx)
75862306a36Sopenharmony_ci		dma_release_channel(master->dma_rx);
75962306a36Sopenharmony_cierr_free_dma_tx:
76062306a36Sopenharmony_ci	if (master->dma_tx)
76162306a36Sopenharmony_ci		dma_release_channel(master->dma_tx);
76262306a36Sopenharmony_cierr_free_master:
76362306a36Sopenharmony_ci	spi_master_put(master);
76462306a36Sopenharmony_ci	return ret;
76562306a36Sopenharmony_ci}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_cistatic void sun6i_spi_remove(struct platform_device *pdev)
76862306a36Sopenharmony_ci{
76962306a36Sopenharmony_ci	struct spi_master *master = platform_get_drvdata(pdev);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	pm_runtime_force_suspend(&pdev->dev);
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	if (master->dma_tx)
77462306a36Sopenharmony_ci		dma_release_channel(master->dma_tx);
77562306a36Sopenharmony_ci	if (master->dma_rx)
77662306a36Sopenharmony_ci		dma_release_channel(master->dma_rx);
77762306a36Sopenharmony_ci}
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_cistatic const struct sun6i_spi_cfg sun6i_a31_spi_cfg = {
78062306a36Sopenharmony_ci	.fifo_depth	= SUN6I_FIFO_DEPTH,
78162306a36Sopenharmony_ci	.has_clk_ctl	= true,
78262306a36Sopenharmony_ci};
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_cistatic const struct sun6i_spi_cfg sun8i_h3_spi_cfg = {
78562306a36Sopenharmony_ci	.fifo_depth	= SUN8I_FIFO_DEPTH,
78662306a36Sopenharmony_ci	.has_clk_ctl	= true,
78762306a36Sopenharmony_ci};
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_cistatic const struct sun6i_spi_cfg sun50i_r329_spi_cfg = {
79062306a36Sopenharmony_ci	.fifo_depth	= SUN8I_FIFO_DEPTH,
79162306a36Sopenharmony_ci	.mode_bits	= SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD,
79262306a36Sopenharmony_ci};
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_cistatic const struct of_device_id sun6i_spi_match[] = {
79562306a36Sopenharmony_ci	{ .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_cfg },
79662306a36Sopenharmony_ci	{ .compatible = "allwinner,sun8i-h3-spi",  .data = &sun8i_h3_spi_cfg },
79762306a36Sopenharmony_ci	{
79862306a36Sopenharmony_ci		.compatible = "allwinner,sun50i-r329-spi",
79962306a36Sopenharmony_ci		.data = &sun50i_r329_spi_cfg
80062306a36Sopenharmony_ci	},
80162306a36Sopenharmony_ci	{}
80262306a36Sopenharmony_ci};
80362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, sun6i_spi_match);
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_cistatic const struct dev_pm_ops sun6i_spi_pm_ops = {
80662306a36Sopenharmony_ci	.runtime_resume		= sun6i_spi_runtime_resume,
80762306a36Sopenharmony_ci	.runtime_suspend	= sun6i_spi_runtime_suspend,
80862306a36Sopenharmony_ci};
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_cistatic struct platform_driver sun6i_spi_driver = {
81162306a36Sopenharmony_ci	.probe	= sun6i_spi_probe,
81262306a36Sopenharmony_ci	.remove_new = sun6i_spi_remove,
81362306a36Sopenharmony_ci	.driver	= {
81462306a36Sopenharmony_ci		.name		= "sun6i-spi",
81562306a36Sopenharmony_ci		.of_match_table	= sun6i_spi_match,
81662306a36Sopenharmony_ci		.pm		= &sun6i_spi_pm_ops,
81762306a36Sopenharmony_ci	},
81862306a36Sopenharmony_ci};
81962306a36Sopenharmony_cimodule_platform_driver(sun6i_spi_driver);
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ciMODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>");
82262306a36Sopenharmony_ciMODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
82362306a36Sopenharmony_ciMODULE_DESCRIPTION("Allwinner A31 SPI controller driver");
82462306a36Sopenharmony_ciMODULE_LICENSE("GPL");
825