18596124cSNaga Sureshkumar Relli // SPDX-License-Identifier: (GPL-2.0)
28596124cSNaga Sureshkumar Relli /*
38596124cSNaga Sureshkumar Relli  * Microchip coreQSPI QSPI controller driver
48596124cSNaga Sureshkumar Relli  *
58596124cSNaga Sureshkumar Relli  * Copyright (C) 2018-2022 Microchip Technology Inc. and its subsidiaries
68596124cSNaga Sureshkumar Relli  *
78596124cSNaga Sureshkumar Relli  * Author: Naga Sureshkumar Relli <nagasuresh.relli@microchip.com>
88596124cSNaga Sureshkumar Relli  *
98596124cSNaga Sureshkumar Relli  */
108596124cSNaga Sureshkumar Relli 
118596124cSNaga Sureshkumar Relli #include <linux/clk.h>
128596124cSNaga Sureshkumar Relli #include <linux/err.h>
138596124cSNaga Sureshkumar Relli #include <linux/init.h>
148596124cSNaga Sureshkumar Relli #include <linux/interrupt.h>
158596124cSNaga Sureshkumar Relli #include <linux/io.h>
168596124cSNaga Sureshkumar Relli #include <linux/iopoll.h>
178596124cSNaga Sureshkumar Relli #include <linux/module.h>
188596124cSNaga Sureshkumar Relli #include <linux/of.h>
198596124cSNaga Sureshkumar Relli #include <linux/of_irq.h>
208596124cSNaga Sureshkumar Relli #include <linux/platform_device.h>
218596124cSNaga Sureshkumar Relli #include <linux/spi/spi.h>
228596124cSNaga Sureshkumar Relli #include <linux/spi/spi-mem.h>
238596124cSNaga Sureshkumar Relli 
248596124cSNaga Sureshkumar Relli /*
258596124cSNaga Sureshkumar Relli  * QSPI Control register mask defines
268596124cSNaga Sureshkumar Relli  */
278596124cSNaga Sureshkumar Relli #define CONTROL_ENABLE		BIT(0)
288596124cSNaga Sureshkumar Relli #define CONTROL_MASTER		BIT(1)
298596124cSNaga Sureshkumar Relli #define CONTROL_XIP		BIT(2)
308596124cSNaga Sureshkumar Relli #define CONTROL_XIPADDR		BIT(3)
318596124cSNaga Sureshkumar Relli #define CONTROL_CLKIDLE		BIT(10)
328596124cSNaga Sureshkumar Relli #define CONTROL_SAMPLE_MASK	GENMASK(12, 11)
338596124cSNaga Sureshkumar Relli #define CONTROL_MODE0		BIT(13)
348596124cSNaga Sureshkumar Relli #define CONTROL_MODE12_MASK	GENMASK(15, 14)
358596124cSNaga Sureshkumar Relli #define CONTROL_MODE12_EX_RO	BIT(14)
368596124cSNaga Sureshkumar Relli #define CONTROL_MODE12_EX_RW	BIT(15)
378596124cSNaga Sureshkumar Relli #define CONTROL_MODE12_FULL	GENMASK(15, 14)
388596124cSNaga Sureshkumar Relli #define CONTROL_FLAGSX4		BIT(16)
398596124cSNaga Sureshkumar Relli #define CONTROL_CLKRATE_MASK	GENMASK(27, 24)
408596124cSNaga Sureshkumar Relli #define CONTROL_CLKRATE_SHIFT	24
418596124cSNaga Sureshkumar Relli 
428596124cSNaga Sureshkumar Relli /*
438596124cSNaga Sureshkumar Relli  * QSPI Frames register mask defines
448596124cSNaga Sureshkumar Relli  */
458596124cSNaga Sureshkumar Relli #define FRAMES_TOTALBYTES_MASK	GENMASK(15, 0)
468596124cSNaga Sureshkumar Relli #define FRAMES_CMDBYTES_MASK	GENMASK(24, 16)
478596124cSNaga Sureshkumar Relli #define FRAMES_CMDBYTES_SHIFT	16
488596124cSNaga Sureshkumar Relli #define FRAMES_SHIFT		25
498596124cSNaga Sureshkumar Relli #define FRAMES_IDLE_MASK	GENMASK(29, 26)
508596124cSNaga Sureshkumar Relli #define FRAMES_IDLE_SHIFT	26
518596124cSNaga Sureshkumar Relli #define FRAMES_FLAGBYTE		BIT(30)
528596124cSNaga Sureshkumar Relli #define FRAMES_FLAGWORD		BIT(31)
538596124cSNaga Sureshkumar Relli 
548596124cSNaga Sureshkumar Relli /*
558596124cSNaga Sureshkumar Relli  * QSPI Interrupt Enable register mask defines
568596124cSNaga Sureshkumar Relli  */
578596124cSNaga Sureshkumar Relli #define IEN_TXDONE		BIT(0)
588596124cSNaga Sureshkumar Relli #define IEN_RXDONE		BIT(1)
598596124cSNaga Sureshkumar Relli #define IEN_RXAVAILABLE		BIT(2)
608596124cSNaga Sureshkumar Relli #define IEN_TXAVAILABLE		BIT(3)
618596124cSNaga Sureshkumar Relli #define IEN_RXFIFOEMPTY		BIT(4)
628596124cSNaga Sureshkumar Relli #define IEN_TXFIFOFULL		BIT(5)
638596124cSNaga Sureshkumar Relli 
648596124cSNaga Sureshkumar Relli /*
658596124cSNaga Sureshkumar Relli  * QSPI Status register mask defines
668596124cSNaga Sureshkumar Relli  */
678596124cSNaga Sureshkumar Relli #define STATUS_TXDONE		BIT(0)
688596124cSNaga Sureshkumar Relli #define STATUS_RXDONE		BIT(1)
698596124cSNaga Sureshkumar Relli #define STATUS_RXAVAILABLE	BIT(2)
708596124cSNaga Sureshkumar Relli #define STATUS_TXAVAILABLE	BIT(3)
718596124cSNaga Sureshkumar Relli #define STATUS_RXFIFOEMPTY	BIT(4)
728596124cSNaga Sureshkumar Relli #define STATUS_TXFIFOFULL	BIT(5)
738596124cSNaga Sureshkumar Relli #define STATUS_READY		BIT(7)
748596124cSNaga Sureshkumar Relli #define STATUS_FLAGSX4		BIT(8)
758596124cSNaga Sureshkumar Relli #define STATUS_MASK		GENMASK(8, 0)
768596124cSNaga Sureshkumar Relli 
778596124cSNaga Sureshkumar Relli #define BYTESUPPER_MASK		GENMASK(31, 16)
788596124cSNaga Sureshkumar Relli #define BYTESLOWER_MASK		GENMASK(15, 0)
798596124cSNaga Sureshkumar Relli 
808596124cSNaga Sureshkumar Relli #define MAX_DIVIDER		16
818596124cSNaga Sureshkumar Relli #define MIN_DIVIDER		0
828596124cSNaga Sureshkumar Relli #define MAX_DATA_CMD_LEN	256
838596124cSNaga Sureshkumar Relli 
848596124cSNaga Sureshkumar Relli /* QSPI ready time out value */
858596124cSNaga Sureshkumar Relli #define TIMEOUT_MS		500
868596124cSNaga Sureshkumar Relli 
878596124cSNaga Sureshkumar Relli /*
888596124cSNaga Sureshkumar Relli  * QSPI Register offsets.
898596124cSNaga Sureshkumar Relli  */
908596124cSNaga Sureshkumar Relli #define REG_CONTROL		(0x00)
918596124cSNaga Sureshkumar Relli #define REG_FRAMES		(0x04)
928596124cSNaga Sureshkumar Relli #define REG_IEN			(0x0c)
938596124cSNaga Sureshkumar Relli #define REG_STATUS		(0x10)
948596124cSNaga Sureshkumar Relli #define REG_DIRECT_ACCESS	(0x14)
958596124cSNaga Sureshkumar Relli #define REG_UPPER_ACCESS	(0x18)
968596124cSNaga Sureshkumar Relli #define REG_RX_DATA		(0x40)
978596124cSNaga Sureshkumar Relli #define REG_TX_DATA		(0x44)
988596124cSNaga Sureshkumar Relli #define REG_X4_RX_DATA		(0x48)
998596124cSNaga Sureshkumar Relli #define REG_X4_TX_DATA		(0x4c)
1008596124cSNaga Sureshkumar Relli #define REG_FRAMESUP		(0x50)
1018596124cSNaga Sureshkumar Relli 
1028596124cSNaga Sureshkumar Relli /**
1038596124cSNaga Sureshkumar Relli  * struct mchp_coreqspi - Defines qspi driver instance
1048596124cSNaga Sureshkumar Relli  * @regs:              Virtual address of the QSPI controller registers
1058596124cSNaga Sureshkumar Relli  * @clk:               QSPI Operating clock
1068596124cSNaga Sureshkumar Relli  * @data_completion:   completion structure
1078596124cSNaga Sureshkumar Relli  * @op_lock:           lock access to the device
1088596124cSNaga Sureshkumar Relli  * @txbuf:             TX buffer
1098596124cSNaga Sureshkumar Relli  * @rxbuf:             RX buffer
1108596124cSNaga Sureshkumar Relli  * @irq:               IRQ number
1118596124cSNaga Sureshkumar Relli  * @tx_len:            Number of bytes left to transfer
1128596124cSNaga Sureshkumar Relli  * @rx_len:            Number of bytes left to receive
1138596124cSNaga Sureshkumar Relli  */
1148596124cSNaga Sureshkumar Relli struct mchp_coreqspi {
1158596124cSNaga Sureshkumar Relli 	void __iomem *regs;
1168596124cSNaga Sureshkumar Relli 	struct clk *clk;
1178596124cSNaga Sureshkumar Relli 	struct completion data_completion;
1188596124cSNaga Sureshkumar Relli 	struct mutex op_lock; /* lock access to the device */
1198596124cSNaga Sureshkumar Relli 	u8 *txbuf;
1208596124cSNaga Sureshkumar Relli 	u8 *rxbuf;
1218596124cSNaga Sureshkumar Relli 	int irq;
1228596124cSNaga Sureshkumar Relli 	int tx_len;
1238596124cSNaga Sureshkumar Relli 	int rx_len;
1248596124cSNaga Sureshkumar Relli };
1258596124cSNaga Sureshkumar Relli 
mchp_coreqspi_set_mode(struct mchp_coreqspi * qspi,const struct spi_mem_op * op)1268596124cSNaga Sureshkumar Relli static int mchp_coreqspi_set_mode(struct mchp_coreqspi *qspi, const struct spi_mem_op *op)
1278596124cSNaga Sureshkumar Relli {
1288596124cSNaga Sureshkumar Relli 	u32 control = readl_relaxed(qspi->regs + REG_CONTROL);
1298596124cSNaga Sureshkumar Relli 
1308596124cSNaga Sureshkumar Relli 	/*
1318596124cSNaga Sureshkumar Relli 	 * The operating mode can be configured based on the command that needs to be send.
1328596124cSNaga Sureshkumar Relli 	 * bits[15:14]: Sets whether multiple bit SPI operates in normal, extended or full modes.
1338596124cSNaga Sureshkumar Relli 	 *		00: Normal (single DQ0 TX and single DQ1 RX lines)
1348596124cSNaga Sureshkumar Relli 	 *		01: Extended RO (command and address bytes on DQ0 only)
1358596124cSNaga Sureshkumar Relli 	 *		10: Extended RW (command byte on DQ0 only)
1368596124cSNaga Sureshkumar Relli 	 *		11: Full. (command and address are on all DQ lines)
1378596124cSNaga Sureshkumar Relli 	 * bit[13]:	Sets whether multiple bit SPI uses 2 or 4 bits of data
1388596124cSNaga Sureshkumar Relli 	 *		0: 2-bits (BSPI)
1398596124cSNaga Sureshkumar Relli 	 *		1: 4-bits (QSPI)
1408596124cSNaga Sureshkumar Relli 	 */
1418596124cSNaga Sureshkumar Relli 	if (op->data.buswidth == 4 || op->data.buswidth == 2) {
1428596124cSNaga Sureshkumar Relli 		control &= ~CONTROL_MODE12_MASK;
1438596124cSNaga Sureshkumar Relli 		if (op->cmd.buswidth == 1 && (op->addr.buswidth == 1 || op->addr.buswidth == 0))
1448596124cSNaga Sureshkumar Relli 			control |= CONTROL_MODE12_EX_RO;
1458596124cSNaga Sureshkumar Relli 		else if (op->cmd.buswidth == 1)
1468596124cSNaga Sureshkumar Relli 			control |= CONTROL_MODE12_EX_RW;
1478596124cSNaga Sureshkumar Relli 		else
1488596124cSNaga Sureshkumar Relli 			control |= CONTROL_MODE12_FULL;
1498596124cSNaga Sureshkumar Relli 
1508596124cSNaga Sureshkumar Relli 		control |= CONTROL_MODE0;
1518596124cSNaga Sureshkumar Relli 	} else {
1528596124cSNaga Sureshkumar Relli 		control &= ~(CONTROL_MODE12_MASK |
1538596124cSNaga Sureshkumar Relli 			     CONTROL_MODE0);
1548596124cSNaga Sureshkumar Relli 	}
1558596124cSNaga Sureshkumar Relli 
1568596124cSNaga Sureshkumar Relli 	writel_relaxed(control, qspi->regs + REG_CONTROL);
1578596124cSNaga Sureshkumar Relli 
1588596124cSNaga Sureshkumar Relli 	return 0;
1598596124cSNaga Sureshkumar Relli }
1608596124cSNaga Sureshkumar Relli 
mchp_coreqspi_read_op(struct mchp_coreqspi * qspi)1618596124cSNaga Sureshkumar Relli static inline void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi)
1628596124cSNaga Sureshkumar Relli {
1638596124cSNaga Sureshkumar Relli 	u32 control, data;
1648596124cSNaga Sureshkumar Relli 
1658596124cSNaga Sureshkumar Relli 	if (!qspi->rx_len)
1668596124cSNaga Sureshkumar Relli 		return;
1678596124cSNaga Sureshkumar Relli 
1688596124cSNaga Sureshkumar Relli 	control = readl_relaxed(qspi->regs + REG_CONTROL);
1698596124cSNaga Sureshkumar Relli 
1708596124cSNaga Sureshkumar Relli 	/*
1718596124cSNaga Sureshkumar Relli 	 * Read 4-bytes from the SPI FIFO in single transaction and then read
1728596124cSNaga Sureshkumar Relli 	 * the reamaining data byte wise.
1738596124cSNaga Sureshkumar Relli 	 */
1748596124cSNaga Sureshkumar Relli 	control |= CONTROL_FLAGSX4;
1758596124cSNaga Sureshkumar Relli 	writel_relaxed(control, qspi->regs + REG_CONTROL);
1768596124cSNaga Sureshkumar Relli 
1778596124cSNaga Sureshkumar Relli 	while (qspi->rx_len >= 4) {
1788596124cSNaga Sureshkumar Relli 		while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_RXFIFOEMPTY)
1798596124cSNaga Sureshkumar Relli 			;
1808596124cSNaga Sureshkumar Relli 		data = readl_relaxed(qspi->regs + REG_X4_RX_DATA);
1818596124cSNaga Sureshkumar Relli 		*(u32 *)qspi->rxbuf = data;
1828596124cSNaga Sureshkumar Relli 		qspi->rxbuf += 4;
1838596124cSNaga Sureshkumar Relli 		qspi->rx_len -= 4;
1848596124cSNaga Sureshkumar Relli 	}
1858596124cSNaga Sureshkumar Relli 
1868596124cSNaga Sureshkumar Relli 	control &= ~CONTROL_FLAGSX4;
1878596124cSNaga Sureshkumar Relli 	writel_relaxed(control, qspi->regs + REG_CONTROL);
1888596124cSNaga Sureshkumar Relli 
1898596124cSNaga Sureshkumar Relli 	while (qspi->rx_len--) {
1908596124cSNaga Sureshkumar Relli 		while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_RXFIFOEMPTY)
1918596124cSNaga Sureshkumar Relli 			;
1928596124cSNaga Sureshkumar Relli 		data = readl_relaxed(qspi->regs + REG_RX_DATA);
1938596124cSNaga Sureshkumar Relli 		*qspi->rxbuf++ = (data & 0xFF);
1948596124cSNaga Sureshkumar Relli 	}
1958596124cSNaga Sureshkumar Relli }
1968596124cSNaga Sureshkumar Relli 
mchp_coreqspi_write_op(struct mchp_coreqspi * qspi,bool word)1978596124cSNaga Sureshkumar Relli static inline void mchp_coreqspi_write_op(struct mchp_coreqspi *qspi, bool word)
1988596124cSNaga Sureshkumar Relli {
1998596124cSNaga Sureshkumar Relli 	u32 control, data;
2008596124cSNaga Sureshkumar Relli 
2018596124cSNaga Sureshkumar Relli 	control = readl_relaxed(qspi->regs + REG_CONTROL);
2028596124cSNaga Sureshkumar Relli 	control |= CONTROL_FLAGSX4;
2038596124cSNaga Sureshkumar Relli 	writel_relaxed(control, qspi->regs + REG_CONTROL);
2048596124cSNaga Sureshkumar Relli 
2058596124cSNaga Sureshkumar Relli 	while (qspi->tx_len >= 4) {
2068596124cSNaga Sureshkumar Relli 		while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_TXFIFOFULL)
2078596124cSNaga Sureshkumar Relli 			;
2088596124cSNaga Sureshkumar Relli 		data = *(u32 *)qspi->txbuf;
2098596124cSNaga Sureshkumar Relli 		qspi->txbuf += 4;
2108596124cSNaga Sureshkumar Relli 		qspi->tx_len -= 4;
2118596124cSNaga Sureshkumar Relli 		writel_relaxed(data, qspi->regs + REG_X4_TX_DATA);
2128596124cSNaga Sureshkumar Relli 	}
2138596124cSNaga Sureshkumar Relli 
2148596124cSNaga Sureshkumar Relli 	control &= ~CONTROL_FLAGSX4;
2158596124cSNaga Sureshkumar Relli 	writel_relaxed(control, qspi->regs + REG_CONTROL);
2168596124cSNaga Sureshkumar Relli 
2178596124cSNaga Sureshkumar Relli 	while (qspi->tx_len--) {
2188596124cSNaga Sureshkumar Relli 		while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_TXFIFOFULL)
2198596124cSNaga Sureshkumar Relli 			;
2208596124cSNaga Sureshkumar Relli 		data =  *qspi->txbuf++;
2218596124cSNaga Sureshkumar Relli 		writel_relaxed(data, qspi->regs + REG_TX_DATA);
2228596124cSNaga Sureshkumar Relli 	}
2238596124cSNaga Sureshkumar Relli }
2248596124cSNaga Sureshkumar Relli 
mchp_coreqspi_enable_ints(struct mchp_coreqspi * qspi)2258596124cSNaga Sureshkumar Relli static void mchp_coreqspi_enable_ints(struct mchp_coreqspi *qspi)
2268596124cSNaga Sureshkumar Relli {
2278596124cSNaga Sureshkumar Relli 	u32 mask = IEN_TXDONE |
2288596124cSNaga Sureshkumar Relli 		   IEN_RXDONE |
2298596124cSNaga Sureshkumar Relli 		   IEN_RXAVAILABLE;
2308596124cSNaga Sureshkumar Relli 
2318596124cSNaga Sureshkumar Relli 	writel_relaxed(mask, qspi->regs + REG_IEN);
2328596124cSNaga Sureshkumar Relli }
2338596124cSNaga Sureshkumar Relli 
mchp_coreqspi_disable_ints(struct mchp_coreqspi * qspi)2348596124cSNaga Sureshkumar Relli static void mchp_coreqspi_disable_ints(struct mchp_coreqspi *qspi)
2358596124cSNaga Sureshkumar Relli {
2368596124cSNaga Sureshkumar Relli 	writel_relaxed(0, qspi->regs + REG_IEN);
2378596124cSNaga Sureshkumar Relli }
2388596124cSNaga Sureshkumar Relli 
mchp_coreqspi_isr(int irq,void * dev_id)2398596124cSNaga Sureshkumar Relli static irqreturn_t mchp_coreqspi_isr(int irq, void *dev_id)
2408596124cSNaga Sureshkumar Relli {
2418596124cSNaga Sureshkumar Relli 	struct mchp_coreqspi *qspi = (struct mchp_coreqspi *)dev_id;
2428596124cSNaga Sureshkumar Relli 	irqreturn_t ret = IRQ_NONE;
2438596124cSNaga Sureshkumar Relli 	int intfield = readl_relaxed(qspi->regs + REG_STATUS) & STATUS_MASK;
2448596124cSNaga Sureshkumar Relli 
2458596124cSNaga Sureshkumar Relli 	if (intfield == 0)
2468596124cSNaga Sureshkumar Relli 		return ret;
2478596124cSNaga Sureshkumar Relli 
2488596124cSNaga Sureshkumar Relli 	if (intfield & IEN_TXDONE) {
2498596124cSNaga Sureshkumar Relli 		writel_relaxed(IEN_TXDONE, qspi->regs + REG_STATUS);
2508596124cSNaga Sureshkumar Relli 		ret = IRQ_HANDLED;
2518596124cSNaga Sureshkumar Relli 	}
2528596124cSNaga Sureshkumar Relli 
2538596124cSNaga Sureshkumar Relli 	if (intfield & IEN_RXAVAILABLE) {
2548596124cSNaga Sureshkumar Relli 		writel_relaxed(IEN_RXAVAILABLE, qspi->regs + REG_STATUS);
2558596124cSNaga Sureshkumar Relli 		mchp_coreqspi_read_op(qspi);
2568596124cSNaga Sureshkumar Relli 		ret = IRQ_HANDLED;
2578596124cSNaga Sureshkumar Relli 	}
2588596124cSNaga Sureshkumar Relli 
2598596124cSNaga Sureshkumar Relli 	if (intfield & IEN_RXDONE) {
2608596124cSNaga Sureshkumar Relli 		writel_relaxed(IEN_RXDONE, qspi->regs + REG_STATUS);
2618596124cSNaga Sureshkumar Relli 		complete(&qspi->data_completion);
2628596124cSNaga Sureshkumar Relli 		ret = IRQ_HANDLED;
2638596124cSNaga Sureshkumar Relli 	}
2648596124cSNaga Sureshkumar Relli 
2658596124cSNaga Sureshkumar Relli 	return ret;
2668596124cSNaga Sureshkumar Relli }
2678596124cSNaga Sureshkumar Relli 
mchp_coreqspi_setup_clock(struct mchp_coreqspi * qspi,struct spi_device * spi)2688596124cSNaga Sureshkumar Relli static int mchp_coreqspi_setup_clock(struct mchp_coreqspi *qspi, struct spi_device *spi)
2698596124cSNaga Sureshkumar Relli {
2708596124cSNaga Sureshkumar Relli 	unsigned long clk_hz;
2718596124cSNaga Sureshkumar Relli 	u32 control, baud_rate_val = 0;
2728596124cSNaga Sureshkumar Relli 
2738596124cSNaga Sureshkumar Relli 	clk_hz = clk_get_rate(qspi->clk);
2748596124cSNaga Sureshkumar Relli 	if (!clk_hz)
2758596124cSNaga Sureshkumar Relli 		return -EINVAL;
2768596124cSNaga Sureshkumar Relli 
2778596124cSNaga Sureshkumar Relli 	baud_rate_val = DIV_ROUND_UP(clk_hz, 2 * spi->max_speed_hz);
2788596124cSNaga Sureshkumar Relli 	if (baud_rate_val > MAX_DIVIDER || baud_rate_val < MIN_DIVIDER) {
2798596124cSNaga Sureshkumar Relli 		dev_err(&spi->dev,
2808596124cSNaga Sureshkumar Relli 			"could not configure the clock for spi clock %d Hz & system clock %ld Hz\n",
2818596124cSNaga Sureshkumar Relli 			spi->max_speed_hz, clk_hz);
2828596124cSNaga Sureshkumar Relli 		return -EINVAL;
2838596124cSNaga Sureshkumar Relli 	}
2848596124cSNaga Sureshkumar Relli 
2858596124cSNaga Sureshkumar Relli 	control = readl_relaxed(qspi->regs + REG_CONTROL);
2868a5e88cbSConor Dooley 	control &= ~CONTROL_CLKRATE_MASK;
2878596124cSNaga Sureshkumar Relli 	control |= baud_rate_val << CONTROL_CLKRATE_SHIFT;
2888596124cSNaga Sureshkumar Relli 	writel_relaxed(control, qspi->regs + REG_CONTROL);
2898596124cSNaga Sureshkumar Relli 	control = readl_relaxed(qspi->regs + REG_CONTROL);
2908596124cSNaga Sureshkumar Relli 
2918596124cSNaga Sureshkumar Relli 	if ((spi->mode & SPI_CPOL) && (spi->mode & SPI_CPHA))
2928596124cSNaga Sureshkumar Relli 		control |= CONTROL_CLKIDLE;
2938596124cSNaga Sureshkumar Relli 	else
2948596124cSNaga Sureshkumar Relli 		control &= ~CONTROL_CLKIDLE;
2958596124cSNaga Sureshkumar Relli 
2968596124cSNaga Sureshkumar Relli 	writel_relaxed(control, qspi->regs + REG_CONTROL);
2978596124cSNaga Sureshkumar Relli 
2988596124cSNaga Sureshkumar Relli 	return 0;
2998596124cSNaga Sureshkumar Relli }
3008596124cSNaga Sureshkumar Relli 
mchp_coreqspi_setup_op(struct spi_device * spi_dev)3018596124cSNaga Sureshkumar Relli static int mchp_coreqspi_setup_op(struct spi_device *spi_dev)
3028596124cSNaga Sureshkumar Relli {
3038596124cSNaga Sureshkumar Relli 	struct spi_controller *ctlr = spi_dev->master;
3048596124cSNaga Sureshkumar Relli 	struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr);
3058596124cSNaga Sureshkumar Relli 	u32 control = readl_relaxed(qspi->regs + REG_CONTROL);
3068596124cSNaga Sureshkumar Relli 
3078596124cSNaga Sureshkumar Relli 	control |= (CONTROL_MASTER | CONTROL_ENABLE);
3088596124cSNaga Sureshkumar Relli 	control &= ~CONTROL_CLKIDLE;
3098596124cSNaga Sureshkumar Relli 	writel_relaxed(control, qspi->regs + REG_CONTROL);
3108596124cSNaga Sureshkumar Relli 
3118596124cSNaga Sureshkumar Relli 	return 0;
3128596124cSNaga Sureshkumar Relli }
3138596124cSNaga Sureshkumar Relli 
mchp_coreqspi_config_op(struct mchp_coreqspi * qspi,const struct spi_mem_op * op)3148596124cSNaga Sureshkumar Relli static inline void mchp_coreqspi_config_op(struct mchp_coreqspi *qspi, const struct spi_mem_op *op)
3158596124cSNaga Sureshkumar Relli {
3168596124cSNaga Sureshkumar Relli 	u32 idle_cycles = 0;
3178596124cSNaga Sureshkumar Relli 	int total_bytes, cmd_bytes, frames, ctrl;
3188596124cSNaga Sureshkumar Relli 
3198596124cSNaga Sureshkumar Relli 	cmd_bytes = op->cmd.nbytes + op->addr.nbytes;
3208596124cSNaga Sureshkumar Relli 	total_bytes = cmd_bytes + op->data.nbytes;
3218596124cSNaga Sureshkumar Relli 
3228596124cSNaga Sureshkumar Relli 	/*
3238596124cSNaga Sureshkumar Relli 	 * As per the coreQSPI IP spec,the number of command and data bytes are
3248596124cSNaga Sureshkumar Relli 	 * controlled by the frames register for each SPI sequence. This supports
3258596124cSNaga Sureshkumar Relli 	 * the SPI flash memory read and writes sequences as below. so configure
3268596124cSNaga Sureshkumar Relli 	 * the cmd and total bytes accordingly.
3278596124cSNaga Sureshkumar Relli 	 * ---------------------------------------------------------------------
3288596124cSNaga Sureshkumar Relli 	 * TOTAL BYTES  |  CMD BYTES | What happens                             |
3298596124cSNaga Sureshkumar Relli 	 * ______________________________________________________________________
3308596124cSNaga Sureshkumar Relli 	 *              |            |                                          |
3318596124cSNaga Sureshkumar Relli 	 *     1        |   1        | The SPI core will transmit a single byte |
3328596124cSNaga Sureshkumar Relli 	 *              |            | and receive data is discarded            |
3338596124cSNaga Sureshkumar Relli 	 *              |            |                                          |
3348596124cSNaga Sureshkumar Relli 	 *     1        |   0        | The SPI core will transmit a single byte |
3358596124cSNaga Sureshkumar Relli 	 *              |            | and return a single byte                 |
3368596124cSNaga Sureshkumar Relli 	 *              |            |                                          |
3378596124cSNaga Sureshkumar Relli 	 *     10       |   4        | The SPI core will transmit 4 command     |
3388596124cSNaga Sureshkumar Relli 	 *              |            | bytes discarding the receive data and    |
3398596124cSNaga Sureshkumar Relli 	 *              |            | transmits 6 dummy bytes returning the 6  |
3408596124cSNaga Sureshkumar Relli 	 *              |            | received bytes and return a single byte  |
3418596124cSNaga Sureshkumar Relli 	 *              |            |                                          |
3428596124cSNaga Sureshkumar Relli 	 *     10       |   10       | The SPI core will transmit 10 command    |
3438596124cSNaga Sureshkumar Relli 	 *              |            |                                          |
3448596124cSNaga Sureshkumar Relli 	 *     10       |    0       | The SPI core will transmit 10 command    |
3458596124cSNaga Sureshkumar Relli 	 *              |            | bytes and returning 10 received bytes    |
3468596124cSNaga Sureshkumar Relli 	 * ______________________________________________________________________
3478596124cSNaga Sureshkumar Relli 	 */
3488596124cSNaga Sureshkumar Relli 	if (!(op->data.dir == SPI_MEM_DATA_IN))
3498596124cSNaga Sureshkumar Relli 		cmd_bytes = total_bytes;
3508596124cSNaga Sureshkumar Relli 
3518596124cSNaga Sureshkumar Relli 	frames = total_bytes & BYTESUPPER_MASK;
3528596124cSNaga Sureshkumar Relli 	writel_relaxed(frames, qspi->regs + REG_FRAMESUP);
3538596124cSNaga Sureshkumar Relli 	frames = total_bytes & BYTESLOWER_MASK;
3548596124cSNaga Sureshkumar Relli 	frames |= cmd_bytes << FRAMES_CMDBYTES_SHIFT;
3558596124cSNaga Sureshkumar Relli 
3568596124cSNaga Sureshkumar Relli 	if (op->dummy.buswidth)
3578596124cSNaga Sureshkumar Relli 		idle_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
3588596124cSNaga Sureshkumar Relli 
3598596124cSNaga Sureshkumar Relli 	frames |= idle_cycles << FRAMES_IDLE_SHIFT;
3608596124cSNaga Sureshkumar Relli 	ctrl = readl_relaxed(qspi->regs + REG_CONTROL);
3618596124cSNaga Sureshkumar Relli 
3628596124cSNaga Sureshkumar Relli 	if (ctrl & CONTROL_MODE12_MASK)
3638596124cSNaga Sureshkumar Relli 		frames |= (1 << FRAMES_SHIFT);
3648596124cSNaga Sureshkumar Relli 
3658596124cSNaga Sureshkumar Relli 	frames |= FRAMES_FLAGWORD;
3668596124cSNaga Sureshkumar Relli 	writel_relaxed(frames, qspi->regs + REG_FRAMES);
3678596124cSNaga Sureshkumar Relli }
3688596124cSNaga Sureshkumar Relli 
mchp_qspi_wait_for_ready(struct spi_mem * mem)3698596124cSNaga Sureshkumar Relli static int mchp_qspi_wait_for_ready(struct spi_mem *mem)
3708596124cSNaga Sureshkumar Relli {
3718596124cSNaga Sureshkumar Relli 	struct mchp_coreqspi *qspi = spi_controller_get_devdata
3728596124cSNaga Sureshkumar Relli 				    (mem->spi->master);
3738596124cSNaga Sureshkumar Relli 	u32 status;
3748596124cSNaga Sureshkumar Relli 	int ret;
3758596124cSNaga Sureshkumar Relli 
3768596124cSNaga Sureshkumar Relli 	ret = readl_poll_timeout(qspi->regs + REG_STATUS, status,
3778596124cSNaga Sureshkumar Relli 				 (status & STATUS_READY), 0,
3788596124cSNaga Sureshkumar Relli 				 TIMEOUT_MS);
3798596124cSNaga Sureshkumar Relli 	if (ret) {
3808596124cSNaga Sureshkumar Relli 		dev_err(&mem->spi->dev,
3818596124cSNaga Sureshkumar Relli 			"Timeout waiting on QSPI ready.\n");
3828596124cSNaga Sureshkumar Relli 		return -ETIMEDOUT;
3838596124cSNaga Sureshkumar Relli 	}
3848596124cSNaga Sureshkumar Relli 
3858596124cSNaga Sureshkumar Relli 	return ret;
3868596124cSNaga Sureshkumar Relli }
3878596124cSNaga Sureshkumar Relli 
mchp_coreqspi_exec_op(struct spi_mem * mem,const struct spi_mem_op * op)3888596124cSNaga Sureshkumar Relli static int mchp_coreqspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
3898596124cSNaga Sureshkumar Relli {
3908596124cSNaga Sureshkumar Relli 	struct mchp_coreqspi *qspi = spi_controller_get_devdata
3918596124cSNaga Sureshkumar Relli 				    (mem->spi->master);
3928596124cSNaga Sureshkumar Relli 	u32 address = op->addr.val;
3938596124cSNaga Sureshkumar Relli 	u8 opcode = op->cmd.opcode;
3948596124cSNaga Sureshkumar Relli 	u8 opaddr[5];
3958596124cSNaga Sureshkumar Relli 	int err, i;
3968596124cSNaga Sureshkumar Relli 
3978596124cSNaga Sureshkumar Relli 	mutex_lock(&qspi->op_lock);
3988596124cSNaga Sureshkumar Relli 	err = mchp_qspi_wait_for_ready(mem);
3998596124cSNaga Sureshkumar Relli 	if (err)
4008596124cSNaga Sureshkumar Relli 		goto error;
4018596124cSNaga Sureshkumar Relli 
4028596124cSNaga Sureshkumar Relli 	err = mchp_coreqspi_setup_clock(qspi, mem->spi);
4038596124cSNaga Sureshkumar Relli 	if (err)
4048596124cSNaga Sureshkumar Relli 		goto error;
4058596124cSNaga Sureshkumar Relli 
4068596124cSNaga Sureshkumar Relli 	err = mchp_coreqspi_set_mode(qspi, op);
4078596124cSNaga Sureshkumar Relli 	if (err)
4088596124cSNaga Sureshkumar Relli 		goto error;
4098596124cSNaga Sureshkumar Relli 
4108596124cSNaga Sureshkumar Relli 	reinit_completion(&qspi->data_completion);
4118596124cSNaga Sureshkumar Relli 	mchp_coreqspi_config_op(qspi, op);
4128596124cSNaga Sureshkumar Relli 	if (op->cmd.opcode) {
4138596124cSNaga Sureshkumar Relli 		qspi->txbuf = &opcode;
4148596124cSNaga Sureshkumar Relli 		qspi->rxbuf = NULL;
4158596124cSNaga Sureshkumar Relli 		qspi->tx_len = op->cmd.nbytes;
4168596124cSNaga Sureshkumar Relli 		qspi->rx_len = 0;
4178596124cSNaga Sureshkumar Relli 		mchp_coreqspi_write_op(qspi, false);
4188596124cSNaga Sureshkumar Relli 	}
4198596124cSNaga Sureshkumar Relli 
4208596124cSNaga Sureshkumar Relli 	qspi->txbuf = &opaddr[0];
4218596124cSNaga Sureshkumar Relli 	if (op->addr.nbytes) {
4228596124cSNaga Sureshkumar Relli 		for (i = 0; i < op->addr.nbytes; i++)
4238596124cSNaga Sureshkumar Relli 			qspi->txbuf[i] = address >> (8 * (op->addr.nbytes - i - 1));
4248596124cSNaga Sureshkumar Relli 
4258596124cSNaga Sureshkumar Relli 		qspi->rxbuf = NULL;
4268596124cSNaga Sureshkumar Relli 		qspi->tx_len = op->addr.nbytes;
4278596124cSNaga Sureshkumar Relli 		qspi->rx_len = 0;
4288596124cSNaga Sureshkumar Relli 		mchp_coreqspi_write_op(qspi, false);
4298596124cSNaga Sureshkumar Relli 	}
4308596124cSNaga Sureshkumar Relli 
4318596124cSNaga Sureshkumar Relli 	if (op->data.nbytes) {
4328596124cSNaga Sureshkumar Relli 		if (op->data.dir == SPI_MEM_DATA_OUT) {
4338596124cSNaga Sureshkumar Relli 			qspi->txbuf = (u8 *)op->data.buf.out;
4348596124cSNaga Sureshkumar Relli 			qspi->rxbuf = NULL;
4358596124cSNaga Sureshkumar Relli 			qspi->rx_len = 0;
4368596124cSNaga Sureshkumar Relli 			qspi->tx_len = op->data.nbytes;
4378596124cSNaga Sureshkumar Relli 			mchp_coreqspi_write_op(qspi, true);
4388596124cSNaga Sureshkumar Relli 		} else {
4398596124cSNaga Sureshkumar Relli 			qspi->txbuf = NULL;
4408596124cSNaga Sureshkumar Relli 			qspi->rxbuf = (u8 *)op->data.buf.in;
4418596124cSNaga Sureshkumar Relli 			qspi->rx_len = op->data.nbytes;
4428596124cSNaga Sureshkumar Relli 			qspi->tx_len = 0;
4438596124cSNaga Sureshkumar Relli 		}
4448596124cSNaga Sureshkumar Relli 	}
4458596124cSNaga Sureshkumar Relli 
4468596124cSNaga Sureshkumar Relli 	mchp_coreqspi_enable_ints(qspi);
4478596124cSNaga Sureshkumar Relli 
4488596124cSNaga Sureshkumar Relli 	if (!wait_for_completion_timeout(&qspi->data_completion, msecs_to_jiffies(1000)))
4498596124cSNaga Sureshkumar Relli 		err = -ETIMEDOUT;
4508596124cSNaga Sureshkumar Relli 
4518596124cSNaga Sureshkumar Relli error:
4528596124cSNaga Sureshkumar Relli 	mutex_unlock(&qspi->op_lock);
4538596124cSNaga Sureshkumar Relli 	mchp_coreqspi_disable_ints(qspi);
4548596124cSNaga Sureshkumar Relli 
4558596124cSNaga Sureshkumar Relli 	return err;
4568596124cSNaga Sureshkumar Relli }
4578596124cSNaga Sureshkumar Relli 
mchp_coreqspi_supports_op(struct spi_mem * mem,const struct spi_mem_op * op)4588596124cSNaga Sureshkumar Relli static bool mchp_coreqspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op)
4598596124cSNaga Sureshkumar Relli {
4608596124cSNaga Sureshkumar Relli 	if (!spi_mem_default_supports_op(mem, op))
4618596124cSNaga Sureshkumar Relli 		return false;
4628596124cSNaga Sureshkumar Relli 
4638596124cSNaga Sureshkumar Relli 	if ((op->data.buswidth == 4 || op->data.buswidth == 2) &&
4648596124cSNaga Sureshkumar Relli 	    (op->cmd.buswidth == 1 && (op->addr.buswidth == 1 || op->addr.buswidth == 0))) {
4658596124cSNaga Sureshkumar Relli 		/*
4668596124cSNaga Sureshkumar Relli 		 * If the command and address are on DQ0 only, then this
4678596124cSNaga Sureshkumar Relli 		 * controller doesn't support sending data on dual and
4688596124cSNaga Sureshkumar Relli 		 * quad lines. but it supports reading data on dual and
4698596124cSNaga Sureshkumar Relli 		 * quad lines with same configuration as command and
4708596124cSNaga Sureshkumar Relli 		 * address on DQ0.
4718596124cSNaga Sureshkumar Relli 		 * i.e. The control register[15:13] :EX_RO(read only) is
4728596124cSNaga Sureshkumar Relli 		 * meant only for the command and address are on DQ0 but
4738596124cSNaga Sureshkumar Relli 		 * not to write data, it is just to read.
4748596124cSNaga Sureshkumar Relli 		 * Ex: 0x34h is Quad Load Program Data which is not
4758596124cSNaga Sureshkumar Relli 		 * supported. Then the spi-mem layer will iterate over
4768596124cSNaga Sureshkumar Relli 		 * each command and it will chose the supported one.
4778596124cSNaga Sureshkumar Relli 		 */
4788596124cSNaga Sureshkumar Relli 		if (op->data.dir == SPI_MEM_DATA_OUT)
4798596124cSNaga Sureshkumar Relli 			return false;
4808596124cSNaga Sureshkumar Relli 	}
4818596124cSNaga Sureshkumar Relli 
4828596124cSNaga Sureshkumar Relli 	return true;
4838596124cSNaga Sureshkumar Relli }
4848596124cSNaga Sureshkumar Relli 
mchp_coreqspi_adjust_op_size(struct spi_mem * mem,struct spi_mem_op * op)4858596124cSNaga Sureshkumar Relli static int mchp_coreqspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
4868596124cSNaga Sureshkumar Relli {
4878596124cSNaga Sureshkumar Relli 	if (op->data.dir == SPI_MEM_DATA_OUT || op->data.dir == SPI_MEM_DATA_IN) {
4888596124cSNaga Sureshkumar Relli 		if (op->data.nbytes > MAX_DATA_CMD_LEN)
4898596124cSNaga Sureshkumar Relli 			op->data.nbytes = MAX_DATA_CMD_LEN;
4908596124cSNaga Sureshkumar Relli 	}
4918596124cSNaga Sureshkumar Relli 
4928596124cSNaga Sureshkumar Relli 	return 0;
4938596124cSNaga Sureshkumar Relli }
4948596124cSNaga Sureshkumar Relli 
4958596124cSNaga Sureshkumar Relli static const struct spi_controller_mem_ops mchp_coreqspi_mem_ops = {
4968596124cSNaga Sureshkumar Relli 	.adjust_op_size = mchp_coreqspi_adjust_op_size,
4978596124cSNaga Sureshkumar Relli 	.supports_op = mchp_coreqspi_supports_op,
4988596124cSNaga Sureshkumar Relli 	.exec_op = mchp_coreqspi_exec_op,
4998596124cSNaga Sureshkumar Relli };
5008596124cSNaga Sureshkumar Relli 
mchp_coreqspi_probe(struct platform_device * pdev)5018596124cSNaga Sureshkumar Relli static int mchp_coreqspi_probe(struct platform_device *pdev)
5028596124cSNaga Sureshkumar Relli {
5038596124cSNaga Sureshkumar Relli 	struct spi_controller *ctlr;
5048596124cSNaga Sureshkumar Relli 	struct mchp_coreqspi *qspi;
5058596124cSNaga Sureshkumar Relli 	struct device *dev = &pdev->dev;
5068596124cSNaga Sureshkumar Relli 	struct device_node *np = dev->of_node;
5078596124cSNaga Sureshkumar Relli 	int ret;
5088596124cSNaga Sureshkumar Relli 
5098596124cSNaga Sureshkumar Relli 	ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*qspi));
5108596124cSNaga Sureshkumar Relli 	if (!ctlr)
5118596124cSNaga Sureshkumar Relli 		return dev_err_probe(&pdev->dev, -ENOMEM,
5128596124cSNaga Sureshkumar Relli 				     "unable to allocate master for QSPI controller\n");
5138596124cSNaga Sureshkumar Relli 
5148596124cSNaga Sureshkumar Relli 	qspi = spi_controller_get_devdata(ctlr);
5158596124cSNaga Sureshkumar Relli 	platform_set_drvdata(pdev, qspi);
5168596124cSNaga Sureshkumar Relli 
5178596124cSNaga Sureshkumar Relli 	qspi->regs = devm_platform_ioremap_resource(pdev, 0);
5188596124cSNaga Sureshkumar Relli 	if (IS_ERR(qspi->regs))
5198596124cSNaga Sureshkumar Relli 		return dev_err_probe(&pdev->dev, PTR_ERR(qspi->regs),
5208596124cSNaga Sureshkumar Relli 				     "failed to map registers\n");
5218596124cSNaga Sureshkumar Relli 
5228596124cSNaga Sureshkumar Relli 	qspi->clk = devm_clk_get(&pdev->dev, NULL);
5238596124cSNaga Sureshkumar Relli 	if (IS_ERR(qspi->clk))
5248596124cSNaga Sureshkumar Relli 		return dev_err_probe(&pdev->dev, PTR_ERR(qspi->clk),
5258596124cSNaga Sureshkumar Relli 				     "could not get clock\n");
5268596124cSNaga Sureshkumar Relli 
5278596124cSNaga Sureshkumar Relli 	ret = clk_prepare_enable(qspi->clk);
5288596124cSNaga Sureshkumar Relli 	if (ret)
5298596124cSNaga Sureshkumar Relli 		return dev_err_probe(&pdev->dev, ret,
5308596124cSNaga Sureshkumar Relli 				     "failed to enable clock\n");
5318596124cSNaga Sureshkumar Relli 
5328596124cSNaga Sureshkumar Relli 	init_completion(&qspi->data_completion);
5338596124cSNaga Sureshkumar Relli 	mutex_init(&qspi->op_lock);
5348596124cSNaga Sureshkumar Relli 
5358596124cSNaga Sureshkumar Relli 	qspi->irq = platform_get_irq(pdev, 0);
5368596124cSNaga Sureshkumar Relli 	if (qspi->irq < 0) {
5378596124cSNaga Sureshkumar Relli 		ret = qspi->irq;
5388596124cSNaga Sureshkumar Relli 		goto out;
5398596124cSNaga Sureshkumar Relli 	}
5408596124cSNaga Sureshkumar Relli 
5418596124cSNaga Sureshkumar Relli 	ret = devm_request_irq(&pdev->dev, qspi->irq, mchp_coreqspi_isr,
5428596124cSNaga Sureshkumar Relli 			       IRQF_SHARED, pdev->name, qspi);
5438596124cSNaga Sureshkumar Relli 	if (ret) {
5448596124cSNaga Sureshkumar Relli 		dev_err(&pdev->dev, "request_irq failed %d\n", ret);
5458596124cSNaga Sureshkumar Relli 		goto out;
5468596124cSNaga Sureshkumar Relli 	}
5478596124cSNaga Sureshkumar Relli 
5488596124cSNaga Sureshkumar Relli 	ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
5498596124cSNaga Sureshkumar Relli 	ctlr->mem_ops = &mchp_coreqspi_mem_ops;
5508596124cSNaga Sureshkumar Relli 	ctlr->setup = mchp_coreqspi_setup_op;
5518596124cSNaga Sureshkumar Relli 	ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
5528596124cSNaga Sureshkumar Relli 			  SPI_TX_DUAL | SPI_TX_QUAD;
5538596124cSNaga Sureshkumar Relli 	ctlr->dev.of_node = np;
5548596124cSNaga Sureshkumar Relli 
5558596124cSNaga Sureshkumar Relli 	ret = devm_spi_register_controller(&pdev->dev, ctlr);
5568596124cSNaga Sureshkumar Relli 	if (ret) {
5578596124cSNaga Sureshkumar Relli 		dev_err_probe(&pdev->dev, ret,
5588596124cSNaga Sureshkumar Relli 			      "spi_register_controller failed\n");
5598596124cSNaga Sureshkumar Relli 		goto out;
5608596124cSNaga Sureshkumar Relli 	}
5618596124cSNaga Sureshkumar Relli 
5628596124cSNaga Sureshkumar Relli 	return 0;
5638596124cSNaga Sureshkumar Relli 
5648596124cSNaga Sureshkumar Relli out:
5658596124cSNaga Sureshkumar Relli 	clk_disable_unprepare(qspi->clk);
5668596124cSNaga Sureshkumar Relli 
5678596124cSNaga Sureshkumar Relli 	return ret;
5688596124cSNaga Sureshkumar Relli }
5698596124cSNaga Sureshkumar Relli 
mchp_coreqspi_remove(struct platform_device * pdev)570e4cf312dSUwe Kleine-König static void mchp_coreqspi_remove(struct platform_device *pdev)
5718596124cSNaga Sureshkumar Relli {
5728596124cSNaga Sureshkumar Relli 	struct mchp_coreqspi *qspi = platform_get_drvdata(pdev);
5738596124cSNaga Sureshkumar Relli 	u32 control = readl_relaxed(qspi->regs + REG_CONTROL);
5748596124cSNaga Sureshkumar Relli 
5758596124cSNaga Sureshkumar Relli 	mchp_coreqspi_disable_ints(qspi);
5768596124cSNaga Sureshkumar Relli 	control &= ~CONTROL_ENABLE;
5778596124cSNaga Sureshkumar Relli 	writel_relaxed(control, qspi->regs + REG_CONTROL);
5788596124cSNaga Sureshkumar Relli 	clk_disable_unprepare(qspi->clk);
5798596124cSNaga Sureshkumar Relli }
5808596124cSNaga Sureshkumar Relli 
5818596124cSNaga Sureshkumar Relli static const struct of_device_id mchp_coreqspi_of_match[] = {
5828596124cSNaga Sureshkumar Relli 	{ .compatible = "microchip,coreqspi-rtl-v2" },
5838596124cSNaga Sureshkumar Relli 	{ /* sentinel */ }
5848596124cSNaga Sureshkumar Relli };
5858596124cSNaga Sureshkumar Relli MODULE_DEVICE_TABLE(of, mchp_coreqspi_of_match);
5868596124cSNaga Sureshkumar Relli 
5878596124cSNaga Sureshkumar Relli static struct platform_driver mchp_coreqspi_driver = {
5888596124cSNaga Sureshkumar Relli 	.probe = mchp_coreqspi_probe,
5898596124cSNaga Sureshkumar Relli 	.driver = {
5908596124cSNaga Sureshkumar Relli 		.name = "microchip,coreqspi",
5918596124cSNaga Sureshkumar Relli 		.of_match_table = mchp_coreqspi_of_match,
5928596124cSNaga Sureshkumar Relli 	},
593e4cf312dSUwe Kleine-König 	.remove_new = mchp_coreqspi_remove,
5948596124cSNaga Sureshkumar Relli };
5958596124cSNaga Sureshkumar Relli module_platform_driver(mchp_coreqspi_driver);
5968596124cSNaga Sureshkumar Relli 
5978596124cSNaga Sureshkumar Relli MODULE_AUTHOR("Naga Sureshkumar Relli <nagasuresh.relli@microchip.com");
5988596124cSNaga Sureshkumar Relli MODULE_DESCRIPTION("Microchip coreQSPI QSPI controller driver");
5998596124cSNaga Sureshkumar Relli MODULE_LICENSE("GPL");
600