| /* | 
 |  * PIC32 Quad SPI controller driver. | 
 |  * | 
 |  * Purna Chandra Mandal <purna.mandal@microchip.com> | 
 |  * Copyright (c) 2016, Microchip Technology Inc. | 
 |  * | 
 |  * This program is free software; you can distribute it and/or modify it | 
 |  * under the terms of the GNU General Public License (Version 2) as | 
 |  * published by the Free Software Foundation. | 
 |  * | 
 |  * This program is distributed in the hope it will be useful, but WITHOUT | 
 |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
 |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
 |  * for more details. | 
 |  */ | 
 |  | 
 | #include <linux/clk.h> | 
 | #include <linux/dma-mapping.h> | 
 | #include <linux/interrupt.h> | 
 | #include <linux/io.h> | 
 | #include <linux/iopoll.h> | 
 | #include <linux/module.h> | 
 | #include <linux/of.h> | 
 | #include <linux/platform_device.h> | 
 | #include <linux/slab.h> | 
 | #include <linux/spi/spi.h> | 
 |  | 
 | /* SQI registers */ | 
 | #define PESQI_XIP_CONF1_REG	0x00 | 
 | #define PESQI_XIP_CONF2_REG	0x04 | 
 | #define PESQI_CONF_REG		0x08 | 
 | #define PESQI_CTRL_REG		0x0C | 
 | #define PESQI_CLK_CTRL_REG	0x10 | 
 | #define PESQI_CMD_THRES_REG	0x14 | 
 | #define PESQI_INT_THRES_REG	0x18 | 
 | #define PESQI_INT_ENABLE_REG	0x1C | 
 | #define PESQI_INT_STAT_REG	0x20 | 
 | #define PESQI_TX_DATA_REG	0x24 | 
 | #define PESQI_RX_DATA_REG	0x28 | 
 | #define PESQI_STAT1_REG		0x2C | 
 | #define PESQI_STAT2_REG		0x30 | 
 | #define PESQI_BD_CTRL_REG	0x34 | 
 | #define PESQI_BD_CUR_ADDR_REG	0x38 | 
 | #define PESQI_BD_BASE_ADDR_REG	0x40 | 
 | #define PESQI_BD_STAT_REG	0x44 | 
 | #define PESQI_BD_POLL_CTRL_REG	0x48 | 
 | #define PESQI_BD_TX_DMA_STAT_REG	0x4C | 
 | #define PESQI_BD_RX_DMA_STAT_REG	0x50 | 
 | #define PESQI_THRES_REG		0x54 | 
 | #define PESQI_INT_SIGEN_REG	0x58 | 
 |  | 
 | /* PESQI_CONF_REG fields */ | 
 | #define PESQI_MODE		0x7 | 
 | #define  PESQI_MODE_BOOT	0 | 
 | #define  PESQI_MODE_PIO		1 | 
 | #define  PESQI_MODE_DMA		2 | 
 | #define  PESQI_MODE_XIP		3 | 
 | #define PESQI_MODE_SHIFT	0 | 
 | #define PESQI_CPHA		BIT(3) | 
 | #define PESQI_CPOL		BIT(4) | 
 | #define PESQI_LSBF		BIT(5) | 
 | #define PESQI_RXLATCH		BIT(7) | 
 | #define PESQI_SERMODE		BIT(8) | 
 | #define PESQI_WP_EN		BIT(9) | 
 | #define PESQI_HOLD_EN		BIT(10) | 
 | #define PESQI_BURST_EN		BIT(12) | 
 | #define PESQI_CS_CTRL_HW	BIT(15) | 
 | #define PESQI_SOFT_RESET	BIT(16) | 
 | #define PESQI_LANES_SHIFT	20 | 
 | #define  PESQI_SINGLE_LANE	0 | 
 | #define  PESQI_DUAL_LANE	1 | 
 | #define  PESQI_QUAD_LANE	2 | 
 | #define PESQI_CSEN_SHIFT	24 | 
 | #define PESQI_EN		BIT(23) | 
 |  | 
 | /* PESQI_CLK_CTRL_REG fields */ | 
 | #define PESQI_CLK_EN		BIT(0) | 
 | #define PESQI_CLK_STABLE	BIT(1) | 
 | #define PESQI_CLKDIV_SHIFT	8 | 
 | #define PESQI_CLKDIV		0xff | 
 |  | 
 | /* PESQI_INT_THR/CMD_THR_REG */ | 
 | #define PESQI_TXTHR_MASK	0x1f | 
 | #define PESQI_TXTHR_SHIFT	8 | 
 | #define PESQI_RXTHR_MASK	0x1f | 
 | #define PESQI_RXTHR_SHIFT	0 | 
 |  | 
 | /* PESQI_INT_EN/INT_STAT/INT_SIG_EN_REG */ | 
 | #define PESQI_TXEMPTY		BIT(0) | 
 | #define PESQI_TXFULL		BIT(1) | 
 | #define PESQI_TXTHR		BIT(2) | 
 | #define PESQI_RXEMPTY		BIT(3) | 
 | #define PESQI_RXFULL		BIT(4) | 
 | #define PESQI_RXTHR		BIT(5) | 
 | #define PESQI_BDDONE		BIT(9)  /* BD processing complete */ | 
 | #define PESQI_PKTCOMP		BIT(10) /* packet processing complete */ | 
 | #define PESQI_DMAERR		BIT(11) /* error */ | 
 |  | 
 | /* PESQI_BD_CTRL_REG */ | 
 | #define PESQI_DMA_EN		BIT(0) /* enable DMA engine */ | 
 | #define PESQI_POLL_EN		BIT(1) /* enable polling */ | 
 | #define PESQI_BDP_START		BIT(2) /* start BD processor */ | 
 |  | 
 | /* PESQI controller buffer descriptor */ | 
 | struct buf_desc { | 
 | 	u32 bd_ctrl;	/* control */ | 
 | 	u32 bd_status;	/* reserved */ | 
 | 	u32 bd_addr;	/* DMA buffer addr */ | 
 | 	u32 bd_nextp;	/* next item in chain */ | 
 | }; | 
 |  | 
 | /* bd_ctrl */ | 
 | #define BD_BUFLEN		0x1ff | 
 | #define BD_CBD_INT_EN		BIT(16)	/* Current BD is processed */ | 
 | #define BD_PKT_INT_EN		BIT(17) /* All BDs of PKT processed */ | 
 | #define BD_LIFM			BIT(18) /* last data of pkt */ | 
 | #define BD_LAST			BIT(19) /* end of list */ | 
 | #define BD_DATA_RECV		BIT(20) /* receive data */ | 
 | #define BD_DDR			BIT(21) /* DDR mode */ | 
 | #define BD_DUAL			BIT(22)	/* Dual SPI */ | 
 | #define BD_QUAD			BIT(23) /* Quad SPI */ | 
 | #define BD_LSBF			BIT(25)	/* LSB First */ | 
 | #define BD_STAT_CHECK		BIT(27) /* Status poll */ | 
 | #define BD_DEVSEL_SHIFT		28	/* CS */ | 
 | #define BD_CS_DEASSERT		BIT(30) /* de-assert CS after current BD */ | 
 | #define BD_EN			BIT(31) /* BD owned by H/W */ | 
 |  | 
 | /** | 
 |  * struct ring_desc - Representation of SQI ring descriptor | 
 |  * @list:	list element to add to free or used list. | 
 |  * @bd:		PESQI controller buffer descriptor | 
 |  * @bd_dma:	DMA address of PESQI controller buffer descriptor | 
 |  * @xfer_len:	transfer length | 
 |  */ | 
 | struct ring_desc { | 
 | 	struct list_head list; | 
 | 	struct buf_desc *bd; | 
 | 	dma_addr_t bd_dma; | 
 | 	u32 xfer_len; | 
 | }; | 
 |  | 
 | /* Global constants */ | 
 | #define PESQI_BD_BUF_LEN_MAX	256 | 
 | #define PESQI_BD_COUNT		256 /* max 64KB data per spi message */ | 
 |  | 
 | struct pic32_sqi { | 
 | 	void __iomem		*regs; | 
 | 	struct clk		*sys_clk; | 
 | 	struct clk		*base_clk; /* drives spi clock */ | 
 | 	struct spi_master	*master; | 
 | 	int			irq; | 
 | 	struct completion	xfer_done; | 
 | 	struct ring_desc	*ring; | 
 | 	void			*bd; | 
 | 	dma_addr_t		bd_dma; | 
 | 	struct list_head	bd_list_free; /* free */ | 
 | 	struct list_head	bd_list_used; /* allocated */ | 
 | 	struct spi_device	*cur_spi; | 
 | 	u32			cur_speed; | 
 | 	u8			cur_mode; | 
 | }; | 
 |  | 
 | static inline void pic32_setbits(void __iomem *reg, u32 set) | 
 | { | 
 | 	writel(readl(reg) | set, reg); | 
 | } | 
 |  | 
 | static inline void pic32_clrbits(void __iomem *reg, u32 clr) | 
 | { | 
 | 	writel(readl(reg) & ~clr, reg); | 
 | } | 
 |  | 
 | static int pic32_sqi_set_clk_rate(struct pic32_sqi *sqi, u32 sck) | 
 | { | 
 | 	u32 val, div; | 
 |  | 
 | 	/* div = base_clk / (2 * spi_clk) */ | 
 | 	div = clk_get_rate(sqi->base_clk) / (2 * sck); | 
 | 	div &= PESQI_CLKDIV; | 
 |  | 
 | 	val = readl(sqi->regs + PESQI_CLK_CTRL_REG); | 
 | 	/* apply new divider */ | 
 | 	val &= ~(PESQI_CLK_STABLE | (PESQI_CLKDIV << PESQI_CLKDIV_SHIFT)); | 
 | 	val |= div << PESQI_CLKDIV_SHIFT; | 
 | 	writel(val, sqi->regs + PESQI_CLK_CTRL_REG); | 
 |  | 
 | 	/* wait for stability */ | 
 | 	return readl_poll_timeout(sqi->regs + PESQI_CLK_CTRL_REG, val, | 
 | 				  val & PESQI_CLK_STABLE, 1, 5000); | 
 | } | 
 |  | 
 | static inline void pic32_sqi_enable_int(struct pic32_sqi *sqi) | 
 | { | 
 | 	u32 mask = PESQI_DMAERR | PESQI_BDDONE | PESQI_PKTCOMP; | 
 |  | 
 | 	writel(mask, sqi->regs + PESQI_INT_ENABLE_REG); | 
 | 	/* INT_SIGEN works as interrupt-gate to INTR line */ | 
 | 	writel(mask, sqi->regs + PESQI_INT_SIGEN_REG); | 
 | } | 
 |  | 
 | static inline void pic32_sqi_disable_int(struct pic32_sqi *sqi) | 
 | { | 
 | 	writel(0, sqi->regs + PESQI_INT_ENABLE_REG); | 
 | 	writel(0, sqi->regs + PESQI_INT_SIGEN_REG); | 
 | } | 
 |  | 
 | static irqreturn_t pic32_sqi_isr(int irq, void *dev_id) | 
 | { | 
 | 	struct pic32_sqi *sqi = dev_id; | 
 | 	u32 enable, status; | 
 |  | 
 | 	enable = readl(sqi->regs + PESQI_INT_ENABLE_REG); | 
 | 	status = readl(sqi->regs + PESQI_INT_STAT_REG); | 
 |  | 
 | 	/* check spurious interrupt */ | 
 | 	if (!status) | 
 | 		return IRQ_NONE; | 
 |  | 
 | 	if (status & PESQI_DMAERR) { | 
 | 		enable = 0; | 
 | 		goto irq_done; | 
 | 	} | 
 |  | 
 | 	if (status & PESQI_TXTHR) | 
 | 		enable &= ~(PESQI_TXTHR | PESQI_TXFULL | PESQI_TXEMPTY); | 
 |  | 
 | 	if (status & PESQI_RXTHR) | 
 | 		enable &= ~(PESQI_RXTHR | PESQI_RXFULL | PESQI_RXEMPTY); | 
 |  | 
 | 	if (status & PESQI_BDDONE) | 
 | 		enable &= ~PESQI_BDDONE; | 
 |  | 
 | 	/* packet processing completed */ | 
 | 	if (status & PESQI_PKTCOMP) { | 
 | 		/* mask all interrupts */ | 
 | 		enable = 0; | 
 | 		/* complete trasaction */ | 
 | 		complete(&sqi->xfer_done); | 
 | 	} | 
 |  | 
 | irq_done: | 
 | 	/* interrupts are sticky, so mask when handled */ | 
 | 	writel(enable, sqi->regs + PESQI_INT_ENABLE_REG); | 
 |  | 
 | 	return IRQ_HANDLED; | 
 | } | 
 |  | 
 | static struct ring_desc *ring_desc_get(struct pic32_sqi *sqi) | 
 | { | 
 | 	struct ring_desc *rdesc; | 
 |  | 
 | 	if (list_empty(&sqi->bd_list_free)) | 
 | 		return NULL; | 
 |  | 
 | 	rdesc = list_first_entry(&sqi->bd_list_free, struct ring_desc, list); | 
 | 	list_move_tail(&rdesc->list, &sqi->bd_list_used); | 
 | 	return rdesc; | 
 | } | 
 |  | 
 | static void ring_desc_put(struct pic32_sqi *sqi, struct ring_desc *rdesc) | 
 | { | 
 | 	list_move(&rdesc->list, &sqi->bd_list_free); | 
 | } | 
 |  | 
 | static int pic32_sqi_one_transfer(struct pic32_sqi *sqi, | 
 | 				  struct spi_message *mesg, | 
 | 				  struct spi_transfer *xfer) | 
 | { | 
 | 	struct spi_device *spi = mesg->spi; | 
 | 	struct scatterlist *sg, *sgl; | 
 | 	struct ring_desc *rdesc; | 
 | 	struct buf_desc *bd; | 
 | 	int nents, i; | 
 | 	u32 bd_ctrl; | 
 | 	u32 nbits; | 
 |  | 
 | 	/* Device selection */ | 
 | 	bd_ctrl = spi->chip_select << BD_DEVSEL_SHIFT; | 
 |  | 
 | 	/* half-duplex: select transfer buffer, direction and lane */ | 
 | 	if (xfer->rx_buf) { | 
 | 		bd_ctrl |= BD_DATA_RECV; | 
 | 		nbits = xfer->rx_nbits; | 
 | 		sgl = xfer->rx_sg.sgl; | 
 | 		nents = xfer->rx_sg.nents; | 
 | 	} else { | 
 | 		nbits = xfer->tx_nbits; | 
 | 		sgl = xfer->tx_sg.sgl; | 
 | 		nents = xfer->tx_sg.nents; | 
 | 	} | 
 |  | 
 | 	if (nbits & SPI_NBITS_QUAD) | 
 | 		bd_ctrl |= BD_QUAD; | 
 | 	else if (nbits & SPI_NBITS_DUAL) | 
 | 		bd_ctrl |= BD_DUAL; | 
 |  | 
 | 	/* LSB first */ | 
 | 	if (spi->mode & SPI_LSB_FIRST) | 
 | 		bd_ctrl |= BD_LSBF; | 
 |  | 
 | 	/* ownership to hardware */ | 
 | 	bd_ctrl |= BD_EN; | 
 |  | 
 | 	for_each_sg(sgl, sg, nents, i) { | 
 | 		/* get ring descriptor */ | 
 | 		rdesc = ring_desc_get(sqi); | 
 | 		if (!rdesc) | 
 | 			break; | 
 |  | 
 | 		bd = rdesc->bd; | 
 |  | 
 | 		/* BD CTRL: length */ | 
 | 		rdesc->xfer_len = sg_dma_len(sg); | 
 | 		bd->bd_ctrl = bd_ctrl; | 
 | 		bd->bd_ctrl |= rdesc->xfer_len; | 
 |  | 
 | 		/* BD STAT */ | 
 | 		bd->bd_status = 0; | 
 |  | 
 | 		/* BD BUFFER ADDRESS */ | 
 | 		bd->bd_addr = sg->dma_address; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int pic32_sqi_prepare_hardware(struct spi_master *master) | 
 | { | 
 | 	struct pic32_sqi *sqi = spi_master_get_devdata(master); | 
 |  | 
 | 	/* enable spi interface */ | 
 | 	pic32_setbits(sqi->regs + PESQI_CONF_REG, PESQI_EN); | 
 | 	/* enable spi clk */ | 
 | 	pic32_setbits(sqi->regs + PESQI_CLK_CTRL_REG, PESQI_CLK_EN); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static bool pic32_sqi_can_dma(struct spi_master *master, | 
 | 			      struct spi_device *spi, | 
 | 			      struct spi_transfer *x) | 
 | { | 
 | 	/* Do DMA irrespective of transfer size */ | 
 | 	return true; | 
 | } | 
 |  | 
 | static int pic32_sqi_one_message(struct spi_master *master, | 
 | 				 struct spi_message *msg) | 
 | { | 
 | 	struct spi_device *spi = msg->spi; | 
 | 	struct ring_desc *rdesc, *next; | 
 | 	struct spi_transfer *xfer; | 
 | 	struct pic32_sqi *sqi; | 
 | 	int ret = 0, mode; | 
 | 	unsigned long timeout; | 
 | 	u32 val; | 
 |  | 
 | 	sqi = spi_master_get_devdata(master); | 
 |  | 
 | 	reinit_completion(&sqi->xfer_done); | 
 | 	msg->actual_length = 0; | 
 |  | 
 | 	/* We can't handle spi_transfer specific "speed_hz", "bits_per_word" | 
 | 	 * and "delay_usecs". But spi_device specific speed and mode change | 
 | 	 * can be handled at best during spi chip-select switch. | 
 | 	 */ | 
 | 	if (sqi->cur_spi != spi) { | 
 | 		/* set spi speed */ | 
 | 		if (sqi->cur_speed != spi->max_speed_hz) { | 
 | 			sqi->cur_speed = spi->max_speed_hz; | 
 | 			ret = pic32_sqi_set_clk_rate(sqi, spi->max_speed_hz); | 
 | 			if (ret) | 
 | 				dev_warn(&spi->dev, "set_clk, %d\n", ret); | 
 | 		} | 
 |  | 
 | 		/* set spi mode */ | 
 | 		mode = spi->mode & (SPI_MODE_3 | SPI_LSB_FIRST); | 
 | 		if (sqi->cur_mode != mode) { | 
 | 			val = readl(sqi->regs + PESQI_CONF_REG); | 
 | 			val &= ~(PESQI_CPOL | PESQI_CPHA | PESQI_LSBF); | 
 | 			if (mode & SPI_CPOL) | 
 | 				val |= PESQI_CPOL; | 
 | 			if (mode & SPI_LSB_FIRST) | 
 | 				val |= PESQI_LSBF; | 
 | 			val |= PESQI_CPHA; | 
 | 			writel(val, sqi->regs + PESQI_CONF_REG); | 
 |  | 
 | 			sqi->cur_mode = mode; | 
 | 		} | 
 | 		sqi->cur_spi = spi; | 
 | 	} | 
 |  | 
 | 	/* prepare hardware desc-list(BD) for transfer(s) */ | 
 | 	list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 
 | 		ret = pic32_sqi_one_transfer(sqi, msg, xfer); | 
 | 		if (ret) { | 
 | 			dev_err(&spi->dev, "xfer %p err\n", xfer); | 
 | 			goto xfer_out; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	/* BDs are prepared and chained. Now mark LAST_BD, CS_DEASSERT at last | 
 | 	 * element of the list. | 
 | 	 */ | 
 | 	rdesc = list_last_entry(&sqi->bd_list_used, struct ring_desc, list); | 
 | 	rdesc->bd->bd_ctrl |= BD_LAST | BD_CS_DEASSERT | | 
 | 			      BD_LIFM | BD_PKT_INT_EN; | 
 |  | 
 | 	/* set base address BD list for DMA engine */ | 
 | 	rdesc = list_first_entry(&sqi->bd_list_used, struct ring_desc, list); | 
 | 	writel(rdesc->bd_dma, sqi->regs + PESQI_BD_BASE_ADDR_REG); | 
 |  | 
 | 	/* enable interrupt */ | 
 | 	pic32_sqi_enable_int(sqi); | 
 |  | 
 | 	/* enable DMA engine */ | 
 | 	val = PESQI_DMA_EN | PESQI_POLL_EN | PESQI_BDP_START; | 
 | 	writel(val, sqi->regs + PESQI_BD_CTRL_REG); | 
 |  | 
 | 	/* wait for xfer completion */ | 
 | 	timeout = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ); | 
 | 	if (timeout == 0) { | 
 | 		dev_err(&sqi->master->dev, "wait timedout/interrupted\n"); | 
 | 		ret = -ETIMEDOUT; | 
 | 		msg->status = ret; | 
 | 	} else { | 
 | 		/* success */ | 
 | 		msg->status = 0; | 
 | 		ret = 0; | 
 | 	} | 
 |  | 
 | 	/* disable DMA */ | 
 | 	writel(0, sqi->regs + PESQI_BD_CTRL_REG); | 
 |  | 
 | 	pic32_sqi_disable_int(sqi); | 
 |  | 
 | xfer_out: | 
 | 	list_for_each_entry_safe_reverse(rdesc, next, | 
 | 					 &sqi->bd_list_used, list) { | 
 | 		/* Update total byte transferred */ | 
 | 		msg->actual_length += rdesc->xfer_len; | 
 | 		/* release ring descr */ | 
 | 		ring_desc_put(sqi, rdesc); | 
 | 	} | 
 | 	spi_finalize_current_message(spi->master); | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | static int pic32_sqi_unprepare_hardware(struct spi_master *master) | 
 | { | 
 | 	struct pic32_sqi *sqi = spi_master_get_devdata(master); | 
 |  | 
 | 	/* disable clk */ | 
 | 	pic32_clrbits(sqi->regs + PESQI_CLK_CTRL_REG, PESQI_CLK_EN); | 
 | 	/* disable spi */ | 
 | 	pic32_clrbits(sqi->regs + PESQI_CONF_REG, PESQI_EN); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int ring_desc_ring_alloc(struct pic32_sqi *sqi) | 
 | { | 
 | 	struct ring_desc *rdesc; | 
 | 	struct buf_desc *bd; | 
 | 	int i; | 
 |  | 
 | 	/* allocate coherent DMAable memory for hardware buffer descriptors. */ | 
 | 	sqi->bd = dma_zalloc_coherent(&sqi->master->dev, | 
 | 				      sizeof(*bd) * PESQI_BD_COUNT, | 
 | 				      &sqi->bd_dma, GFP_DMA32); | 
 | 	if (!sqi->bd) { | 
 | 		dev_err(&sqi->master->dev, "failed allocating dma buffer\n"); | 
 | 		return -ENOMEM; | 
 | 	} | 
 |  | 
 | 	/* allocate software ring descriptors */ | 
 | 	sqi->ring = kcalloc(PESQI_BD_COUNT, sizeof(*rdesc), GFP_KERNEL); | 
 | 	if (!sqi->ring) { | 
 | 		dma_free_coherent(&sqi->master->dev, | 
 | 				  sizeof(*bd) * PESQI_BD_COUNT, | 
 | 				  sqi->bd, sqi->bd_dma); | 
 | 		return -ENOMEM; | 
 | 	} | 
 |  | 
 | 	bd = (struct buf_desc *)sqi->bd; | 
 |  | 
 | 	INIT_LIST_HEAD(&sqi->bd_list_free); | 
 | 	INIT_LIST_HEAD(&sqi->bd_list_used); | 
 |  | 
 | 	/* initialize ring-desc */ | 
 | 	for (i = 0, rdesc = sqi->ring; i < PESQI_BD_COUNT; i++, rdesc++) { | 
 | 		INIT_LIST_HEAD(&rdesc->list); | 
 | 		rdesc->bd = &bd[i]; | 
 | 		rdesc->bd_dma = sqi->bd_dma + (void *)&bd[i] - (void *)bd; | 
 | 		list_add_tail(&rdesc->list, &sqi->bd_list_free); | 
 | 	} | 
 |  | 
 | 	/* Prepare BD: chain to next BD(s) */ | 
 | 	for (i = 0, rdesc = sqi->ring; i < PESQI_BD_COUNT - 1; i++) | 
 | 		bd[i].bd_nextp = rdesc[i + 1].bd_dma; | 
 | 	bd[PESQI_BD_COUNT - 1].bd_nextp = 0; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static void ring_desc_ring_free(struct pic32_sqi *sqi) | 
 | { | 
 | 	dma_free_coherent(&sqi->master->dev, | 
 | 			  sizeof(struct buf_desc) * PESQI_BD_COUNT, | 
 | 			  sqi->bd, sqi->bd_dma); | 
 | 	kfree(sqi->ring); | 
 | } | 
 |  | 
 | static void pic32_sqi_hw_init(struct pic32_sqi *sqi) | 
 | { | 
 | 	unsigned long flags; | 
 | 	u32 val; | 
 |  | 
 | 	/* Soft-reset of PESQI controller triggers interrupt. | 
 | 	 * We are not yet ready to handle them so disable CPU | 
 | 	 * interrupt for the time being. | 
 | 	 */ | 
 | 	local_irq_save(flags); | 
 |  | 
 | 	/* assert soft-reset */ | 
 | 	writel(PESQI_SOFT_RESET, sqi->regs + PESQI_CONF_REG); | 
 |  | 
 | 	/* wait until clear */ | 
 | 	readl_poll_timeout_atomic(sqi->regs + PESQI_CONF_REG, val, | 
 | 				  !(val & PESQI_SOFT_RESET), 1, 5000); | 
 |  | 
 | 	/* disable all interrupts */ | 
 | 	pic32_sqi_disable_int(sqi); | 
 |  | 
 | 	/* Now it is safe to enable back CPU interrupt */ | 
 | 	local_irq_restore(flags); | 
 |  | 
 | 	/* tx and rx fifo interrupt threshold */ | 
 | 	val = readl(sqi->regs + PESQI_CMD_THRES_REG); | 
 | 	val &= ~(PESQI_TXTHR_MASK << PESQI_TXTHR_SHIFT); | 
 | 	val &= ~(PESQI_RXTHR_MASK << PESQI_RXTHR_SHIFT); | 
 | 	val |= (1U << PESQI_TXTHR_SHIFT) | (1U << PESQI_RXTHR_SHIFT); | 
 | 	writel(val, sqi->regs + PESQI_CMD_THRES_REG); | 
 |  | 
 | 	val = readl(sqi->regs + PESQI_INT_THRES_REG); | 
 | 	val &= ~(PESQI_TXTHR_MASK << PESQI_TXTHR_SHIFT); | 
 | 	val &= ~(PESQI_RXTHR_MASK << PESQI_RXTHR_SHIFT); | 
 | 	val |= (1U << PESQI_TXTHR_SHIFT) | (1U << PESQI_RXTHR_SHIFT); | 
 | 	writel(val, sqi->regs + PESQI_INT_THRES_REG); | 
 |  | 
 | 	/* default configuration */ | 
 | 	val = readl(sqi->regs + PESQI_CONF_REG); | 
 |  | 
 | 	/* set mode: DMA */ | 
 | 	val &= ~PESQI_MODE; | 
 | 	val |= PESQI_MODE_DMA << PESQI_MODE_SHIFT; | 
 | 	writel(val, sqi->regs + PESQI_CONF_REG); | 
 |  | 
 | 	/* DATAEN - SQIID0-ID3 */ | 
 | 	val |= PESQI_QUAD_LANE << PESQI_LANES_SHIFT; | 
 |  | 
 | 	/* burst/INCR4 enable */ | 
 | 	val |= PESQI_BURST_EN; | 
 |  | 
 | 	/* CSEN - all CS */ | 
 | 	val |= 3U << PESQI_CSEN_SHIFT; | 
 | 	writel(val, sqi->regs + PESQI_CONF_REG); | 
 |  | 
 | 	/* write poll count */ | 
 | 	writel(0, sqi->regs + PESQI_BD_POLL_CTRL_REG); | 
 |  | 
 | 	sqi->cur_speed = 0; | 
 | 	sqi->cur_mode = -1; | 
 | } | 
 |  | 
 | static int pic32_sqi_probe(struct platform_device *pdev) | 
 | { | 
 | 	struct spi_master *master; | 
 | 	struct pic32_sqi *sqi; | 
 | 	struct resource *reg; | 
 | 	int ret; | 
 |  | 
 | 	master = spi_alloc_master(&pdev->dev, sizeof(*sqi)); | 
 | 	if (!master) | 
 | 		return -ENOMEM; | 
 |  | 
 | 	sqi = spi_master_get_devdata(master); | 
 | 	sqi->master = master; | 
 |  | 
 | 	reg = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
 | 	sqi->regs = devm_ioremap_resource(&pdev->dev, reg); | 
 | 	if (IS_ERR(sqi->regs)) { | 
 | 		ret = PTR_ERR(sqi->regs); | 
 | 		goto err_free_master; | 
 | 	} | 
 |  | 
 | 	/* irq */ | 
 | 	sqi->irq = platform_get_irq(pdev, 0); | 
 | 	if (sqi->irq < 0) { | 
 | 		dev_err(&pdev->dev, "no irq found\n"); | 
 | 		ret = sqi->irq; | 
 | 		goto err_free_master; | 
 | 	} | 
 |  | 
 | 	/* clocks */ | 
 | 	sqi->sys_clk = devm_clk_get(&pdev->dev, "reg_ck"); | 
 | 	if (IS_ERR(sqi->sys_clk)) { | 
 | 		ret = PTR_ERR(sqi->sys_clk); | 
 | 		dev_err(&pdev->dev, "no sys_clk ?\n"); | 
 | 		goto err_free_master; | 
 | 	} | 
 |  | 
 | 	sqi->base_clk = devm_clk_get(&pdev->dev, "spi_ck"); | 
 | 	if (IS_ERR(sqi->base_clk)) { | 
 | 		ret = PTR_ERR(sqi->base_clk); | 
 | 		dev_err(&pdev->dev, "no base clk ?\n"); | 
 | 		goto err_free_master; | 
 | 	} | 
 |  | 
 | 	ret = clk_prepare_enable(sqi->sys_clk); | 
 | 	if (ret) { | 
 | 		dev_err(&pdev->dev, "sys clk enable failed\n"); | 
 | 		goto err_free_master; | 
 | 	} | 
 |  | 
 | 	ret = clk_prepare_enable(sqi->base_clk); | 
 | 	if (ret) { | 
 | 		dev_err(&pdev->dev, "base clk enable failed\n"); | 
 | 		clk_disable_unprepare(sqi->sys_clk); | 
 | 		goto err_free_master; | 
 | 	} | 
 |  | 
 | 	init_completion(&sqi->xfer_done); | 
 |  | 
 | 	/* initialize hardware */ | 
 | 	pic32_sqi_hw_init(sqi); | 
 |  | 
 | 	/* allocate buffers & descriptors */ | 
 | 	ret = ring_desc_ring_alloc(sqi); | 
 | 	if (ret) { | 
 | 		dev_err(&pdev->dev, "ring alloc failed\n"); | 
 | 		goto err_disable_clk; | 
 | 	} | 
 |  | 
 | 	/* install irq handlers */ | 
 | 	ret = request_irq(sqi->irq, pic32_sqi_isr, 0, | 
 | 			  dev_name(&pdev->dev), sqi); | 
 | 	if (ret < 0) { | 
 | 		dev_err(&pdev->dev, "request_irq(%d), failed\n", sqi->irq); | 
 | 		goto err_free_ring; | 
 | 	} | 
 |  | 
 | 	/* register master */ | 
 | 	master->num_chipselect	= 2; | 
 | 	master->max_speed_hz	= clk_get_rate(sqi->base_clk); | 
 | 	master->dma_alignment	= 32; | 
 | 	master->max_dma_len	= PESQI_BD_BUF_LEN_MAX; | 
 | 	master->dev.of_node	= of_node_get(pdev->dev.of_node); | 
 | 	master->mode_bits	= SPI_MODE_3 | SPI_MODE_0 | SPI_TX_DUAL | | 
 | 				  SPI_RX_DUAL | SPI_TX_QUAD | SPI_RX_QUAD; | 
 | 	master->flags		= SPI_MASTER_HALF_DUPLEX; | 
 | 	master->can_dma		= pic32_sqi_can_dma; | 
 | 	master->bits_per_word_mask	= SPI_BPW_RANGE_MASK(8, 32); | 
 | 	master->transfer_one_message	= pic32_sqi_one_message; | 
 | 	master->prepare_transfer_hardware	= pic32_sqi_prepare_hardware; | 
 | 	master->unprepare_transfer_hardware	= pic32_sqi_unprepare_hardware; | 
 |  | 
 | 	ret = devm_spi_register_master(&pdev->dev, master); | 
 | 	if (ret) { | 
 | 		dev_err(&master->dev, "failed registering spi master\n"); | 
 | 		free_irq(sqi->irq, sqi); | 
 | 		goto err_free_ring; | 
 | 	} | 
 |  | 
 | 	platform_set_drvdata(pdev, sqi); | 
 |  | 
 | 	return 0; | 
 |  | 
 | err_free_ring: | 
 | 	ring_desc_ring_free(sqi); | 
 |  | 
 | err_disable_clk: | 
 | 	clk_disable_unprepare(sqi->base_clk); | 
 | 	clk_disable_unprepare(sqi->sys_clk); | 
 |  | 
 | err_free_master: | 
 | 	spi_master_put(master); | 
 | 	return ret; | 
 | } | 
 |  | 
 | static int pic32_sqi_remove(struct platform_device *pdev) | 
 | { | 
 | 	struct pic32_sqi *sqi = platform_get_drvdata(pdev); | 
 |  | 
 | 	/* release resources */ | 
 | 	free_irq(sqi->irq, sqi); | 
 | 	ring_desc_ring_free(sqi); | 
 |  | 
 | 	/* disable clk */ | 
 | 	clk_disable_unprepare(sqi->base_clk); | 
 | 	clk_disable_unprepare(sqi->sys_clk); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct of_device_id pic32_sqi_of_ids[] = { | 
 | 	{.compatible = "microchip,pic32mzda-sqi",}, | 
 | 	{}, | 
 | }; | 
 | MODULE_DEVICE_TABLE(of, pic32_sqi_of_ids); | 
 |  | 
 | static struct platform_driver pic32_sqi_driver = { | 
 | 	.driver = { | 
 | 		.name = "sqi-pic32", | 
 | 		.of_match_table = of_match_ptr(pic32_sqi_of_ids), | 
 | 	}, | 
 | 	.probe = pic32_sqi_probe, | 
 | 	.remove = pic32_sqi_remove, | 
 | }; | 
 |  | 
 | module_platform_driver(pic32_sqi_driver); | 
 |  | 
 | MODULE_AUTHOR("Purna Chandra Mandal <purna.mandal@microchip.com>"); | 
 | MODULE_DESCRIPTION("Microchip SPI driver for PIC32 SQI controller."); | 
 | MODULE_LICENSE("GPL v2"); |