xref: /openbmc/linux/drivers/spi/spi-pic32-sqi.c (revision cc64ab49)
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