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