xref: /openbmc/linux/drivers/spi/spi-uniphier.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
15ba155a4SKeiji Hayashibara // SPDX-License-Identifier: GPL-2.0
25ba155a4SKeiji Hayashibara // spi-uniphier.c - Socionext UniPhier SPI controller driver
35ba155a4SKeiji Hayashibara // Copyright 2012      Panasonic Corporation
45ba155a4SKeiji Hayashibara // Copyright 2016-2018 Socionext Inc.
55ba155a4SKeiji Hayashibara 
65ba155a4SKeiji Hayashibara #include <linux/kernel.h>
75ba155a4SKeiji Hayashibara #include <linux/bitfield.h>
85ba155a4SKeiji Hayashibara #include <linux/bitops.h>
95ba155a4SKeiji Hayashibara #include <linux/clk.h>
1037ffab81SKeiji Hayashibara #include <linux/delay.h>
1128d1dddcSKunihiko Hayashi #include <linux/dmaengine.h>
125ba155a4SKeiji Hayashibara #include <linux/interrupt.h>
135ba155a4SKeiji Hayashibara #include <linux/io.h>
145ba155a4SKeiji Hayashibara #include <linux/module.h>
155ba155a4SKeiji Hayashibara #include <linux/platform_device.h>
165ba155a4SKeiji Hayashibara #include <linux/spi/spi.h>
175ba155a4SKeiji Hayashibara 
185ba155a4SKeiji Hayashibara #include <asm/unaligned.h>
195ba155a4SKeiji Hayashibara 
205ba155a4SKeiji Hayashibara #define SSI_TIMEOUT_MS		2000
2137ffab81SKeiji Hayashibara #define SSI_POLL_TIMEOUT_US	200
225ba155a4SKeiji Hayashibara #define SSI_MAX_CLK_DIVIDER	254
235ba155a4SKeiji Hayashibara #define SSI_MIN_CLK_DIVIDER	4
245ba155a4SKeiji Hayashibara 
255ba155a4SKeiji Hayashibara struct uniphier_spi_priv {
265ba155a4SKeiji Hayashibara 	void __iomem *base;
2728d1dddcSKunihiko Hayashi 	dma_addr_t base_dma_addr;
285ba155a4SKeiji Hayashibara 	struct clk *clk;
295ba155a4SKeiji Hayashibara 	struct spi_master *master;
305ba155a4SKeiji Hayashibara 	struct completion xfer_done;
315ba155a4SKeiji Hayashibara 
325ba155a4SKeiji Hayashibara 	int error;
335ba155a4SKeiji Hayashibara 	unsigned int tx_bytes;
345ba155a4SKeiji Hayashibara 	unsigned int rx_bytes;
355ba155a4SKeiji Hayashibara 	const u8 *tx_buf;
365ba155a4SKeiji Hayashibara 	u8 *rx_buf;
3728d1dddcSKunihiko Hayashi 	atomic_t dma_busy;
385ba155a4SKeiji Hayashibara 
395ba155a4SKeiji Hayashibara 	bool is_save_param;
405ba155a4SKeiji Hayashibara 	u8 bits_per_word;
415ba155a4SKeiji Hayashibara 	u16 mode;
425ba155a4SKeiji Hayashibara 	u32 speed_hz;
435ba155a4SKeiji Hayashibara };
445ba155a4SKeiji Hayashibara 
455ba155a4SKeiji Hayashibara #define SSI_CTL			0x00
465ba155a4SKeiji Hayashibara #define   SSI_CTL_EN		BIT(0)
475ba155a4SKeiji Hayashibara 
485ba155a4SKeiji Hayashibara #define SSI_CKS			0x04
495ba155a4SKeiji Hayashibara #define   SSI_CKS_CKRAT_MASK	GENMASK(7, 0)
505ba155a4SKeiji Hayashibara #define   SSI_CKS_CKPHS		BIT(14)
515ba155a4SKeiji Hayashibara #define   SSI_CKS_CKINIT	BIT(13)
525ba155a4SKeiji Hayashibara #define   SSI_CKS_CKDLY		BIT(12)
535ba155a4SKeiji Hayashibara 
545ba155a4SKeiji Hayashibara #define SSI_TXWDS		0x08
555ba155a4SKeiji Hayashibara #define   SSI_TXWDS_WDLEN_MASK	GENMASK(13, 8)
565ba155a4SKeiji Hayashibara #define   SSI_TXWDS_TDTF_MASK	GENMASK(7, 6)
575ba155a4SKeiji Hayashibara #define   SSI_TXWDS_DTLEN_MASK	GENMASK(5, 0)
585ba155a4SKeiji Hayashibara 
595ba155a4SKeiji Hayashibara #define SSI_RXWDS		0x0c
605ba155a4SKeiji Hayashibara #define   SSI_RXWDS_DTLEN_MASK	GENMASK(5, 0)
615ba155a4SKeiji Hayashibara 
625ba155a4SKeiji Hayashibara #define SSI_FPS			0x10
635ba155a4SKeiji Hayashibara #define   SSI_FPS_FSPOL		BIT(15)
645ba155a4SKeiji Hayashibara #define   SSI_FPS_FSTRT		BIT(14)
655ba155a4SKeiji Hayashibara 
665ba155a4SKeiji Hayashibara #define SSI_SR			0x14
6728d1dddcSKunihiko Hayashi #define   SSI_SR_BUSY		BIT(7)
685ba155a4SKeiji Hayashibara #define   SSI_SR_RNE		BIT(0)
695ba155a4SKeiji Hayashibara 
705ba155a4SKeiji Hayashibara #define SSI_IE			0x18
7128d1dddcSKunihiko Hayashi #define   SSI_IE_TCIE		BIT(4)
725ba155a4SKeiji Hayashibara #define   SSI_IE_RCIE		BIT(3)
7328d1dddcSKunihiko Hayashi #define   SSI_IE_TXRE		BIT(2)
7428d1dddcSKunihiko Hayashi #define   SSI_IE_RXRE		BIT(1)
755ba155a4SKeiji Hayashibara #define   SSI_IE_RORIE		BIT(0)
7628d1dddcSKunihiko Hayashi #define   SSI_IE_ALL_MASK	GENMASK(4, 0)
775ba155a4SKeiji Hayashibara 
785ba155a4SKeiji Hayashibara #define SSI_IS			0x1c
795ba155a4SKeiji Hayashibara #define   SSI_IS_RXRS		BIT(9)
805ba155a4SKeiji Hayashibara #define   SSI_IS_RCID		BIT(3)
815ba155a4SKeiji Hayashibara #define   SSI_IS_RORID		BIT(0)
825ba155a4SKeiji Hayashibara 
835ba155a4SKeiji Hayashibara #define SSI_IC			0x1c
845ba155a4SKeiji Hayashibara #define   SSI_IC_TCIC		BIT(4)
855ba155a4SKeiji Hayashibara #define   SSI_IC_RCIC		BIT(3)
865ba155a4SKeiji Hayashibara #define   SSI_IC_RORIC		BIT(0)
875ba155a4SKeiji Hayashibara 
885ba155a4SKeiji Hayashibara #define SSI_FC			0x20
895ba155a4SKeiji Hayashibara #define   SSI_FC_TXFFL		BIT(12)
905ba155a4SKeiji Hayashibara #define   SSI_FC_TXFTH_MASK	GENMASK(11, 8)
915ba155a4SKeiji Hayashibara #define   SSI_FC_RXFFL		BIT(4)
925ba155a4SKeiji Hayashibara #define   SSI_FC_RXFTH_MASK	GENMASK(3, 0)
935ba155a4SKeiji Hayashibara 
945ba155a4SKeiji Hayashibara #define SSI_TXDR		0x24
955ba155a4SKeiji Hayashibara #define SSI_RXDR		0x24
965ba155a4SKeiji Hayashibara 
975ba155a4SKeiji Hayashibara #define SSI_FIFO_DEPTH		8U
9828d1dddcSKunihiko Hayashi #define SSI_FIFO_BURST_NUM	1
9928d1dddcSKunihiko Hayashi 
10028d1dddcSKunihiko Hayashi #define SSI_DMA_RX_BUSY		BIT(1)
10128d1dddcSKunihiko Hayashi #define SSI_DMA_TX_BUSY		BIT(0)
1025ba155a4SKeiji Hayashibara 
bytes_per_word(unsigned int bits)1035ba155a4SKeiji Hayashibara static inline unsigned int bytes_per_word(unsigned int bits)
1045ba155a4SKeiji Hayashibara {
1055ba155a4SKeiji Hayashibara 	return bits <= 8 ? 1 : (bits <= 16 ? 2 : 4);
1065ba155a4SKeiji Hayashibara }
1075ba155a4SKeiji Hayashibara 
uniphier_spi_irq_enable(struct uniphier_spi_priv * priv,u32 mask)1089859db51SKunihiko Hayashi static inline void uniphier_spi_irq_enable(struct uniphier_spi_priv *priv,
1099859db51SKunihiko Hayashi 					   u32 mask)
1105ba155a4SKeiji Hayashibara {
1115ba155a4SKeiji Hayashibara 	u32 val;
1125ba155a4SKeiji Hayashibara 
1135ba155a4SKeiji Hayashibara 	val = readl(priv->base + SSI_IE);
1145ba155a4SKeiji Hayashibara 	val |= mask;
1155ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_IE);
1165ba155a4SKeiji Hayashibara }
1175ba155a4SKeiji Hayashibara 
uniphier_spi_irq_disable(struct uniphier_spi_priv * priv,u32 mask)1189859db51SKunihiko Hayashi static inline void uniphier_spi_irq_disable(struct uniphier_spi_priv *priv,
1199859db51SKunihiko Hayashi 					    u32 mask)
1205ba155a4SKeiji Hayashibara {
1215ba155a4SKeiji Hayashibara 	u32 val;
1225ba155a4SKeiji Hayashibara 
1235ba155a4SKeiji Hayashibara 	val = readl(priv->base + SSI_IE);
1245ba155a4SKeiji Hayashibara 	val &= ~mask;
1255ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_IE);
1265ba155a4SKeiji Hayashibara }
1275ba155a4SKeiji Hayashibara 
uniphier_spi_set_mode(struct spi_device * spi)1285ba155a4SKeiji Hayashibara static void uniphier_spi_set_mode(struct spi_device *spi)
1295ba155a4SKeiji Hayashibara {
1305ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
1315ba155a4SKeiji Hayashibara 	u32 val1, val2;
1325ba155a4SKeiji Hayashibara 
1335ba155a4SKeiji Hayashibara 	/*
1345ba155a4SKeiji Hayashibara 	 * clock setting
1355ba155a4SKeiji Hayashibara 	 * CKPHS    capture timing. 0:rising edge, 1:falling edge
1365ba155a4SKeiji Hayashibara 	 * CKINIT   clock initial level. 0:low, 1:high
1375ba155a4SKeiji Hayashibara 	 * CKDLY    clock delay. 0:no delay, 1:delay depending on FSTRT
1385ba155a4SKeiji Hayashibara 	 *          (FSTRT=0: 1 clock, FSTRT=1: 0.5 clock)
1395ba155a4SKeiji Hayashibara 	 *
1405ba155a4SKeiji Hayashibara 	 * frame setting
1415ba155a4SKeiji Hayashibara 	 * FSPOL    frame signal porarity. 0: low, 1: high
1425ba155a4SKeiji Hayashibara 	 * FSTRT    start frame timing
1435ba155a4SKeiji Hayashibara 	 *          0: rising edge of clock, 1: falling edge of clock
1445ba155a4SKeiji Hayashibara 	 */
145038b9de4SAndy Shevchenko 	switch (spi->mode & SPI_MODE_X_MASK) {
1465ba155a4SKeiji Hayashibara 	case SPI_MODE_0:
1475ba155a4SKeiji Hayashibara 		/* CKPHS=1, CKINIT=0, CKDLY=1, FSTRT=0 */
1485ba155a4SKeiji Hayashibara 		val1 = SSI_CKS_CKPHS | SSI_CKS_CKDLY;
1495ba155a4SKeiji Hayashibara 		val2 = 0;
1505ba155a4SKeiji Hayashibara 		break;
1515ba155a4SKeiji Hayashibara 	case SPI_MODE_1:
1525ba155a4SKeiji Hayashibara 		/* CKPHS=0, CKINIT=0, CKDLY=0, FSTRT=1 */
1535ba155a4SKeiji Hayashibara 		val1 = 0;
1545ba155a4SKeiji Hayashibara 		val2 = SSI_FPS_FSTRT;
1555ba155a4SKeiji Hayashibara 		break;
1565ba155a4SKeiji Hayashibara 	case SPI_MODE_2:
1575ba155a4SKeiji Hayashibara 		/* CKPHS=0, CKINIT=1, CKDLY=1, FSTRT=1 */
1585ba155a4SKeiji Hayashibara 		val1 = SSI_CKS_CKINIT | SSI_CKS_CKDLY;
1595ba155a4SKeiji Hayashibara 		val2 = SSI_FPS_FSTRT;
1605ba155a4SKeiji Hayashibara 		break;
1615ba155a4SKeiji Hayashibara 	case SPI_MODE_3:
1625ba155a4SKeiji Hayashibara 		/* CKPHS=1, CKINIT=1, CKDLY=0, FSTRT=0 */
1635ba155a4SKeiji Hayashibara 		val1 = SSI_CKS_CKPHS | SSI_CKS_CKINIT;
1645ba155a4SKeiji Hayashibara 		val2 = 0;
1655ba155a4SKeiji Hayashibara 		break;
1665ba155a4SKeiji Hayashibara 	}
1675ba155a4SKeiji Hayashibara 
1685ba155a4SKeiji Hayashibara 	if (!(spi->mode & SPI_CS_HIGH))
1695ba155a4SKeiji Hayashibara 		val2 |= SSI_FPS_FSPOL;
1705ba155a4SKeiji Hayashibara 
1715ba155a4SKeiji Hayashibara 	writel(val1, priv->base + SSI_CKS);
1725ba155a4SKeiji Hayashibara 	writel(val2, priv->base + SSI_FPS);
1735ba155a4SKeiji Hayashibara 
1745ba155a4SKeiji Hayashibara 	val1 = 0;
1755ba155a4SKeiji Hayashibara 	if (spi->mode & SPI_LSB_FIRST)
1765ba155a4SKeiji Hayashibara 		val1 |= FIELD_PREP(SSI_TXWDS_TDTF_MASK, 1);
1775ba155a4SKeiji Hayashibara 	writel(val1, priv->base + SSI_TXWDS);
1785ba155a4SKeiji Hayashibara 	writel(val1, priv->base + SSI_RXWDS);
1795ba155a4SKeiji Hayashibara }
1805ba155a4SKeiji Hayashibara 
uniphier_spi_set_transfer_size(struct spi_device * spi,int size)1815ba155a4SKeiji Hayashibara static void uniphier_spi_set_transfer_size(struct spi_device *spi, int size)
1825ba155a4SKeiji Hayashibara {
1835ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
1845ba155a4SKeiji Hayashibara 	u32 val;
1855ba155a4SKeiji Hayashibara 
1865ba155a4SKeiji Hayashibara 	val = readl(priv->base + SSI_TXWDS);
1875ba155a4SKeiji Hayashibara 	val &= ~(SSI_TXWDS_WDLEN_MASK | SSI_TXWDS_DTLEN_MASK);
1885ba155a4SKeiji Hayashibara 	val |= FIELD_PREP(SSI_TXWDS_WDLEN_MASK, size);
1895ba155a4SKeiji Hayashibara 	val |= FIELD_PREP(SSI_TXWDS_DTLEN_MASK, size);
1905ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_TXWDS);
1915ba155a4SKeiji Hayashibara 
1925ba155a4SKeiji Hayashibara 	val = readl(priv->base + SSI_RXWDS);
1935ba155a4SKeiji Hayashibara 	val &= ~SSI_RXWDS_DTLEN_MASK;
1945ba155a4SKeiji Hayashibara 	val |= FIELD_PREP(SSI_RXWDS_DTLEN_MASK, size);
1955ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_RXWDS);
1965ba155a4SKeiji Hayashibara }
1975ba155a4SKeiji Hayashibara 
uniphier_spi_set_baudrate(struct spi_device * spi,unsigned int speed)1985ba155a4SKeiji Hayashibara static void uniphier_spi_set_baudrate(struct spi_device *spi,
1995ba155a4SKeiji Hayashibara 				      unsigned int speed)
2005ba155a4SKeiji Hayashibara {
2015ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
2025ba155a4SKeiji Hayashibara 	u32 val, ckdiv;
2035ba155a4SKeiji Hayashibara 
2045ba155a4SKeiji Hayashibara 	/*
2055ba155a4SKeiji Hayashibara 	 * the supported rates are even numbers from 4 to 254. (4,6,8...254)
2065ba155a4SKeiji Hayashibara 	 * round up as we look for equal or less speed
2075ba155a4SKeiji Hayashibara 	 */
2085ba155a4SKeiji Hayashibara 	ckdiv = DIV_ROUND_UP(clk_get_rate(priv->clk), speed);
2095ba155a4SKeiji Hayashibara 	ckdiv = round_up(ckdiv, 2);
2105ba155a4SKeiji Hayashibara 
2115ba155a4SKeiji Hayashibara 	val = readl(priv->base + SSI_CKS);
2125ba155a4SKeiji Hayashibara 	val &= ~SSI_CKS_CKRAT_MASK;
2135ba155a4SKeiji Hayashibara 	val |= ckdiv & SSI_CKS_CKRAT_MASK;
2145ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_CKS);
2155ba155a4SKeiji Hayashibara }
2165ba155a4SKeiji Hayashibara 
uniphier_spi_setup_transfer(struct spi_device * spi,struct spi_transfer * t)2175ba155a4SKeiji Hayashibara static void uniphier_spi_setup_transfer(struct spi_device *spi,
2185ba155a4SKeiji Hayashibara 				       struct spi_transfer *t)
2195ba155a4SKeiji Hayashibara {
2205ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
2215ba155a4SKeiji Hayashibara 	u32 val;
2225ba155a4SKeiji Hayashibara 
2235ba155a4SKeiji Hayashibara 	priv->error = 0;
2245ba155a4SKeiji Hayashibara 	priv->tx_buf = t->tx_buf;
2255ba155a4SKeiji Hayashibara 	priv->rx_buf = t->rx_buf;
2265ba155a4SKeiji Hayashibara 	priv->tx_bytes = priv->rx_bytes = t->len;
2275ba155a4SKeiji Hayashibara 
2285ba155a4SKeiji Hayashibara 	if (!priv->is_save_param || priv->mode != spi->mode) {
2295ba155a4SKeiji Hayashibara 		uniphier_spi_set_mode(spi);
2305ba155a4SKeiji Hayashibara 		priv->mode = spi->mode;
2313c633f9dSKeiji Hayashibara 		priv->is_save_param = false;
2325ba155a4SKeiji Hayashibara 	}
2335ba155a4SKeiji Hayashibara 
2345ba155a4SKeiji Hayashibara 	if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) {
2355ba155a4SKeiji Hayashibara 		uniphier_spi_set_transfer_size(spi, t->bits_per_word);
2365ba155a4SKeiji Hayashibara 		priv->bits_per_word = t->bits_per_word;
2375ba155a4SKeiji Hayashibara 	}
2385ba155a4SKeiji Hayashibara 
2395ba155a4SKeiji Hayashibara 	if (!priv->is_save_param || priv->speed_hz != t->speed_hz) {
2405ba155a4SKeiji Hayashibara 		uniphier_spi_set_baudrate(spi, t->speed_hz);
2415ba155a4SKeiji Hayashibara 		priv->speed_hz = t->speed_hz;
2425ba155a4SKeiji Hayashibara 	}
2435ba155a4SKeiji Hayashibara 
2445ba155a4SKeiji Hayashibara 	priv->is_save_param = true;
2455ba155a4SKeiji Hayashibara 
2465ba155a4SKeiji Hayashibara 	/* reset FIFOs */
2475ba155a4SKeiji Hayashibara 	val = SSI_FC_TXFFL | SSI_FC_RXFFL;
2485ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_FC);
2495ba155a4SKeiji Hayashibara }
2505ba155a4SKeiji Hayashibara 
uniphier_spi_send(struct uniphier_spi_priv * priv)2515ba155a4SKeiji Hayashibara static void uniphier_spi_send(struct uniphier_spi_priv *priv)
2525ba155a4SKeiji Hayashibara {
2535ba155a4SKeiji Hayashibara 	int wsize;
2545ba155a4SKeiji Hayashibara 	u32 val = 0;
2555ba155a4SKeiji Hayashibara 
2565ba155a4SKeiji Hayashibara 	wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes);
2575ba155a4SKeiji Hayashibara 	priv->tx_bytes -= wsize;
2585ba155a4SKeiji Hayashibara 
2595ba155a4SKeiji Hayashibara 	if (priv->tx_buf) {
2605ba155a4SKeiji Hayashibara 		switch (wsize) {
2615ba155a4SKeiji Hayashibara 		case 1:
2625ba155a4SKeiji Hayashibara 			val = *priv->tx_buf;
2635ba155a4SKeiji Hayashibara 			break;
2645ba155a4SKeiji Hayashibara 		case 2:
2655ba155a4SKeiji Hayashibara 			val = get_unaligned_le16(priv->tx_buf);
2665ba155a4SKeiji Hayashibara 			break;
2675ba155a4SKeiji Hayashibara 		case 4:
2685ba155a4SKeiji Hayashibara 			val = get_unaligned_le32(priv->tx_buf);
2695ba155a4SKeiji Hayashibara 			break;
2705ba155a4SKeiji Hayashibara 		}
2715ba155a4SKeiji Hayashibara 
2725ba155a4SKeiji Hayashibara 		priv->tx_buf += wsize;
2735ba155a4SKeiji Hayashibara 	}
2745ba155a4SKeiji Hayashibara 
2755ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_TXDR);
2765ba155a4SKeiji Hayashibara }
2775ba155a4SKeiji Hayashibara 
uniphier_spi_recv(struct uniphier_spi_priv * priv)2785ba155a4SKeiji Hayashibara static void uniphier_spi_recv(struct uniphier_spi_priv *priv)
2795ba155a4SKeiji Hayashibara {
2805ba155a4SKeiji Hayashibara 	int rsize;
2815ba155a4SKeiji Hayashibara 	u32 val;
2825ba155a4SKeiji Hayashibara 
2835ba155a4SKeiji Hayashibara 	rsize = min(bytes_per_word(priv->bits_per_word), priv->rx_bytes);
2845ba155a4SKeiji Hayashibara 	priv->rx_bytes -= rsize;
2855ba155a4SKeiji Hayashibara 
2865ba155a4SKeiji Hayashibara 	val = readl(priv->base + SSI_RXDR);
2875ba155a4SKeiji Hayashibara 
2885ba155a4SKeiji Hayashibara 	if (priv->rx_buf) {
2895ba155a4SKeiji Hayashibara 		switch (rsize) {
2905ba155a4SKeiji Hayashibara 		case 1:
2915ba155a4SKeiji Hayashibara 			*priv->rx_buf = val;
2925ba155a4SKeiji Hayashibara 			break;
2935ba155a4SKeiji Hayashibara 		case 2:
2945ba155a4SKeiji Hayashibara 			put_unaligned_le16(val, priv->rx_buf);
2955ba155a4SKeiji Hayashibara 			break;
2965ba155a4SKeiji Hayashibara 		case 4:
2975ba155a4SKeiji Hayashibara 			put_unaligned_le32(val, priv->rx_buf);
2985ba155a4SKeiji Hayashibara 			break;
2995ba155a4SKeiji Hayashibara 		}
3005ba155a4SKeiji Hayashibara 
3015ba155a4SKeiji Hayashibara 		priv->rx_buf += rsize;
3025ba155a4SKeiji Hayashibara 	}
3035ba155a4SKeiji Hayashibara }
3045ba155a4SKeiji Hayashibara 
uniphier_spi_set_fifo_threshold(struct uniphier_spi_priv * priv,unsigned int threshold)3059cd34efbSKunihiko Hayashi static void uniphier_spi_set_fifo_threshold(struct uniphier_spi_priv *priv,
3069cd34efbSKunihiko Hayashi 					    unsigned int threshold)
3075ba155a4SKeiji Hayashibara {
3085ba155a4SKeiji Hayashibara 	u32 val;
3095ba155a4SKeiji Hayashibara 
3105ba155a4SKeiji Hayashibara 	val = readl(priv->base + SSI_FC);
3115ba155a4SKeiji Hayashibara 	val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK);
3129cd34efbSKunihiko Hayashi 	val |= FIELD_PREP(SSI_FC_TXFTH_MASK, SSI_FIFO_DEPTH - threshold);
3139cd34efbSKunihiko Hayashi 	val |= FIELD_PREP(SSI_FC_RXFTH_MASK, threshold);
3145ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_FC);
3159cd34efbSKunihiko Hayashi }
3165ba155a4SKeiji Hayashibara 
uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv * priv)3179cd34efbSKunihiko Hayashi static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv)
3189cd34efbSKunihiko Hayashi {
3199cd34efbSKunihiko Hayashi 	unsigned int fifo_threshold, fill_words;
3209cd34efbSKunihiko Hayashi 	unsigned int bpw = bytes_per_word(priv->bits_per_word);
3219cd34efbSKunihiko Hayashi 
3229cd34efbSKunihiko Hayashi 	fifo_threshold = DIV_ROUND_UP(priv->rx_bytes, bpw);
3239cd34efbSKunihiko Hayashi 	fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH);
3249cd34efbSKunihiko Hayashi 
3259cd34efbSKunihiko Hayashi 	uniphier_spi_set_fifo_threshold(priv, fifo_threshold);
3269cd34efbSKunihiko Hayashi 
3279cd34efbSKunihiko Hayashi 	fill_words = fifo_threshold -
3289cd34efbSKunihiko Hayashi 		DIV_ROUND_UP(priv->rx_bytes - priv->tx_bytes, bpw);
3299cd34efbSKunihiko Hayashi 
3309cd34efbSKunihiko Hayashi 	while (fill_words--)
3315ba155a4SKeiji Hayashibara 		uniphier_spi_send(priv);
3325ba155a4SKeiji Hayashibara }
3335ba155a4SKeiji Hayashibara 
uniphier_spi_set_cs(struct spi_device * spi,bool enable)3345ba155a4SKeiji Hayashibara static void uniphier_spi_set_cs(struct spi_device *spi, bool enable)
3355ba155a4SKeiji Hayashibara {
3365ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
3375ba155a4SKeiji Hayashibara 	u32 val;
3385ba155a4SKeiji Hayashibara 
3395ba155a4SKeiji Hayashibara 	val = readl(priv->base + SSI_FPS);
3405ba155a4SKeiji Hayashibara 
3415ba155a4SKeiji Hayashibara 	if (enable)
3425ba155a4SKeiji Hayashibara 		val |= SSI_FPS_FSPOL;
3435ba155a4SKeiji Hayashibara 	else
3445ba155a4SKeiji Hayashibara 		val &= ~SSI_FPS_FSPOL;
3455ba155a4SKeiji Hayashibara 
3465ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_FPS);
3475ba155a4SKeiji Hayashibara }
3485ba155a4SKeiji Hayashibara 
uniphier_spi_can_dma(struct spi_master * master,struct spi_device * spi,struct spi_transfer * t)34928d1dddcSKunihiko Hayashi static bool uniphier_spi_can_dma(struct spi_master *master,
35028d1dddcSKunihiko Hayashi 				 struct spi_device *spi,
35128d1dddcSKunihiko Hayashi 				 struct spi_transfer *t)
35228d1dddcSKunihiko Hayashi {
35328d1dddcSKunihiko Hayashi 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
35428d1dddcSKunihiko Hayashi 	unsigned int bpw = bytes_per_word(priv->bits_per_word);
35528d1dddcSKunihiko Hayashi 
35628d1dddcSKunihiko Hayashi 	if ((!master->dma_tx && !master->dma_rx)
35728d1dddcSKunihiko Hayashi 	    || (!master->dma_tx && t->tx_buf)
35828d1dddcSKunihiko Hayashi 	    || (!master->dma_rx && t->rx_buf))
35928d1dddcSKunihiko Hayashi 		return false;
36028d1dddcSKunihiko Hayashi 
36128d1dddcSKunihiko Hayashi 	return DIV_ROUND_UP(t->len, bpw) > SSI_FIFO_DEPTH;
36228d1dddcSKunihiko Hayashi }
36328d1dddcSKunihiko Hayashi 
uniphier_spi_dma_rxcb(void * data)36428d1dddcSKunihiko Hayashi static void uniphier_spi_dma_rxcb(void *data)
36528d1dddcSKunihiko Hayashi {
36628d1dddcSKunihiko Hayashi 	struct spi_master *master = data;
36728d1dddcSKunihiko Hayashi 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
36828d1dddcSKunihiko Hayashi 	int state = atomic_fetch_andnot(SSI_DMA_RX_BUSY, &priv->dma_busy);
36928d1dddcSKunihiko Hayashi 
37028d1dddcSKunihiko Hayashi 	uniphier_spi_irq_disable(priv, SSI_IE_RXRE);
37128d1dddcSKunihiko Hayashi 
37228d1dddcSKunihiko Hayashi 	if (!(state & SSI_DMA_TX_BUSY))
37328d1dddcSKunihiko Hayashi 		spi_finalize_current_transfer(master);
37428d1dddcSKunihiko Hayashi }
37528d1dddcSKunihiko Hayashi 
uniphier_spi_dma_txcb(void * data)37628d1dddcSKunihiko Hayashi static void uniphier_spi_dma_txcb(void *data)
37728d1dddcSKunihiko Hayashi {
37828d1dddcSKunihiko Hayashi 	struct spi_master *master = data;
37928d1dddcSKunihiko Hayashi 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
38028d1dddcSKunihiko Hayashi 	int state = atomic_fetch_andnot(SSI_DMA_TX_BUSY, &priv->dma_busy);
38128d1dddcSKunihiko Hayashi 
38228d1dddcSKunihiko Hayashi 	uniphier_spi_irq_disable(priv, SSI_IE_TXRE);
38328d1dddcSKunihiko Hayashi 
38428d1dddcSKunihiko Hayashi 	if (!(state & SSI_DMA_RX_BUSY))
38528d1dddcSKunihiko Hayashi 		spi_finalize_current_transfer(master);
38628d1dddcSKunihiko Hayashi }
38728d1dddcSKunihiko Hayashi 
uniphier_spi_transfer_one_dma(struct spi_master * master,struct spi_device * spi,struct spi_transfer * t)38828d1dddcSKunihiko Hayashi static int uniphier_spi_transfer_one_dma(struct spi_master *master,
38928d1dddcSKunihiko Hayashi 					 struct spi_device *spi,
39028d1dddcSKunihiko Hayashi 					 struct spi_transfer *t)
39128d1dddcSKunihiko Hayashi {
39228d1dddcSKunihiko Hayashi 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
39328d1dddcSKunihiko Hayashi 	struct dma_async_tx_descriptor *rxdesc = NULL, *txdesc = NULL;
39428d1dddcSKunihiko Hayashi 	int buswidth;
39528d1dddcSKunihiko Hayashi 
39628d1dddcSKunihiko Hayashi 	atomic_set(&priv->dma_busy, 0);
39728d1dddcSKunihiko Hayashi 
39828d1dddcSKunihiko Hayashi 	uniphier_spi_set_fifo_threshold(priv, SSI_FIFO_BURST_NUM);
39928d1dddcSKunihiko Hayashi 
40028d1dddcSKunihiko Hayashi 	if (priv->bits_per_word <= 8)
40128d1dddcSKunihiko Hayashi 		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
40228d1dddcSKunihiko Hayashi 	else if (priv->bits_per_word <= 16)
40328d1dddcSKunihiko Hayashi 		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
40428d1dddcSKunihiko Hayashi 	else
40528d1dddcSKunihiko Hayashi 		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
40628d1dddcSKunihiko Hayashi 
40728d1dddcSKunihiko Hayashi 	if (priv->rx_buf) {
40828d1dddcSKunihiko Hayashi 		struct dma_slave_config rxconf = {
40928d1dddcSKunihiko Hayashi 			.direction = DMA_DEV_TO_MEM,
41028d1dddcSKunihiko Hayashi 			.src_addr = priv->base_dma_addr + SSI_RXDR,
41128d1dddcSKunihiko Hayashi 			.src_addr_width = buswidth,
41228d1dddcSKunihiko Hayashi 			.src_maxburst = SSI_FIFO_BURST_NUM,
41328d1dddcSKunihiko Hayashi 		};
41428d1dddcSKunihiko Hayashi 
41528d1dddcSKunihiko Hayashi 		dmaengine_slave_config(master->dma_rx, &rxconf);
41628d1dddcSKunihiko Hayashi 
41728d1dddcSKunihiko Hayashi 		rxdesc = dmaengine_prep_slave_sg(
41828d1dddcSKunihiko Hayashi 			master->dma_rx,
41928d1dddcSKunihiko Hayashi 			t->rx_sg.sgl, t->rx_sg.nents,
42028d1dddcSKunihiko Hayashi 			DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
42128d1dddcSKunihiko Hayashi 		if (!rxdesc)
42228d1dddcSKunihiko Hayashi 			goto out_err_prep;
42328d1dddcSKunihiko Hayashi 
42428d1dddcSKunihiko Hayashi 		rxdesc->callback = uniphier_spi_dma_rxcb;
42528d1dddcSKunihiko Hayashi 		rxdesc->callback_param = master;
42628d1dddcSKunihiko Hayashi 
42728d1dddcSKunihiko Hayashi 		uniphier_spi_irq_enable(priv, SSI_IE_RXRE);
42828d1dddcSKunihiko Hayashi 		atomic_or(SSI_DMA_RX_BUSY, &priv->dma_busy);
42928d1dddcSKunihiko Hayashi 
43028d1dddcSKunihiko Hayashi 		dmaengine_submit(rxdesc);
43128d1dddcSKunihiko Hayashi 		dma_async_issue_pending(master->dma_rx);
43228d1dddcSKunihiko Hayashi 	}
43328d1dddcSKunihiko Hayashi 
43428d1dddcSKunihiko Hayashi 	if (priv->tx_buf) {
43528d1dddcSKunihiko Hayashi 		struct dma_slave_config txconf = {
43628d1dddcSKunihiko Hayashi 			.direction = DMA_MEM_TO_DEV,
43728d1dddcSKunihiko Hayashi 			.dst_addr = priv->base_dma_addr + SSI_TXDR,
43828d1dddcSKunihiko Hayashi 			.dst_addr_width = buswidth,
43928d1dddcSKunihiko Hayashi 			.dst_maxburst = SSI_FIFO_BURST_NUM,
44028d1dddcSKunihiko Hayashi 		};
44128d1dddcSKunihiko Hayashi 
44228d1dddcSKunihiko Hayashi 		dmaengine_slave_config(master->dma_tx, &txconf);
44328d1dddcSKunihiko Hayashi 
44428d1dddcSKunihiko Hayashi 		txdesc = dmaengine_prep_slave_sg(
44528d1dddcSKunihiko Hayashi 			master->dma_tx,
44628d1dddcSKunihiko Hayashi 			t->tx_sg.sgl, t->tx_sg.nents,
44728d1dddcSKunihiko Hayashi 			DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
44828d1dddcSKunihiko Hayashi 		if (!txdesc)
44928d1dddcSKunihiko Hayashi 			goto out_err_prep;
45028d1dddcSKunihiko Hayashi 
45128d1dddcSKunihiko Hayashi 		txdesc->callback = uniphier_spi_dma_txcb;
45228d1dddcSKunihiko Hayashi 		txdesc->callback_param = master;
45328d1dddcSKunihiko Hayashi 
45428d1dddcSKunihiko Hayashi 		uniphier_spi_irq_enable(priv, SSI_IE_TXRE);
45528d1dddcSKunihiko Hayashi 		atomic_or(SSI_DMA_TX_BUSY, &priv->dma_busy);
45628d1dddcSKunihiko Hayashi 
45728d1dddcSKunihiko Hayashi 		dmaengine_submit(txdesc);
45828d1dddcSKunihiko Hayashi 		dma_async_issue_pending(master->dma_tx);
45928d1dddcSKunihiko Hayashi 	}
46028d1dddcSKunihiko Hayashi 
46128d1dddcSKunihiko Hayashi 	/* signal that we need to wait for completion */
46228d1dddcSKunihiko Hayashi 	return (priv->tx_buf || priv->rx_buf);
46328d1dddcSKunihiko Hayashi 
46428d1dddcSKunihiko Hayashi out_err_prep:
46528d1dddcSKunihiko Hayashi 	if (rxdesc)
46628d1dddcSKunihiko Hayashi 		dmaengine_terminate_sync(master->dma_rx);
46728d1dddcSKunihiko Hayashi 
46828d1dddcSKunihiko Hayashi 	return -EINVAL;
46928d1dddcSKunihiko Hayashi }
47028d1dddcSKunihiko Hayashi 
uniphier_spi_transfer_one_irq(struct spi_master * master,struct spi_device * spi,struct spi_transfer * t)47137ffab81SKeiji Hayashibara static int uniphier_spi_transfer_one_irq(struct spi_master *master,
4725ba155a4SKeiji Hayashibara 					 struct spi_device *spi,
4735ba155a4SKeiji Hayashibara 					 struct spi_transfer *t)
4745ba155a4SKeiji Hayashibara {
4755ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
476e4671df0SKeiji Hayashibara 	struct device *dev = master->dev.parent;
477e4671df0SKeiji Hayashibara 	unsigned long time_left;
4785ba155a4SKeiji Hayashibara 
4795ba155a4SKeiji Hayashibara 	reinit_completion(&priv->xfer_done);
4805ba155a4SKeiji Hayashibara 
4815ba155a4SKeiji Hayashibara 	uniphier_spi_fill_tx_fifo(priv);
4825ba155a4SKeiji Hayashibara 
4839859db51SKunihiko Hayashi 	uniphier_spi_irq_enable(priv, SSI_IE_RCIE | SSI_IE_RORIE);
4845ba155a4SKeiji Hayashibara 
485e4671df0SKeiji Hayashibara 	time_left = wait_for_completion_timeout(&priv->xfer_done,
4865ba155a4SKeiji Hayashibara 					msecs_to_jiffies(SSI_TIMEOUT_MS));
4875ba155a4SKeiji Hayashibara 
4889859db51SKunihiko Hayashi 	uniphier_spi_irq_disable(priv, SSI_IE_RCIE | SSI_IE_RORIE);
4895ba155a4SKeiji Hayashibara 
490e4671df0SKeiji Hayashibara 	if (!time_left) {
491e4671df0SKeiji Hayashibara 		dev_err(dev, "transfer timeout.\n");
492e4671df0SKeiji Hayashibara 		return -ETIMEDOUT;
493e4671df0SKeiji Hayashibara 	}
4945ba155a4SKeiji Hayashibara 
4955ba155a4SKeiji Hayashibara 	return priv->error;
4965ba155a4SKeiji Hayashibara }
4975ba155a4SKeiji Hayashibara 
uniphier_spi_transfer_one_poll(struct spi_master * master,struct spi_device * spi,struct spi_transfer * t)49837ffab81SKeiji Hayashibara static int uniphier_spi_transfer_one_poll(struct spi_master *master,
49937ffab81SKeiji Hayashibara 					  struct spi_device *spi,
50037ffab81SKeiji Hayashibara 					  struct spi_transfer *t)
50137ffab81SKeiji Hayashibara {
50237ffab81SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
50337ffab81SKeiji Hayashibara 	int loop = SSI_POLL_TIMEOUT_US * 10;
50437ffab81SKeiji Hayashibara 
50537ffab81SKeiji Hayashibara 	while (priv->tx_bytes) {
50637ffab81SKeiji Hayashibara 		uniphier_spi_fill_tx_fifo(priv);
50737ffab81SKeiji Hayashibara 
50837ffab81SKeiji Hayashibara 		while ((priv->rx_bytes - priv->tx_bytes) > 0) {
50937ffab81SKeiji Hayashibara 			while (!(readl(priv->base + SSI_SR) & SSI_SR_RNE)
51037ffab81SKeiji Hayashibara 								&& loop--)
51137ffab81SKeiji Hayashibara 				ndelay(100);
51237ffab81SKeiji Hayashibara 
51337ffab81SKeiji Hayashibara 			if (loop == -1)
51437ffab81SKeiji Hayashibara 				goto irq_transfer;
51537ffab81SKeiji Hayashibara 
51637ffab81SKeiji Hayashibara 			uniphier_spi_recv(priv);
51737ffab81SKeiji Hayashibara 		}
51837ffab81SKeiji Hayashibara 	}
51937ffab81SKeiji Hayashibara 
52037ffab81SKeiji Hayashibara 	return 0;
52137ffab81SKeiji Hayashibara 
52237ffab81SKeiji Hayashibara irq_transfer:
52337ffab81SKeiji Hayashibara 	return uniphier_spi_transfer_one_irq(master, spi, t);
52437ffab81SKeiji Hayashibara }
52537ffab81SKeiji Hayashibara 
uniphier_spi_transfer_one(struct spi_master * master,struct spi_device * spi,struct spi_transfer * t)52637ffab81SKeiji Hayashibara static int uniphier_spi_transfer_one(struct spi_master *master,
52737ffab81SKeiji Hayashibara 				     struct spi_device *spi,
52837ffab81SKeiji Hayashibara 				     struct spi_transfer *t)
52937ffab81SKeiji Hayashibara {
53037ffab81SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
53137ffab81SKeiji Hayashibara 	unsigned long threshold;
53228d1dddcSKunihiko Hayashi 	bool use_dma;
53337ffab81SKeiji Hayashibara 
53437ffab81SKeiji Hayashibara 	/* Terminate and return success for 0 byte length transfer */
53537ffab81SKeiji Hayashibara 	if (!t->len)
53637ffab81SKeiji Hayashibara 		return 0;
53737ffab81SKeiji Hayashibara 
53837ffab81SKeiji Hayashibara 	uniphier_spi_setup_transfer(spi, t);
53937ffab81SKeiji Hayashibara 
54028d1dddcSKunihiko Hayashi 	use_dma = master->can_dma ? master->can_dma(master, spi, t) : false;
54128d1dddcSKunihiko Hayashi 	if (use_dma)
54228d1dddcSKunihiko Hayashi 		return uniphier_spi_transfer_one_dma(master, spi, t);
54328d1dddcSKunihiko Hayashi 
54437ffab81SKeiji Hayashibara 	/*
54537ffab81SKeiji Hayashibara 	 * If the transfer operation will take longer than
54637ffab81SKeiji Hayashibara 	 * SSI_POLL_TIMEOUT_US, it should use irq.
54737ffab81SKeiji Hayashibara 	 */
54837ffab81SKeiji Hayashibara 	threshold = DIV_ROUND_UP(SSI_POLL_TIMEOUT_US * priv->speed_hz,
54937ffab81SKeiji Hayashibara 					USEC_PER_SEC * BITS_PER_BYTE);
55037ffab81SKeiji Hayashibara 	if (t->len > threshold)
55137ffab81SKeiji Hayashibara 		return uniphier_spi_transfer_one_irq(master, spi, t);
55237ffab81SKeiji Hayashibara 	else
55337ffab81SKeiji Hayashibara 		return uniphier_spi_transfer_one_poll(master, spi, t);
55437ffab81SKeiji Hayashibara }
55537ffab81SKeiji Hayashibara 
uniphier_spi_prepare_transfer_hardware(struct spi_master * master)5565ba155a4SKeiji Hayashibara static int uniphier_spi_prepare_transfer_hardware(struct spi_master *master)
5575ba155a4SKeiji Hayashibara {
5585ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
5595ba155a4SKeiji Hayashibara 
5605ba155a4SKeiji Hayashibara 	writel(SSI_CTL_EN, priv->base + SSI_CTL);
5615ba155a4SKeiji Hayashibara 
5625ba155a4SKeiji Hayashibara 	return 0;
5635ba155a4SKeiji Hayashibara }
5645ba155a4SKeiji Hayashibara 
uniphier_spi_unprepare_transfer_hardware(struct spi_master * master)5655ba155a4SKeiji Hayashibara static int uniphier_spi_unprepare_transfer_hardware(struct spi_master *master)
5665ba155a4SKeiji Hayashibara {
5675ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
5685ba155a4SKeiji Hayashibara 
5695ba155a4SKeiji Hayashibara 	writel(0, priv->base + SSI_CTL);
5705ba155a4SKeiji Hayashibara 
5715ba155a4SKeiji Hayashibara 	return 0;
5725ba155a4SKeiji Hayashibara }
5735ba155a4SKeiji Hayashibara 
uniphier_spi_handle_err(struct spi_master * master,struct spi_message * msg)57411299c5cSKunihiko Hayashi static void uniphier_spi_handle_err(struct spi_master *master,
57511299c5cSKunihiko Hayashi 				    struct spi_message *msg)
57611299c5cSKunihiko Hayashi {
57711299c5cSKunihiko Hayashi 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
57811299c5cSKunihiko Hayashi 	u32 val;
57911299c5cSKunihiko Hayashi 
58011299c5cSKunihiko Hayashi 	/* stop running spi transfer */
58111299c5cSKunihiko Hayashi 	writel(0, priv->base + SSI_CTL);
58211299c5cSKunihiko Hayashi 
58311299c5cSKunihiko Hayashi 	/* reset FIFOs */
58411299c5cSKunihiko Hayashi 	val = SSI_FC_TXFFL | SSI_FC_RXFFL;
58511299c5cSKunihiko Hayashi 	writel(val, priv->base + SSI_FC);
58611299c5cSKunihiko Hayashi 
58728d1dddcSKunihiko Hayashi 	uniphier_spi_irq_disable(priv, SSI_IE_ALL_MASK);
58828d1dddcSKunihiko Hayashi 
58928d1dddcSKunihiko Hayashi 	if (atomic_read(&priv->dma_busy) & SSI_DMA_TX_BUSY) {
59028d1dddcSKunihiko Hayashi 		dmaengine_terminate_async(master->dma_tx);
59128d1dddcSKunihiko Hayashi 		atomic_andnot(SSI_DMA_TX_BUSY, &priv->dma_busy);
59228d1dddcSKunihiko Hayashi 	}
59328d1dddcSKunihiko Hayashi 
59428d1dddcSKunihiko Hayashi 	if (atomic_read(&priv->dma_busy) & SSI_DMA_RX_BUSY) {
59528d1dddcSKunihiko Hayashi 		dmaengine_terminate_async(master->dma_rx);
59628d1dddcSKunihiko Hayashi 		atomic_andnot(SSI_DMA_RX_BUSY, &priv->dma_busy);
59728d1dddcSKunihiko Hayashi 	}
59811299c5cSKunihiko Hayashi }
59911299c5cSKunihiko Hayashi 
uniphier_spi_handler(int irq,void * dev_id)6005ba155a4SKeiji Hayashibara static irqreturn_t uniphier_spi_handler(int irq, void *dev_id)
6015ba155a4SKeiji Hayashibara {
6025ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv = dev_id;
6035ba155a4SKeiji Hayashibara 	u32 val, stat;
6045ba155a4SKeiji Hayashibara 
6055ba155a4SKeiji Hayashibara 	stat = readl(priv->base + SSI_IS);
6065ba155a4SKeiji Hayashibara 	val = SSI_IC_TCIC | SSI_IC_RCIC | SSI_IC_RORIC;
6075ba155a4SKeiji Hayashibara 	writel(val, priv->base + SSI_IC);
6085ba155a4SKeiji Hayashibara 
6095ba155a4SKeiji Hayashibara 	/* rx fifo overrun */
6105ba155a4SKeiji Hayashibara 	if (stat & SSI_IS_RORID) {
6115ba155a4SKeiji Hayashibara 		priv->error = -EIO;
6125ba155a4SKeiji Hayashibara 		goto done;
6135ba155a4SKeiji Hayashibara 	}
6145ba155a4SKeiji Hayashibara 
6155ba155a4SKeiji Hayashibara 	/* rx complete */
6165ba155a4SKeiji Hayashibara 	if ((stat & SSI_IS_RCID) && (stat & SSI_IS_RXRS)) {
6175ba155a4SKeiji Hayashibara 		while ((readl(priv->base + SSI_SR) & SSI_SR_RNE) &&
6185ba155a4SKeiji Hayashibara 				(priv->rx_bytes - priv->tx_bytes) > 0)
6195ba155a4SKeiji Hayashibara 			uniphier_spi_recv(priv);
6205ba155a4SKeiji Hayashibara 
6215ba155a4SKeiji Hayashibara 		if ((readl(priv->base + SSI_SR) & SSI_SR_RNE) ||
6225ba155a4SKeiji Hayashibara 				(priv->rx_bytes != priv->tx_bytes)) {
6235ba155a4SKeiji Hayashibara 			priv->error = -EIO;
6245ba155a4SKeiji Hayashibara 			goto done;
6255ba155a4SKeiji Hayashibara 		} else if (priv->rx_bytes == 0)
6265ba155a4SKeiji Hayashibara 			goto done;
6275ba155a4SKeiji Hayashibara 
6285ba155a4SKeiji Hayashibara 		/* next tx transfer */
6295ba155a4SKeiji Hayashibara 		uniphier_spi_fill_tx_fifo(priv);
6305ba155a4SKeiji Hayashibara 
6315ba155a4SKeiji Hayashibara 		return IRQ_HANDLED;
6325ba155a4SKeiji Hayashibara 	}
6335ba155a4SKeiji Hayashibara 
6345ba155a4SKeiji Hayashibara 	return IRQ_NONE;
6355ba155a4SKeiji Hayashibara 
6365ba155a4SKeiji Hayashibara done:
6375ba155a4SKeiji Hayashibara 	complete(&priv->xfer_done);
6385ba155a4SKeiji Hayashibara 	return IRQ_HANDLED;
6395ba155a4SKeiji Hayashibara }
6405ba155a4SKeiji Hayashibara 
uniphier_spi_probe(struct platform_device * pdev)6415ba155a4SKeiji Hayashibara static int uniphier_spi_probe(struct platform_device *pdev)
6425ba155a4SKeiji Hayashibara {
6435ba155a4SKeiji Hayashibara 	struct uniphier_spi_priv *priv;
6445ba155a4SKeiji Hayashibara 	struct spi_master *master;
64528d1dddcSKunihiko Hayashi 	struct resource *res;
64628d1dddcSKunihiko Hayashi 	struct dma_slave_caps caps;
64728d1dddcSKunihiko Hayashi 	u32 dma_tx_burst = 0, dma_rx_burst = 0;
6485ba155a4SKeiji Hayashibara 	unsigned long clk_rate;
6495ba155a4SKeiji Hayashibara 	int irq;
6505ba155a4SKeiji Hayashibara 	int ret;
6515ba155a4SKeiji Hayashibara 
6525ba155a4SKeiji Hayashibara 	master = spi_alloc_master(&pdev->dev, sizeof(*priv));
6535ba155a4SKeiji Hayashibara 	if (!master)
6545ba155a4SKeiji Hayashibara 		return -ENOMEM;
6555ba155a4SKeiji Hayashibara 
6565ba155a4SKeiji Hayashibara 	platform_set_drvdata(pdev, master);
6575ba155a4SKeiji Hayashibara 
6585ba155a4SKeiji Hayashibara 	priv = spi_master_get_devdata(master);
6595ba155a4SKeiji Hayashibara 	priv->master = master;
6605ba155a4SKeiji Hayashibara 	priv->is_save_param = false;
6615ba155a4SKeiji Hayashibara 
6625bc48615SKunihiko Hayashi 	priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
6635ba155a4SKeiji Hayashibara 	if (IS_ERR(priv->base)) {
6645ba155a4SKeiji Hayashibara 		ret = PTR_ERR(priv->base);
6655ba155a4SKeiji Hayashibara 		goto out_master_put;
6665ba155a4SKeiji Hayashibara 	}
66728d1dddcSKunihiko Hayashi 	priv->base_dma_addr = res->start;
6685ba155a4SKeiji Hayashibara 
6695ba155a4SKeiji Hayashibara 	priv->clk = devm_clk_get(&pdev->dev, NULL);
6705ba155a4SKeiji Hayashibara 	if (IS_ERR(priv->clk)) {
6715ba155a4SKeiji Hayashibara 		dev_err(&pdev->dev, "failed to get clock\n");
6725ba155a4SKeiji Hayashibara 		ret = PTR_ERR(priv->clk);
6735ba155a4SKeiji Hayashibara 		goto out_master_put;
6745ba155a4SKeiji Hayashibara 	}
6755ba155a4SKeiji Hayashibara 
6765ba155a4SKeiji Hayashibara 	ret = clk_prepare_enable(priv->clk);
6775ba155a4SKeiji Hayashibara 	if (ret)
6785ba155a4SKeiji Hayashibara 		goto out_master_put;
6795ba155a4SKeiji Hayashibara 
6805ba155a4SKeiji Hayashibara 	irq = platform_get_irq(pdev, 0);
6815ba155a4SKeiji Hayashibara 	if (irq < 0) {
6825ba155a4SKeiji Hayashibara 		ret = irq;
6835ba155a4SKeiji Hayashibara 		goto out_disable_clk;
6845ba155a4SKeiji Hayashibara 	}
6855ba155a4SKeiji Hayashibara 
6865ba155a4SKeiji Hayashibara 	ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler,
6875ba155a4SKeiji Hayashibara 			       0, "uniphier-spi", priv);
6885ba155a4SKeiji Hayashibara 	if (ret) {
6895ba155a4SKeiji Hayashibara 		dev_err(&pdev->dev, "failed to request IRQ\n");
6905ba155a4SKeiji Hayashibara 		goto out_disable_clk;
6915ba155a4SKeiji Hayashibara 	}
6925ba155a4SKeiji Hayashibara 
6935ba155a4SKeiji Hayashibara 	init_completion(&priv->xfer_done);
6945ba155a4SKeiji Hayashibara 
6955ba155a4SKeiji Hayashibara 	clk_rate = clk_get_rate(priv->clk);
6965ba155a4SKeiji Hayashibara 
6975ba155a4SKeiji Hayashibara 	master->max_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MIN_CLK_DIVIDER);
6985ba155a4SKeiji Hayashibara 	master->min_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MAX_CLK_DIVIDER);
6995ba155a4SKeiji Hayashibara 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
7005ba155a4SKeiji Hayashibara 	master->dev.of_node = pdev->dev.of_node;
7015ba155a4SKeiji Hayashibara 	master->bus_num = pdev->id;
7025ba155a4SKeiji Hayashibara 	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
7035ba155a4SKeiji Hayashibara 
7045ba155a4SKeiji Hayashibara 	master->set_cs = uniphier_spi_set_cs;
7055ba155a4SKeiji Hayashibara 	master->transfer_one = uniphier_spi_transfer_one;
7065ba155a4SKeiji Hayashibara 	master->prepare_transfer_hardware
7075ba155a4SKeiji Hayashibara 				= uniphier_spi_prepare_transfer_hardware;
7085ba155a4SKeiji Hayashibara 	master->unprepare_transfer_hardware
7095ba155a4SKeiji Hayashibara 				= uniphier_spi_unprepare_transfer_hardware;
71011299c5cSKunihiko Hayashi 	master->handle_err = uniphier_spi_handle_err;
71128d1dddcSKunihiko Hayashi 	master->can_dma = uniphier_spi_can_dma;
71228d1dddcSKunihiko Hayashi 
7135ba155a4SKeiji Hayashibara 	master->num_chipselect = 1;
71428d1dddcSKunihiko Hayashi 	master->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
71528d1dddcSKunihiko Hayashi 
71628d1dddcSKunihiko Hayashi 	master->dma_tx = dma_request_chan(&pdev->dev, "tx");
71728d1dddcSKunihiko Hayashi 	if (IS_ERR_OR_NULL(master->dma_tx)) {
71818168291SWei Yongjun 		if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) {
71918168291SWei Yongjun 			ret = -EPROBE_DEFER;
72028d1dddcSKunihiko Hayashi 			goto out_disable_clk;
72118168291SWei Yongjun 		}
72228d1dddcSKunihiko Hayashi 		master->dma_tx = NULL;
72328d1dddcSKunihiko Hayashi 		dma_tx_burst = INT_MAX;
72428d1dddcSKunihiko Hayashi 	} else {
72528d1dddcSKunihiko Hayashi 		ret = dma_get_slave_caps(master->dma_tx, &caps);
72628d1dddcSKunihiko Hayashi 		if (ret) {
72728d1dddcSKunihiko Hayashi 			dev_err(&pdev->dev, "failed to get TX DMA capacities: %d\n",
72828d1dddcSKunihiko Hayashi 				ret);
72937c2c83cSXin Xiong 			goto out_release_dma;
73028d1dddcSKunihiko Hayashi 		}
73128d1dddcSKunihiko Hayashi 		dma_tx_burst = caps.max_burst;
73228d1dddcSKunihiko Hayashi 	}
73328d1dddcSKunihiko Hayashi 
73428d1dddcSKunihiko Hayashi 	master->dma_rx = dma_request_chan(&pdev->dev, "rx");
73528d1dddcSKunihiko Hayashi 	if (IS_ERR_OR_NULL(master->dma_rx)) {
73618168291SWei Yongjun 		if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) {
73718168291SWei Yongjun 			ret = -EPROBE_DEFER;
73837c2c83cSXin Xiong 			goto out_release_dma;
73918168291SWei Yongjun 		}
74028d1dddcSKunihiko Hayashi 		master->dma_rx = NULL;
74128d1dddcSKunihiko Hayashi 		dma_rx_burst = INT_MAX;
74228d1dddcSKunihiko Hayashi 	} else {
74328d1dddcSKunihiko Hayashi 		ret = dma_get_slave_caps(master->dma_rx, &caps);
74428d1dddcSKunihiko Hayashi 		if (ret) {
74528d1dddcSKunihiko Hayashi 			dev_err(&pdev->dev, "failed to get RX DMA capacities: %d\n",
74628d1dddcSKunihiko Hayashi 				ret);
74737c2c83cSXin Xiong 			goto out_release_dma;
74828d1dddcSKunihiko Hayashi 		}
74928d1dddcSKunihiko Hayashi 		dma_rx_burst = caps.max_burst;
75028d1dddcSKunihiko Hayashi 	}
75128d1dddcSKunihiko Hayashi 
75228d1dddcSKunihiko Hayashi 	master->max_dma_len = min(dma_tx_burst, dma_rx_burst);
7535ba155a4SKeiji Hayashibara 
7545ba155a4SKeiji Hayashibara 	ret = devm_spi_register_master(&pdev->dev, master);
7555ba155a4SKeiji Hayashibara 	if (ret)
75637c2c83cSXin Xiong 		goto out_release_dma;
7575ba155a4SKeiji Hayashibara 
7585ba155a4SKeiji Hayashibara 	return 0;
7595ba155a4SKeiji Hayashibara 
76037c2c83cSXin Xiong out_release_dma:
76137c2c83cSXin Xiong 	if (!IS_ERR_OR_NULL(master->dma_rx)) {
76237c2c83cSXin Xiong 		dma_release_channel(master->dma_rx);
76337c2c83cSXin Xiong 		master->dma_rx = NULL;
76437c2c83cSXin Xiong 	}
76537c2c83cSXin Xiong 	if (!IS_ERR_OR_NULL(master->dma_tx)) {
76637c2c83cSXin Xiong 		dma_release_channel(master->dma_tx);
76737c2c83cSXin Xiong 		master->dma_tx = NULL;
76837c2c83cSXin Xiong 	}
76937c2c83cSXin Xiong 
7705ba155a4SKeiji Hayashibara out_disable_clk:
7715ba155a4SKeiji Hayashibara 	clk_disable_unprepare(priv->clk);
7725ba155a4SKeiji Hayashibara 
7735ba155a4SKeiji Hayashibara out_master_put:
7745ba155a4SKeiji Hayashibara 	spi_master_put(master);
7755ba155a4SKeiji Hayashibara 	return ret;
7765ba155a4SKeiji Hayashibara }
7775ba155a4SKeiji Hayashibara 
uniphier_spi_remove(struct platform_device * pdev)778*1b13d196SUwe Kleine-König static void uniphier_spi_remove(struct platform_device *pdev)
7795ba155a4SKeiji Hayashibara {
78023e3404dSKunihiko Hayashi 	struct spi_master *master = platform_get_drvdata(pdev);
78123e3404dSKunihiko Hayashi 	struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
7825ba155a4SKeiji Hayashibara 
78323e3404dSKunihiko Hayashi 	if (master->dma_tx)
78423e3404dSKunihiko Hayashi 		dma_release_channel(master->dma_tx);
78523e3404dSKunihiko Hayashi 	if (master->dma_rx)
78623e3404dSKunihiko Hayashi 		dma_release_channel(master->dma_rx);
78728d1dddcSKunihiko Hayashi 
7885ba155a4SKeiji Hayashibara 	clk_disable_unprepare(priv->clk);
7895ba155a4SKeiji Hayashibara }
7905ba155a4SKeiji Hayashibara 
7915ba155a4SKeiji Hayashibara static const struct of_device_id uniphier_spi_match[] = {
7925ba155a4SKeiji Hayashibara 	{ .compatible = "socionext,uniphier-scssi" },
7935ba155a4SKeiji Hayashibara 	{ /* sentinel */ }
7945ba155a4SKeiji Hayashibara };
7955ba155a4SKeiji Hayashibara MODULE_DEVICE_TABLE(of, uniphier_spi_match);
7965ba155a4SKeiji Hayashibara 
7975ba155a4SKeiji Hayashibara static struct platform_driver uniphier_spi_driver = {
7985ba155a4SKeiji Hayashibara 	.probe = uniphier_spi_probe,
799*1b13d196SUwe Kleine-König 	.remove_new = uniphier_spi_remove,
8005ba155a4SKeiji Hayashibara 	.driver = {
8015ba155a4SKeiji Hayashibara 		.name = "uniphier-spi",
8025ba155a4SKeiji Hayashibara 		.of_match_table = uniphier_spi_match,
8035ba155a4SKeiji Hayashibara 	},
8045ba155a4SKeiji Hayashibara };
8055ba155a4SKeiji Hayashibara module_platform_driver(uniphier_spi_driver);
8065ba155a4SKeiji Hayashibara 
8075ba155a4SKeiji Hayashibara MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
8085ba155a4SKeiji Hayashibara MODULE_AUTHOR("Keiji Hayashibara <hayashibara.keiji@socionext.com>");
8095ba155a4SKeiji Hayashibara MODULE_DESCRIPTION("Socionext UniPhier SPI controller driver");
8105ba155a4SKeiji Hayashibara MODULE_LICENSE("GPL v2");
811