104dc82e1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23270ac23SPurna Chandra Mandal /*
33270ac23SPurna Chandra Mandal * PIC32 Quad SPI controller driver.
43270ac23SPurna Chandra Mandal *
53270ac23SPurna Chandra Mandal * Purna Chandra Mandal <purna.mandal@microchip.com>
63270ac23SPurna Chandra Mandal * Copyright (c) 2016, Microchip Technology Inc.
73270ac23SPurna Chandra Mandal */
83270ac23SPurna Chandra Mandal
93270ac23SPurna Chandra Mandal #include <linux/clk.h>
103270ac23SPurna Chandra Mandal #include <linux/dma-mapping.h>
113270ac23SPurna Chandra Mandal #include <linux/interrupt.h>
123270ac23SPurna Chandra Mandal #include <linux/io.h>
133270ac23SPurna Chandra Mandal #include <linux/iopoll.h>
143270ac23SPurna Chandra Mandal #include <linux/module.h>
153270ac23SPurna Chandra Mandal #include <linux/of.h>
163270ac23SPurna Chandra Mandal #include <linux/platform_device.h>
173270ac23SPurna Chandra Mandal #include <linux/slab.h>
183270ac23SPurna Chandra Mandal #include <linux/spi/spi.h>
193270ac23SPurna Chandra Mandal
203270ac23SPurna Chandra Mandal /* SQI registers */
213270ac23SPurna Chandra Mandal #define PESQI_XIP_CONF1_REG 0x00
223270ac23SPurna Chandra Mandal #define PESQI_XIP_CONF2_REG 0x04
233270ac23SPurna Chandra Mandal #define PESQI_CONF_REG 0x08
243270ac23SPurna Chandra Mandal #define PESQI_CTRL_REG 0x0C
253270ac23SPurna Chandra Mandal #define PESQI_CLK_CTRL_REG 0x10
263270ac23SPurna Chandra Mandal #define PESQI_CMD_THRES_REG 0x14
273270ac23SPurna Chandra Mandal #define PESQI_INT_THRES_REG 0x18
283270ac23SPurna Chandra Mandal #define PESQI_INT_ENABLE_REG 0x1C
293270ac23SPurna Chandra Mandal #define PESQI_INT_STAT_REG 0x20
303270ac23SPurna Chandra Mandal #define PESQI_TX_DATA_REG 0x24
313270ac23SPurna Chandra Mandal #define PESQI_RX_DATA_REG 0x28
323270ac23SPurna Chandra Mandal #define PESQI_STAT1_REG 0x2C
333270ac23SPurna Chandra Mandal #define PESQI_STAT2_REG 0x30
343270ac23SPurna Chandra Mandal #define PESQI_BD_CTRL_REG 0x34
353270ac23SPurna Chandra Mandal #define PESQI_BD_CUR_ADDR_REG 0x38
363270ac23SPurna Chandra Mandal #define PESQI_BD_BASE_ADDR_REG 0x40
373270ac23SPurna Chandra Mandal #define PESQI_BD_STAT_REG 0x44
383270ac23SPurna Chandra Mandal #define PESQI_BD_POLL_CTRL_REG 0x48
393270ac23SPurna Chandra Mandal #define PESQI_BD_TX_DMA_STAT_REG 0x4C
403270ac23SPurna Chandra Mandal #define PESQI_BD_RX_DMA_STAT_REG 0x50
413270ac23SPurna Chandra Mandal #define PESQI_THRES_REG 0x54
423270ac23SPurna Chandra Mandal #define PESQI_INT_SIGEN_REG 0x58
433270ac23SPurna Chandra Mandal
443270ac23SPurna Chandra Mandal /* PESQI_CONF_REG fields */
453270ac23SPurna Chandra Mandal #define PESQI_MODE 0x7
463270ac23SPurna Chandra Mandal #define PESQI_MODE_BOOT 0
473270ac23SPurna Chandra Mandal #define PESQI_MODE_PIO 1
483270ac23SPurna Chandra Mandal #define PESQI_MODE_DMA 2
493270ac23SPurna Chandra Mandal #define PESQI_MODE_XIP 3
503270ac23SPurna Chandra Mandal #define PESQI_MODE_SHIFT 0
513270ac23SPurna Chandra Mandal #define PESQI_CPHA BIT(3)
523270ac23SPurna Chandra Mandal #define PESQI_CPOL BIT(4)
533270ac23SPurna Chandra Mandal #define PESQI_LSBF BIT(5)
543270ac23SPurna Chandra Mandal #define PESQI_RXLATCH BIT(7)
553270ac23SPurna Chandra Mandal #define PESQI_SERMODE BIT(8)
563270ac23SPurna Chandra Mandal #define PESQI_WP_EN BIT(9)
573270ac23SPurna Chandra Mandal #define PESQI_HOLD_EN BIT(10)
583270ac23SPurna Chandra Mandal #define PESQI_BURST_EN BIT(12)
593270ac23SPurna Chandra Mandal #define PESQI_CS_CTRL_HW BIT(15)
603270ac23SPurna Chandra Mandal #define PESQI_SOFT_RESET BIT(16)
613270ac23SPurna Chandra Mandal #define PESQI_LANES_SHIFT 20
623270ac23SPurna Chandra Mandal #define PESQI_SINGLE_LANE 0
633270ac23SPurna Chandra Mandal #define PESQI_DUAL_LANE 1
643270ac23SPurna Chandra Mandal #define PESQI_QUAD_LANE 2
653270ac23SPurna Chandra Mandal #define PESQI_CSEN_SHIFT 24
663270ac23SPurna Chandra Mandal #define PESQI_EN BIT(23)
673270ac23SPurna Chandra Mandal
683270ac23SPurna Chandra Mandal /* PESQI_CLK_CTRL_REG fields */
693270ac23SPurna Chandra Mandal #define PESQI_CLK_EN BIT(0)
703270ac23SPurna Chandra Mandal #define PESQI_CLK_STABLE BIT(1)
713270ac23SPurna Chandra Mandal #define PESQI_CLKDIV_SHIFT 8
723270ac23SPurna Chandra Mandal #define PESQI_CLKDIV 0xff
733270ac23SPurna Chandra Mandal
743270ac23SPurna Chandra Mandal /* PESQI_INT_THR/CMD_THR_REG */
753270ac23SPurna Chandra Mandal #define PESQI_TXTHR_MASK 0x1f
763270ac23SPurna Chandra Mandal #define PESQI_TXTHR_SHIFT 8
773270ac23SPurna Chandra Mandal #define PESQI_RXTHR_MASK 0x1f
783270ac23SPurna Chandra Mandal #define PESQI_RXTHR_SHIFT 0
793270ac23SPurna Chandra Mandal
803270ac23SPurna Chandra Mandal /* PESQI_INT_EN/INT_STAT/INT_SIG_EN_REG */
813270ac23SPurna Chandra Mandal #define PESQI_TXEMPTY BIT(0)
823270ac23SPurna Chandra Mandal #define PESQI_TXFULL BIT(1)
833270ac23SPurna Chandra Mandal #define PESQI_TXTHR BIT(2)
843270ac23SPurna Chandra Mandal #define PESQI_RXEMPTY BIT(3)
853270ac23SPurna Chandra Mandal #define PESQI_RXFULL BIT(4)
863270ac23SPurna Chandra Mandal #define PESQI_RXTHR BIT(5)
873270ac23SPurna Chandra Mandal #define PESQI_BDDONE BIT(9) /* BD processing complete */
883270ac23SPurna Chandra Mandal #define PESQI_PKTCOMP BIT(10) /* packet processing complete */
893270ac23SPurna Chandra Mandal #define PESQI_DMAERR BIT(11) /* error */
903270ac23SPurna Chandra Mandal
913270ac23SPurna Chandra Mandal /* PESQI_BD_CTRL_REG */
923270ac23SPurna Chandra Mandal #define PESQI_DMA_EN BIT(0) /* enable DMA engine */
933270ac23SPurna Chandra Mandal #define PESQI_POLL_EN BIT(1) /* enable polling */
943270ac23SPurna Chandra Mandal #define PESQI_BDP_START BIT(2) /* start BD processor */
953270ac23SPurna Chandra Mandal
963270ac23SPurna Chandra Mandal /* PESQI controller buffer descriptor */
973270ac23SPurna Chandra Mandal struct buf_desc {
983270ac23SPurna Chandra Mandal u32 bd_ctrl; /* control */
993270ac23SPurna Chandra Mandal u32 bd_status; /* reserved */
1003270ac23SPurna Chandra Mandal u32 bd_addr; /* DMA buffer addr */
1013270ac23SPurna Chandra Mandal u32 bd_nextp; /* next item in chain */
1023270ac23SPurna Chandra Mandal };
1033270ac23SPurna Chandra Mandal
1043270ac23SPurna Chandra Mandal /* bd_ctrl */
1053270ac23SPurna Chandra Mandal #define BD_BUFLEN 0x1ff
1063270ac23SPurna Chandra Mandal #define BD_CBD_INT_EN BIT(16) /* Current BD is processed */
1073270ac23SPurna Chandra Mandal #define BD_PKT_INT_EN BIT(17) /* All BDs of PKT processed */
1083270ac23SPurna Chandra Mandal #define BD_LIFM BIT(18) /* last data of pkt */
1093270ac23SPurna Chandra Mandal #define BD_LAST BIT(19) /* end of list */
1103270ac23SPurna Chandra Mandal #define BD_DATA_RECV BIT(20) /* receive data */
1113270ac23SPurna Chandra Mandal #define BD_DDR BIT(21) /* DDR mode */
1123270ac23SPurna Chandra Mandal #define BD_DUAL BIT(22) /* Dual SPI */
1133270ac23SPurna Chandra Mandal #define BD_QUAD BIT(23) /* Quad SPI */
1143270ac23SPurna Chandra Mandal #define BD_LSBF BIT(25) /* LSB First */
1153270ac23SPurna Chandra Mandal #define BD_STAT_CHECK BIT(27) /* Status poll */
1163270ac23SPurna Chandra Mandal #define BD_DEVSEL_SHIFT 28 /* CS */
1173270ac23SPurna Chandra Mandal #define BD_CS_DEASSERT BIT(30) /* de-assert CS after current BD */
1183270ac23SPurna Chandra Mandal #define BD_EN BIT(31) /* BD owned by H/W */
1193270ac23SPurna Chandra Mandal
1203270ac23SPurna Chandra Mandal /**
1213270ac23SPurna Chandra Mandal * struct ring_desc - Representation of SQI ring descriptor
1223270ac23SPurna Chandra Mandal * @list: list element to add to free or used list.
1233270ac23SPurna Chandra Mandal * @bd: PESQI controller buffer descriptor
1243270ac23SPurna Chandra Mandal * @bd_dma: DMA address of PESQI controller buffer descriptor
1253270ac23SPurna Chandra Mandal * @xfer_len: transfer length
1263270ac23SPurna Chandra Mandal */
1273270ac23SPurna Chandra Mandal struct ring_desc {
1283270ac23SPurna Chandra Mandal struct list_head list;
1293270ac23SPurna Chandra Mandal struct buf_desc *bd;
1303270ac23SPurna Chandra Mandal dma_addr_t bd_dma;
1313270ac23SPurna Chandra Mandal u32 xfer_len;
1323270ac23SPurna Chandra Mandal };
1333270ac23SPurna Chandra Mandal
1343270ac23SPurna Chandra Mandal /* Global constants */
1353270ac23SPurna Chandra Mandal #define PESQI_BD_BUF_LEN_MAX 256
1363270ac23SPurna Chandra Mandal #define PESQI_BD_COUNT 256 /* max 64KB data per spi message */
1373270ac23SPurna Chandra Mandal
1383270ac23SPurna Chandra Mandal struct pic32_sqi {
1393270ac23SPurna Chandra Mandal void __iomem *regs;
1403270ac23SPurna Chandra Mandal struct clk *sys_clk;
1413270ac23SPurna Chandra Mandal struct clk *base_clk; /* drives spi clock */
142*cc64ab49SYang Yingliang struct spi_controller *host;
1433270ac23SPurna Chandra Mandal int irq;
1443270ac23SPurna Chandra Mandal struct completion xfer_done;
1453270ac23SPurna Chandra Mandal struct ring_desc *ring;
1463270ac23SPurna Chandra Mandal void *bd;
1473270ac23SPurna Chandra Mandal dma_addr_t bd_dma;
1483270ac23SPurna Chandra Mandal struct list_head bd_list_free; /* free */
1493270ac23SPurna Chandra Mandal struct list_head bd_list_used; /* allocated */
1503270ac23SPurna Chandra Mandal struct spi_device *cur_spi;
1513270ac23SPurna Chandra Mandal u32 cur_speed;
1523270ac23SPurna Chandra Mandal u8 cur_mode;
1533270ac23SPurna Chandra Mandal };
1543270ac23SPurna Chandra Mandal
pic32_setbits(void __iomem * reg,u32 set)1553270ac23SPurna Chandra Mandal static inline void pic32_setbits(void __iomem *reg, u32 set)
1563270ac23SPurna Chandra Mandal {
1573270ac23SPurna Chandra Mandal writel(readl(reg) | set, reg);
1583270ac23SPurna Chandra Mandal }
1593270ac23SPurna Chandra Mandal
pic32_clrbits(void __iomem * reg,u32 clr)1603270ac23SPurna Chandra Mandal static inline void pic32_clrbits(void __iomem *reg, u32 clr)
1613270ac23SPurna Chandra Mandal {
1623270ac23SPurna Chandra Mandal writel(readl(reg) & ~clr, reg);
1633270ac23SPurna Chandra Mandal }
1643270ac23SPurna Chandra Mandal
pic32_sqi_set_clk_rate(struct pic32_sqi * sqi,u32 sck)1653270ac23SPurna Chandra Mandal static int pic32_sqi_set_clk_rate(struct pic32_sqi *sqi, u32 sck)
1663270ac23SPurna Chandra Mandal {
1673270ac23SPurna Chandra Mandal u32 val, div;
1683270ac23SPurna Chandra Mandal
1693270ac23SPurna Chandra Mandal /* div = base_clk / (2 * spi_clk) */
1703270ac23SPurna Chandra Mandal div = clk_get_rate(sqi->base_clk) / (2 * sck);
1713270ac23SPurna Chandra Mandal div &= PESQI_CLKDIV;
1723270ac23SPurna Chandra Mandal
1733270ac23SPurna Chandra Mandal val = readl(sqi->regs + PESQI_CLK_CTRL_REG);
1743270ac23SPurna Chandra Mandal /* apply new divider */
1753270ac23SPurna Chandra Mandal val &= ~(PESQI_CLK_STABLE | (PESQI_CLKDIV << PESQI_CLKDIV_SHIFT));
1763270ac23SPurna Chandra Mandal val |= div << PESQI_CLKDIV_SHIFT;
1773270ac23SPurna Chandra Mandal writel(val, sqi->regs + PESQI_CLK_CTRL_REG);
1783270ac23SPurna Chandra Mandal
1793270ac23SPurna Chandra Mandal /* wait for stability */
1803270ac23SPurna Chandra Mandal return readl_poll_timeout(sqi->regs + PESQI_CLK_CTRL_REG, val,
1813270ac23SPurna Chandra Mandal val & PESQI_CLK_STABLE, 1, 5000);
1823270ac23SPurna Chandra Mandal }
1833270ac23SPurna Chandra Mandal
pic32_sqi_enable_int(struct pic32_sqi * sqi)1843270ac23SPurna Chandra Mandal static inline void pic32_sqi_enable_int(struct pic32_sqi *sqi)
1853270ac23SPurna Chandra Mandal {
1863270ac23SPurna Chandra Mandal u32 mask = PESQI_DMAERR | PESQI_BDDONE | PESQI_PKTCOMP;
1873270ac23SPurna Chandra Mandal
1883270ac23SPurna Chandra Mandal writel(mask, sqi->regs + PESQI_INT_ENABLE_REG);
1893270ac23SPurna Chandra Mandal /* INT_SIGEN works as interrupt-gate to INTR line */
1903270ac23SPurna Chandra Mandal writel(mask, sqi->regs + PESQI_INT_SIGEN_REG);
1913270ac23SPurna Chandra Mandal }
1923270ac23SPurna Chandra Mandal
pic32_sqi_disable_int(struct pic32_sqi * sqi)1933270ac23SPurna Chandra Mandal static inline void pic32_sqi_disable_int(struct pic32_sqi *sqi)
1943270ac23SPurna Chandra Mandal {
1953270ac23SPurna Chandra Mandal writel(0, sqi->regs + PESQI_INT_ENABLE_REG);
1963270ac23SPurna Chandra Mandal writel(0, sqi->regs + PESQI_INT_SIGEN_REG);
1973270ac23SPurna Chandra Mandal }
1983270ac23SPurna Chandra Mandal
pic32_sqi_isr(int irq,void * dev_id)1993270ac23SPurna Chandra Mandal static irqreturn_t pic32_sqi_isr(int irq, void *dev_id)
2003270ac23SPurna Chandra Mandal {
2013270ac23SPurna Chandra Mandal struct pic32_sqi *sqi = dev_id;
2023270ac23SPurna Chandra Mandal u32 enable, status;
2033270ac23SPurna Chandra Mandal
2043270ac23SPurna Chandra Mandal enable = readl(sqi->regs + PESQI_INT_ENABLE_REG);
2053270ac23SPurna Chandra Mandal status = readl(sqi->regs + PESQI_INT_STAT_REG);
2063270ac23SPurna Chandra Mandal
2073270ac23SPurna Chandra Mandal /* check spurious interrupt */
2083270ac23SPurna Chandra Mandal if (!status)
2093270ac23SPurna Chandra Mandal return IRQ_NONE;
2103270ac23SPurna Chandra Mandal
2113270ac23SPurna Chandra Mandal if (status & PESQI_DMAERR) {
2123270ac23SPurna Chandra Mandal enable = 0;
2133270ac23SPurna Chandra Mandal goto irq_done;
2143270ac23SPurna Chandra Mandal }
2153270ac23SPurna Chandra Mandal
2163270ac23SPurna Chandra Mandal if (status & PESQI_TXTHR)
2173270ac23SPurna Chandra Mandal enable &= ~(PESQI_TXTHR | PESQI_TXFULL | PESQI_TXEMPTY);
2183270ac23SPurna Chandra Mandal
2193270ac23SPurna Chandra Mandal if (status & PESQI_RXTHR)
2203270ac23SPurna Chandra Mandal enable &= ~(PESQI_RXTHR | PESQI_RXFULL | PESQI_RXEMPTY);
2213270ac23SPurna Chandra Mandal
2223270ac23SPurna Chandra Mandal if (status & PESQI_BDDONE)
2233270ac23SPurna Chandra Mandal enable &= ~PESQI_BDDONE;
2243270ac23SPurna Chandra Mandal
2253270ac23SPurna Chandra Mandal /* packet processing completed */
2263270ac23SPurna Chandra Mandal if (status & PESQI_PKTCOMP) {
2273270ac23SPurna Chandra Mandal /* mask all interrupts */
2283270ac23SPurna Chandra Mandal enable = 0;
2293270ac23SPurna Chandra Mandal /* complete trasaction */
2303270ac23SPurna Chandra Mandal complete(&sqi->xfer_done);
2313270ac23SPurna Chandra Mandal }
2323270ac23SPurna Chandra Mandal
2333270ac23SPurna Chandra Mandal irq_done:
2343270ac23SPurna Chandra Mandal /* interrupts are sticky, so mask when handled */
2353270ac23SPurna Chandra Mandal writel(enable, sqi->regs + PESQI_INT_ENABLE_REG);
2363270ac23SPurna Chandra Mandal
2373270ac23SPurna Chandra Mandal return IRQ_HANDLED;
2383270ac23SPurna Chandra Mandal }
2393270ac23SPurna Chandra Mandal
ring_desc_get(struct pic32_sqi * sqi)2403270ac23SPurna Chandra Mandal static struct ring_desc *ring_desc_get(struct pic32_sqi *sqi)
2413270ac23SPurna Chandra Mandal {
2423270ac23SPurna Chandra Mandal struct ring_desc *rdesc;
2433270ac23SPurna Chandra Mandal
2443270ac23SPurna Chandra Mandal if (list_empty(&sqi->bd_list_free))
2453270ac23SPurna Chandra Mandal return NULL;
2463270ac23SPurna Chandra Mandal
2473270ac23SPurna Chandra Mandal rdesc = list_first_entry(&sqi->bd_list_free, struct ring_desc, list);
248a3cfea04SWei Yongjun list_move_tail(&rdesc->list, &sqi->bd_list_used);
2493270ac23SPurna Chandra Mandal return rdesc;
2503270ac23SPurna Chandra Mandal }
2513270ac23SPurna Chandra Mandal
ring_desc_put(struct pic32_sqi * sqi,struct ring_desc * rdesc)2523270ac23SPurna Chandra Mandal static void ring_desc_put(struct pic32_sqi *sqi, struct ring_desc *rdesc)
2533270ac23SPurna Chandra Mandal {
254a3cfea04SWei Yongjun list_move(&rdesc->list, &sqi->bd_list_free);
2553270ac23SPurna Chandra Mandal }
2563270ac23SPurna Chandra Mandal
pic32_sqi_one_transfer(struct pic32_sqi * sqi,struct spi_message * mesg,struct spi_transfer * xfer)2573270ac23SPurna Chandra Mandal static int pic32_sqi_one_transfer(struct pic32_sqi *sqi,
2583270ac23SPurna Chandra Mandal struct spi_message *mesg,
2593270ac23SPurna Chandra Mandal struct spi_transfer *xfer)
2603270ac23SPurna Chandra Mandal {
2613270ac23SPurna Chandra Mandal struct spi_device *spi = mesg->spi;
2623270ac23SPurna Chandra Mandal struct scatterlist *sg, *sgl;
2633270ac23SPurna Chandra Mandal struct ring_desc *rdesc;
2643270ac23SPurna Chandra Mandal struct buf_desc *bd;
2653270ac23SPurna Chandra Mandal int nents, i;
2663270ac23SPurna Chandra Mandal u32 bd_ctrl;
2673270ac23SPurna Chandra Mandal u32 nbits;
2683270ac23SPurna Chandra Mandal
2693270ac23SPurna Chandra Mandal /* Device selection */
2709e264f3fSAmit Kumar Mahapatra via Alsa-devel bd_ctrl = spi_get_chipselect(spi, 0) << BD_DEVSEL_SHIFT;
2713270ac23SPurna Chandra Mandal
2723270ac23SPurna Chandra Mandal /* half-duplex: select transfer buffer, direction and lane */
2733270ac23SPurna Chandra Mandal if (xfer->rx_buf) {
2743270ac23SPurna Chandra Mandal bd_ctrl |= BD_DATA_RECV;
2753270ac23SPurna Chandra Mandal nbits = xfer->rx_nbits;
2763270ac23SPurna Chandra Mandal sgl = xfer->rx_sg.sgl;
2773270ac23SPurna Chandra Mandal nents = xfer->rx_sg.nents;
2783270ac23SPurna Chandra Mandal } else {
2793270ac23SPurna Chandra Mandal nbits = xfer->tx_nbits;
2803270ac23SPurna Chandra Mandal sgl = xfer->tx_sg.sgl;
2813270ac23SPurna Chandra Mandal nents = xfer->tx_sg.nents;
2823270ac23SPurna Chandra Mandal }
2833270ac23SPurna Chandra Mandal
2843270ac23SPurna Chandra Mandal if (nbits & SPI_NBITS_QUAD)
2853270ac23SPurna Chandra Mandal bd_ctrl |= BD_QUAD;
2863270ac23SPurna Chandra Mandal else if (nbits & SPI_NBITS_DUAL)
2873270ac23SPurna Chandra Mandal bd_ctrl |= BD_DUAL;
2883270ac23SPurna Chandra Mandal
2893270ac23SPurna Chandra Mandal /* LSB first */
2903270ac23SPurna Chandra Mandal if (spi->mode & SPI_LSB_FIRST)
2913270ac23SPurna Chandra Mandal bd_ctrl |= BD_LSBF;
2923270ac23SPurna Chandra Mandal
2933270ac23SPurna Chandra Mandal /* ownership to hardware */
2943270ac23SPurna Chandra Mandal bd_ctrl |= BD_EN;
2953270ac23SPurna Chandra Mandal
2963270ac23SPurna Chandra Mandal for_each_sg(sgl, sg, nents, i) {
2973270ac23SPurna Chandra Mandal /* get ring descriptor */
2983270ac23SPurna Chandra Mandal rdesc = ring_desc_get(sqi);
2993270ac23SPurna Chandra Mandal if (!rdesc)
3003270ac23SPurna Chandra Mandal break;
3013270ac23SPurna Chandra Mandal
3023270ac23SPurna Chandra Mandal bd = rdesc->bd;
3033270ac23SPurna Chandra Mandal
3043270ac23SPurna Chandra Mandal /* BD CTRL: length */
3053270ac23SPurna Chandra Mandal rdesc->xfer_len = sg_dma_len(sg);
3063270ac23SPurna Chandra Mandal bd->bd_ctrl = bd_ctrl;
3073270ac23SPurna Chandra Mandal bd->bd_ctrl |= rdesc->xfer_len;
3083270ac23SPurna Chandra Mandal
3093270ac23SPurna Chandra Mandal /* BD STAT */
3103270ac23SPurna Chandra Mandal bd->bd_status = 0;
3113270ac23SPurna Chandra Mandal
3123270ac23SPurna Chandra Mandal /* BD BUFFER ADDRESS */
3133270ac23SPurna Chandra Mandal bd->bd_addr = sg->dma_address;
3143270ac23SPurna Chandra Mandal }
3153270ac23SPurna Chandra Mandal
3163270ac23SPurna Chandra Mandal return 0;
3173270ac23SPurna Chandra Mandal }
3183270ac23SPurna Chandra Mandal
pic32_sqi_prepare_hardware(struct spi_controller * host)319*cc64ab49SYang Yingliang static int pic32_sqi_prepare_hardware(struct spi_controller *host)
3203270ac23SPurna Chandra Mandal {
321*cc64ab49SYang Yingliang struct pic32_sqi *sqi = spi_controller_get_devdata(host);
3223270ac23SPurna Chandra Mandal
3233270ac23SPurna Chandra Mandal /* enable spi interface */
3243270ac23SPurna Chandra Mandal pic32_setbits(sqi->regs + PESQI_CONF_REG, PESQI_EN);
3253270ac23SPurna Chandra Mandal /* enable spi clk */
3263270ac23SPurna Chandra Mandal pic32_setbits(sqi->regs + PESQI_CLK_CTRL_REG, PESQI_CLK_EN);
3273270ac23SPurna Chandra Mandal
3283270ac23SPurna Chandra Mandal return 0;
3293270ac23SPurna Chandra Mandal }
3303270ac23SPurna Chandra Mandal
pic32_sqi_can_dma(struct spi_controller * host,struct spi_device * spi,struct spi_transfer * x)331*cc64ab49SYang Yingliang static bool pic32_sqi_can_dma(struct spi_controller *host,
3323270ac23SPurna Chandra Mandal struct spi_device *spi,
3333270ac23SPurna Chandra Mandal struct spi_transfer *x)
3343270ac23SPurna Chandra Mandal {
3353270ac23SPurna Chandra Mandal /* Do DMA irrespective of transfer size */
3363270ac23SPurna Chandra Mandal return true;
3373270ac23SPurna Chandra Mandal }
3383270ac23SPurna Chandra Mandal
pic32_sqi_one_message(struct spi_controller * host,struct spi_message * msg)339*cc64ab49SYang Yingliang static int pic32_sqi_one_message(struct spi_controller *host,
3403270ac23SPurna Chandra Mandal struct spi_message *msg)
3413270ac23SPurna Chandra Mandal {
3423270ac23SPurna Chandra Mandal struct spi_device *spi = msg->spi;
3433270ac23SPurna Chandra Mandal struct ring_desc *rdesc, *next;
3443270ac23SPurna Chandra Mandal struct spi_transfer *xfer;
3453270ac23SPurna Chandra Mandal struct pic32_sqi *sqi;
3463270ac23SPurna Chandra Mandal int ret = 0, mode;
34733d5097dSNicholas Mc Guire unsigned long timeout;
3483270ac23SPurna Chandra Mandal u32 val;
3493270ac23SPurna Chandra Mandal
350*cc64ab49SYang Yingliang sqi = spi_controller_get_devdata(host);
3513270ac23SPurna Chandra Mandal
3523270ac23SPurna Chandra Mandal reinit_completion(&sqi->xfer_done);
3533270ac23SPurna Chandra Mandal msg->actual_length = 0;
3543270ac23SPurna Chandra Mandal
3553270ac23SPurna Chandra Mandal /* We can't handle spi_transfer specific "speed_hz", "bits_per_word"
3563270ac23SPurna Chandra Mandal * and "delay_usecs". But spi_device specific speed and mode change
3573270ac23SPurna Chandra Mandal * can be handled at best during spi chip-select switch.
3583270ac23SPurna Chandra Mandal */
3593270ac23SPurna Chandra Mandal if (sqi->cur_spi != spi) {
3603270ac23SPurna Chandra Mandal /* set spi speed */
3613270ac23SPurna Chandra Mandal if (sqi->cur_speed != spi->max_speed_hz) {
3623270ac23SPurna Chandra Mandal sqi->cur_speed = spi->max_speed_hz;
3633270ac23SPurna Chandra Mandal ret = pic32_sqi_set_clk_rate(sqi, spi->max_speed_hz);
3643270ac23SPurna Chandra Mandal if (ret)
3653270ac23SPurna Chandra Mandal dev_warn(&spi->dev, "set_clk, %d\n", ret);
3663270ac23SPurna Chandra Mandal }
3673270ac23SPurna Chandra Mandal
3683270ac23SPurna Chandra Mandal /* set spi mode */
3693270ac23SPurna Chandra Mandal mode = spi->mode & (SPI_MODE_3 | SPI_LSB_FIRST);
3703270ac23SPurna Chandra Mandal if (sqi->cur_mode != mode) {
3713270ac23SPurna Chandra Mandal val = readl(sqi->regs + PESQI_CONF_REG);
3723270ac23SPurna Chandra Mandal val &= ~(PESQI_CPOL | PESQI_CPHA | PESQI_LSBF);
3733270ac23SPurna Chandra Mandal if (mode & SPI_CPOL)
3743270ac23SPurna Chandra Mandal val |= PESQI_CPOL;
3753270ac23SPurna Chandra Mandal if (mode & SPI_LSB_FIRST)
3763270ac23SPurna Chandra Mandal val |= PESQI_LSBF;
3773270ac23SPurna Chandra Mandal val |= PESQI_CPHA;
3783270ac23SPurna Chandra Mandal writel(val, sqi->regs + PESQI_CONF_REG);
3793270ac23SPurna Chandra Mandal
3803270ac23SPurna Chandra Mandal sqi->cur_mode = mode;
3813270ac23SPurna Chandra Mandal }
3823270ac23SPurna Chandra Mandal sqi->cur_spi = spi;
3833270ac23SPurna Chandra Mandal }
3843270ac23SPurna Chandra Mandal
3853270ac23SPurna Chandra Mandal /* prepare hardware desc-list(BD) for transfer(s) */
3863270ac23SPurna Chandra Mandal list_for_each_entry(xfer, &msg->transfers, transfer_list) {
3873270ac23SPurna Chandra Mandal ret = pic32_sqi_one_transfer(sqi, msg, xfer);
3883270ac23SPurna Chandra Mandal if (ret) {
3893270ac23SPurna Chandra Mandal dev_err(&spi->dev, "xfer %p err\n", xfer);
3903270ac23SPurna Chandra Mandal goto xfer_out;
3913270ac23SPurna Chandra Mandal }
3923270ac23SPurna Chandra Mandal }
3933270ac23SPurna Chandra Mandal
3943270ac23SPurna Chandra Mandal /* BDs are prepared and chained. Now mark LAST_BD, CS_DEASSERT at last
3953270ac23SPurna Chandra Mandal * element of the list.
3963270ac23SPurna Chandra Mandal */
3973270ac23SPurna Chandra Mandal rdesc = list_last_entry(&sqi->bd_list_used, struct ring_desc, list);
3983270ac23SPurna Chandra Mandal rdesc->bd->bd_ctrl |= BD_LAST | BD_CS_DEASSERT |
3993270ac23SPurna Chandra Mandal BD_LIFM | BD_PKT_INT_EN;
4003270ac23SPurna Chandra Mandal
4013270ac23SPurna Chandra Mandal /* set base address BD list for DMA engine */
4023270ac23SPurna Chandra Mandal rdesc = list_first_entry(&sqi->bd_list_used, struct ring_desc, list);
4033270ac23SPurna Chandra Mandal writel(rdesc->bd_dma, sqi->regs + PESQI_BD_BASE_ADDR_REG);
4043270ac23SPurna Chandra Mandal
4053270ac23SPurna Chandra Mandal /* enable interrupt */
4063270ac23SPurna Chandra Mandal pic32_sqi_enable_int(sqi);
4073270ac23SPurna Chandra Mandal
4083270ac23SPurna Chandra Mandal /* enable DMA engine */
4093270ac23SPurna Chandra Mandal val = PESQI_DMA_EN | PESQI_POLL_EN | PESQI_BDP_START;
4103270ac23SPurna Chandra Mandal writel(val, sqi->regs + PESQI_BD_CTRL_REG);
4113270ac23SPurna Chandra Mandal
4123270ac23SPurna Chandra Mandal /* wait for xfer completion */
41333d5097dSNicholas Mc Guire timeout = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ);
41433d5097dSNicholas Mc Guire if (timeout == 0) {
415*cc64ab49SYang Yingliang dev_err(&sqi->host->dev, "wait timedout/interrupted\n");
41633d5097dSNicholas Mc Guire ret = -ETIMEDOUT;
4173270ac23SPurna Chandra Mandal msg->status = ret;
4183270ac23SPurna Chandra Mandal } else {
4193270ac23SPurna Chandra Mandal /* success */
4203270ac23SPurna Chandra Mandal msg->status = 0;
4213270ac23SPurna Chandra Mandal ret = 0;
4223270ac23SPurna Chandra Mandal }
4233270ac23SPurna Chandra Mandal
4243270ac23SPurna Chandra Mandal /* disable DMA */
4253270ac23SPurna Chandra Mandal writel(0, sqi->regs + PESQI_BD_CTRL_REG);
4263270ac23SPurna Chandra Mandal
4273270ac23SPurna Chandra Mandal pic32_sqi_disable_int(sqi);
4283270ac23SPurna Chandra Mandal
4293270ac23SPurna Chandra Mandal xfer_out:
4303270ac23SPurna Chandra Mandal list_for_each_entry_safe_reverse(rdesc, next,
4313270ac23SPurna Chandra Mandal &sqi->bd_list_used, list) {
4323270ac23SPurna Chandra Mandal /* Update total byte transferred */
4333270ac23SPurna Chandra Mandal msg->actual_length += rdesc->xfer_len;
4343270ac23SPurna Chandra Mandal /* release ring descr */
4353270ac23SPurna Chandra Mandal ring_desc_put(sqi, rdesc);
4363270ac23SPurna Chandra Mandal }
437*cc64ab49SYang Yingliang spi_finalize_current_message(spi->controller);
4383270ac23SPurna Chandra Mandal
4393270ac23SPurna Chandra Mandal return ret;
4403270ac23SPurna Chandra Mandal }
4413270ac23SPurna Chandra Mandal
pic32_sqi_unprepare_hardware(struct spi_controller * host)442*cc64ab49SYang Yingliang static int pic32_sqi_unprepare_hardware(struct spi_controller *host)
4433270ac23SPurna Chandra Mandal {
444*cc64ab49SYang Yingliang struct pic32_sqi *sqi = spi_controller_get_devdata(host);
4453270ac23SPurna Chandra Mandal
4463270ac23SPurna Chandra Mandal /* disable clk */
4473270ac23SPurna Chandra Mandal pic32_clrbits(sqi->regs + PESQI_CLK_CTRL_REG, PESQI_CLK_EN);
4483270ac23SPurna Chandra Mandal /* disable spi */
4493270ac23SPurna Chandra Mandal pic32_clrbits(sqi->regs + PESQI_CONF_REG, PESQI_EN);
4503270ac23SPurna Chandra Mandal
4513270ac23SPurna Chandra Mandal return 0;
4523270ac23SPurna Chandra Mandal }
4533270ac23SPurna Chandra Mandal
ring_desc_ring_alloc(struct pic32_sqi * sqi)4543270ac23SPurna Chandra Mandal static int ring_desc_ring_alloc(struct pic32_sqi *sqi)
4553270ac23SPurna Chandra Mandal {
4563270ac23SPurna Chandra Mandal struct ring_desc *rdesc;
4573270ac23SPurna Chandra Mandal struct buf_desc *bd;
4583270ac23SPurna Chandra Mandal int i;
4593270ac23SPurna Chandra Mandal
4603270ac23SPurna Chandra Mandal /* allocate coherent DMAable memory for hardware buffer descriptors. */
461*cc64ab49SYang Yingliang sqi->bd = dma_alloc_coherent(&sqi->host->dev,
4623270ac23SPurna Chandra Mandal sizeof(*bd) * PESQI_BD_COUNT,
463ec506e92SChristoph Hellwig &sqi->bd_dma, GFP_KERNEL);
4643270ac23SPurna Chandra Mandal if (!sqi->bd) {
465*cc64ab49SYang Yingliang dev_err(&sqi->host->dev, "failed allocating dma buffer\n");
4663270ac23SPurna Chandra Mandal return -ENOMEM;
4673270ac23SPurna Chandra Mandal }
4683270ac23SPurna Chandra Mandal
4693270ac23SPurna Chandra Mandal /* allocate software ring descriptors */
4703270ac23SPurna Chandra Mandal sqi->ring = kcalloc(PESQI_BD_COUNT, sizeof(*rdesc), GFP_KERNEL);
4713270ac23SPurna Chandra Mandal if (!sqi->ring) {
472*cc64ab49SYang Yingliang dma_free_coherent(&sqi->host->dev,
4733270ac23SPurna Chandra Mandal sizeof(*bd) * PESQI_BD_COUNT,
4743270ac23SPurna Chandra Mandal sqi->bd, sqi->bd_dma);
4753270ac23SPurna Chandra Mandal return -ENOMEM;
4763270ac23SPurna Chandra Mandal }
4773270ac23SPurna Chandra Mandal
4783270ac23SPurna Chandra Mandal bd = (struct buf_desc *)sqi->bd;
4793270ac23SPurna Chandra Mandal
4803270ac23SPurna Chandra Mandal INIT_LIST_HEAD(&sqi->bd_list_free);
4813270ac23SPurna Chandra Mandal INIT_LIST_HEAD(&sqi->bd_list_used);
4823270ac23SPurna Chandra Mandal
4833270ac23SPurna Chandra Mandal /* initialize ring-desc */
4843270ac23SPurna Chandra Mandal for (i = 0, rdesc = sqi->ring; i < PESQI_BD_COUNT; i++, rdesc++) {
4853270ac23SPurna Chandra Mandal INIT_LIST_HEAD(&rdesc->list);
4863270ac23SPurna Chandra Mandal rdesc->bd = &bd[i];
4873270ac23SPurna Chandra Mandal rdesc->bd_dma = sqi->bd_dma + (void *)&bd[i] - (void *)bd;
4883270ac23SPurna Chandra Mandal list_add_tail(&rdesc->list, &sqi->bd_list_free);
4893270ac23SPurna Chandra Mandal }
4903270ac23SPurna Chandra Mandal
4913270ac23SPurna Chandra Mandal /* Prepare BD: chain to next BD(s) */
492989ffc7bSDan Carpenter for (i = 0, rdesc = sqi->ring; i < PESQI_BD_COUNT - 1; i++)
4933270ac23SPurna Chandra Mandal bd[i].bd_nextp = rdesc[i + 1].bd_dma;
4943270ac23SPurna Chandra Mandal bd[PESQI_BD_COUNT - 1].bd_nextp = 0;
4953270ac23SPurna Chandra Mandal
4963270ac23SPurna Chandra Mandal return 0;
4973270ac23SPurna Chandra Mandal }
4983270ac23SPurna Chandra Mandal
ring_desc_ring_free(struct pic32_sqi * sqi)4993270ac23SPurna Chandra Mandal static void ring_desc_ring_free(struct pic32_sqi *sqi)
5003270ac23SPurna Chandra Mandal {
501*cc64ab49SYang Yingliang dma_free_coherent(&sqi->host->dev,
5023270ac23SPurna Chandra Mandal sizeof(struct buf_desc) * PESQI_BD_COUNT,
5033270ac23SPurna Chandra Mandal sqi->bd, sqi->bd_dma);
5043270ac23SPurna Chandra Mandal kfree(sqi->ring);
5053270ac23SPurna Chandra Mandal }
5063270ac23SPurna Chandra Mandal
pic32_sqi_hw_init(struct pic32_sqi * sqi)5073270ac23SPurna Chandra Mandal static void pic32_sqi_hw_init(struct pic32_sqi *sqi)
5083270ac23SPurna Chandra Mandal {
5093270ac23SPurna Chandra Mandal unsigned long flags;
5103270ac23SPurna Chandra Mandal u32 val;
5113270ac23SPurna Chandra Mandal
5123270ac23SPurna Chandra Mandal /* Soft-reset of PESQI controller triggers interrupt.
5133270ac23SPurna Chandra Mandal * We are not yet ready to handle them so disable CPU
5143270ac23SPurna Chandra Mandal * interrupt for the time being.
5153270ac23SPurna Chandra Mandal */
5163270ac23SPurna Chandra Mandal local_irq_save(flags);
5173270ac23SPurna Chandra Mandal
5183270ac23SPurna Chandra Mandal /* assert soft-reset */
5193270ac23SPurna Chandra Mandal writel(PESQI_SOFT_RESET, sqi->regs + PESQI_CONF_REG);
5203270ac23SPurna Chandra Mandal
5213270ac23SPurna Chandra Mandal /* wait until clear */
5223270ac23SPurna Chandra Mandal readl_poll_timeout_atomic(sqi->regs + PESQI_CONF_REG, val,
5233270ac23SPurna Chandra Mandal !(val & PESQI_SOFT_RESET), 1, 5000);
5243270ac23SPurna Chandra Mandal
5253270ac23SPurna Chandra Mandal /* disable all interrupts */
5263270ac23SPurna Chandra Mandal pic32_sqi_disable_int(sqi);
5273270ac23SPurna Chandra Mandal
5283270ac23SPurna Chandra Mandal /* Now it is safe to enable back CPU interrupt */
5293270ac23SPurna Chandra Mandal local_irq_restore(flags);
5303270ac23SPurna Chandra Mandal
5313270ac23SPurna Chandra Mandal /* tx and rx fifo interrupt threshold */
5323270ac23SPurna Chandra Mandal val = readl(sqi->regs + PESQI_CMD_THRES_REG);
5333270ac23SPurna Chandra Mandal val &= ~(PESQI_TXTHR_MASK << PESQI_TXTHR_SHIFT);
5343270ac23SPurna Chandra Mandal val &= ~(PESQI_RXTHR_MASK << PESQI_RXTHR_SHIFT);
5353270ac23SPurna Chandra Mandal val |= (1U << PESQI_TXTHR_SHIFT) | (1U << PESQI_RXTHR_SHIFT);
5363270ac23SPurna Chandra Mandal writel(val, sqi->regs + PESQI_CMD_THRES_REG);
5373270ac23SPurna Chandra Mandal
5383270ac23SPurna Chandra Mandal val = readl(sqi->regs + PESQI_INT_THRES_REG);
5393270ac23SPurna Chandra Mandal val &= ~(PESQI_TXTHR_MASK << PESQI_TXTHR_SHIFT);
5403270ac23SPurna Chandra Mandal val &= ~(PESQI_RXTHR_MASK << PESQI_RXTHR_SHIFT);
5413270ac23SPurna Chandra Mandal val |= (1U << PESQI_TXTHR_SHIFT) | (1U << PESQI_RXTHR_SHIFT);
5423270ac23SPurna Chandra Mandal writel(val, sqi->regs + PESQI_INT_THRES_REG);
5433270ac23SPurna Chandra Mandal
5443270ac23SPurna Chandra Mandal /* default configuration */
5453270ac23SPurna Chandra Mandal val = readl(sqi->regs + PESQI_CONF_REG);
5463270ac23SPurna Chandra Mandal
5473270ac23SPurna Chandra Mandal /* set mode: DMA */
5483270ac23SPurna Chandra Mandal val &= ~PESQI_MODE;
5493270ac23SPurna Chandra Mandal val |= PESQI_MODE_DMA << PESQI_MODE_SHIFT;
5503270ac23SPurna Chandra Mandal writel(val, sqi->regs + PESQI_CONF_REG);
5513270ac23SPurna Chandra Mandal
5523270ac23SPurna Chandra Mandal /* DATAEN - SQIID0-ID3 */
5533270ac23SPurna Chandra Mandal val |= PESQI_QUAD_LANE << PESQI_LANES_SHIFT;
5543270ac23SPurna Chandra Mandal
5553270ac23SPurna Chandra Mandal /* burst/INCR4 enable */
5563270ac23SPurna Chandra Mandal val |= PESQI_BURST_EN;
5573270ac23SPurna Chandra Mandal
5583270ac23SPurna Chandra Mandal /* CSEN - all CS */
5593270ac23SPurna Chandra Mandal val |= 3U << PESQI_CSEN_SHIFT;
5603270ac23SPurna Chandra Mandal writel(val, sqi->regs + PESQI_CONF_REG);
5613270ac23SPurna Chandra Mandal
5623270ac23SPurna Chandra Mandal /* write poll count */
5633270ac23SPurna Chandra Mandal writel(0, sqi->regs + PESQI_BD_POLL_CTRL_REG);
5643270ac23SPurna Chandra Mandal
5653270ac23SPurna Chandra Mandal sqi->cur_speed = 0;
5663270ac23SPurna Chandra Mandal sqi->cur_mode = -1;
5673270ac23SPurna Chandra Mandal }
5683270ac23SPurna Chandra Mandal
pic32_sqi_probe(struct platform_device * pdev)5693270ac23SPurna Chandra Mandal static int pic32_sqi_probe(struct platform_device *pdev)
5703270ac23SPurna Chandra Mandal {
571*cc64ab49SYang Yingliang struct spi_controller *host;
5723270ac23SPurna Chandra Mandal struct pic32_sqi *sqi;
5733270ac23SPurna Chandra Mandal int ret;
5743270ac23SPurna Chandra Mandal
575*cc64ab49SYang Yingliang host = spi_alloc_host(&pdev->dev, sizeof(*sqi));
576*cc64ab49SYang Yingliang if (!host)
5773270ac23SPurna Chandra Mandal return -ENOMEM;
5783270ac23SPurna Chandra Mandal
579*cc64ab49SYang Yingliang sqi = spi_controller_get_devdata(host);
580*cc64ab49SYang Yingliang sqi->host = host;
5813270ac23SPurna Chandra Mandal
582e751032bSYueHaibing sqi->regs = devm_platform_ioremap_resource(pdev, 0);
5833270ac23SPurna Chandra Mandal if (IS_ERR(sqi->regs)) {
5843270ac23SPurna Chandra Mandal ret = PTR_ERR(sqi->regs);
585*cc64ab49SYang Yingliang goto err_free_host;
5863270ac23SPurna Chandra Mandal }
5873270ac23SPurna Chandra Mandal
5883270ac23SPurna Chandra Mandal /* irq */
5893270ac23SPurna Chandra Mandal sqi->irq = platform_get_irq(pdev, 0);
5903270ac23SPurna Chandra Mandal if (sqi->irq < 0) {
5913270ac23SPurna Chandra Mandal ret = sqi->irq;
592*cc64ab49SYang Yingliang goto err_free_host;
5933270ac23SPurna Chandra Mandal }
5943270ac23SPurna Chandra Mandal
5953270ac23SPurna Chandra Mandal /* clocks */
5963270ac23SPurna Chandra Mandal sqi->sys_clk = devm_clk_get(&pdev->dev, "reg_ck");
5973270ac23SPurna Chandra Mandal if (IS_ERR(sqi->sys_clk)) {
5983270ac23SPurna Chandra Mandal ret = PTR_ERR(sqi->sys_clk);
5993270ac23SPurna Chandra Mandal dev_err(&pdev->dev, "no sys_clk ?\n");
600*cc64ab49SYang Yingliang goto err_free_host;
6013270ac23SPurna Chandra Mandal }
6023270ac23SPurna Chandra Mandal
6033270ac23SPurna Chandra Mandal sqi->base_clk = devm_clk_get(&pdev->dev, "spi_ck");
6043270ac23SPurna Chandra Mandal if (IS_ERR(sqi->base_clk)) {
6053270ac23SPurna Chandra Mandal ret = PTR_ERR(sqi->base_clk);
6063270ac23SPurna Chandra Mandal dev_err(&pdev->dev, "no base clk ?\n");
607*cc64ab49SYang Yingliang goto err_free_host;
6083270ac23SPurna Chandra Mandal }
6093270ac23SPurna Chandra Mandal
6103270ac23SPurna Chandra Mandal ret = clk_prepare_enable(sqi->sys_clk);
6113270ac23SPurna Chandra Mandal if (ret) {
6123270ac23SPurna Chandra Mandal dev_err(&pdev->dev, "sys clk enable failed\n");
613*cc64ab49SYang Yingliang goto err_free_host;
6143270ac23SPurna Chandra Mandal }
6153270ac23SPurna Chandra Mandal
6163270ac23SPurna Chandra Mandal ret = clk_prepare_enable(sqi->base_clk);
6173270ac23SPurna Chandra Mandal if (ret) {
6183270ac23SPurna Chandra Mandal dev_err(&pdev->dev, "base clk enable failed\n");
6193270ac23SPurna Chandra Mandal clk_disable_unprepare(sqi->sys_clk);
620*cc64ab49SYang Yingliang goto err_free_host;
6213270ac23SPurna Chandra Mandal }
6223270ac23SPurna Chandra Mandal
6233270ac23SPurna Chandra Mandal init_completion(&sqi->xfer_done);
6243270ac23SPurna Chandra Mandal
6253270ac23SPurna Chandra Mandal /* initialize hardware */
6263270ac23SPurna Chandra Mandal pic32_sqi_hw_init(sqi);
6273270ac23SPurna Chandra Mandal
6283270ac23SPurna Chandra Mandal /* allocate buffers & descriptors */
6293270ac23SPurna Chandra Mandal ret = ring_desc_ring_alloc(sqi);
6303270ac23SPurna Chandra Mandal if (ret) {
6313270ac23SPurna Chandra Mandal dev_err(&pdev->dev, "ring alloc failed\n");
6323270ac23SPurna Chandra Mandal goto err_disable_clk;
6333270ac23SPurna Chandra Mandal }
6343270ac23SPurna Chandra Mandal
6353270ac23SPurna Chandra Mandal /* install irq handlers */
6363270ac23SPurna Chandra Mandal ret = request_irq(sqi->irq, pic32_sqi_isr, 0,
6373270ac23SPurna Chandra Mandal dev_name(&pdev->dev), sqi);
6383270ac23SPurna Chandra Mandal if (ret < 0) {
6393270ac23SPurna Chandra Mandal dev_err(&pdev->dev, "request_irq(%d), failed\n", sqi->irq);
6403270ac23SPurna Chandra Mandal goto err_free_ring;
6413270ac23SPurna Chandra Mandal }
6423270ac23SPurna Chandra Mandal
643*cc64ab49SYang Yingliang /* register host */
644*cc64ab49SYang Yingliang host->num_chipselect = 2;
645*cc64ab49SYang Yingliang host->max_speed_hz = clk_get_rate(sqi->base_clk);
646*cc64ab49SYang Yingliang host->dma_alignment = 32;
647*cc64ab49SYang Yingliang host->max_dma_len = PESQI_BD_BUF_LEN_MAX;
648*cc64ab49SYang Yingliang host->dev.of_node = pdev->dev.of_node;
649*cc64ab49SYang Yingliang host->mode_bits = SPI_MODE_3 | SPI_MODE_0 | SPI_TX_DUAL |
6503270ac23SPurna Chandra Mandal SPI_RX_DUAL | SPI_TX_QUAD | SPI_RX_QUAD;
651*cc64ab49SYang Yingliang host->flags = SPI_CONTROLLER_HALF_DUPLEX;
652*cc64ab49SYang Yingliang host->can_dma = pic32_sqi_can_dma;
653*cc64ab49SYang Yingliang host->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
654*cc64ab49SYang Yingliang host->transfer_one_message = pic32_sqi_one_message;
655*cc64ab49SYang Yingliang host->prepare_transfer_hardware = pic32_sqi_prepare_hardware;
656*cc64ab49SYang Yingliang host->unprepare_transfer_hardware = pic32_sqi_unprepare_hardware;
6573270ac23SPurna Chandra Mandal
658*cc64ab49SYang Yingliang ret = devm_spi_register_controller(&pdev->dev, host);
6593270ac23SPurna Chandra Mandal if (ret) {
660*cc64ab49SYang Yingliang dev_err(&host->dev, "failed registering spi host\n");
6613270ac23SPurna Chandra Mandal free_irq(sqi->irq, sqi);
6623270ac23SPurna Chandra Mandal goto err_free_ring;
6633270ac23SPurna Chandra Mandal }
6643270ac23SPurna Chandra Mandal
6653270ac23SPurna Chandra Mandal platform_set_drvdata(pdev, sqi);
6663270ac23SPurna Chandra Mandal
6673270ac23SPurna Chandra Mandal return 0;
6683270ac23SPurna Chandra Mandal
6693270ac23SPurna Chandra Mandal err_free_ring:
6703270ac23SPurna Chandra Mandal ring_desc_ring_free(sqi);
6713270ac23SPurna Chandra Mandal
6723270ac23SPurna Chandra Mandal err_disable_clk:
6733270ac23SPurna Chandra Mandal clk_disable_unprepare(sqi->base_clk);
6743270ac23SPurna Chandra Mandal clk_disable_unprepare(sqi->sys_clk);
6753270ac23SPurna Chandra Mandal
676*cc64ab49SYang Yingliang err_free_host:
677*cc64ab49SYang Yingliang spi_controller_put(host);
6783270ac23SPurna Chandra Mandal return ret;
6793270ac23SPurna Chandra Mandal }
6803270ac23SPurna Chandra Mandal
pic32_sqi_remove(struct platform_device * pdev)681503425edSUwe Kleine-König static void pic32_sqi_remove(struct platform_device *pdev)
6823270ac23SPurna Chandra Mandal {
6833270ac23SPurna Chandra Mandal struct pic32_sqi *sqi = platform_get_drvdata(pdev);
6843270ac23SPurna Chandra Mandal
6853270ac23SPurna Chandra Mandal /* release resources */
6863270ac23SPurna Chandra Mandal free_irq(sqi->irq, sqi);
6873270ac23SPurna Chandra Mandal ring_desc_ring_free(sqi);
6883270ac23SPurna Chandra Mandal
6893270ac23SPurna Chandra Mandal /* disable clk */
6903270ac23SPurna Chandra Mandal clk_disable_unprepare(sqi->base_clk);
6913270ac23SPurna Chandra Mandal clk_disable_unprepare(sqi->sys_clk);
6923270ac23SPurna Chandra Mandal }
6933270ac23SPurna Chandra Mandal
6943270ac23SPurna Chandra Mandal static const struct of_device_id pic32_sqi_of_ids[] = {
6953270ac23SPurna Chandra Mandal {.compatible = "microchip,pic32mzda-sqi",},
6963270ac23SPurna Chandra Mandal {},
6973270ac23SPurna Chandra Mandal };
6983270ac23SPurna Chandra Mandal MODULE_DEVICE_TABLE(of, pic32_sqi_of_ids);
6993270ac23SPurna Chandra Mandal
7003270ac23SPurna Chandra Mandal static struct platform_driver pic32_sqi_driver = {
7013270ac23SPurna Chandra Mandal .driver = {
7023270ac23SPurna Chandra Mandal .name = "sqi-pic32",
7033270ac23SPurna Chandra Mandal .of_match_table = of_match_ptr(pic32_sqi_of_ids),
7043270ac23SPurna Chandra Mandal },
7053270ac23SPurna Chandra Mandal .probe = pic32_sqi_probe,
706503425edSUwe Kleine-König .remove_new = pic32_sqi_remove,
7073270ac23SPurna Chandra Mandal };
7083270ac23SPurna Chandra Mandal
7093270ac23SPurna Chandra Mandal module_platform_driver(pic32_sqi_driver);
7103270ac23SPurna Chandra Mandal
7113270ac23SPurna Chandra Mandal MODULE_AUTHOR("Purna Chandra Mandal <purna.mandal@microchip.com>");
7123270ac23SPurna Chandra Mandal MODULE_DESCRIPTION("Microchip SPI driver for PIC32 SQI controller.");
7133270ac23SPurna Chandra Mandal MODULE_LICENSE("GPL v2");
714