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