xref: /openbmc/u-boot/drivers/spi/zynq_qspi.c (revision fb77a9e3537039664ad42992bef6688869eda7c1)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
246d0a991SJagan Teki /*
346d0a991SJagan Teki  * (C) Copyright 2013 Xilinx, Inc.
446d0a991SJagan Teki  * (C) Copyright 2015 Jagan Teki <jteki@openedev.com>
546d0a991SJagan Teki  *
646d0a991SJagan Teki  * Xilinx Zynq Quad-SPI(QSPI) controller driver (master mode only)
746d0a991SJagan Teki  */
846d0a991SJagan Teki 
946d0a991SJagan Teki #include <common.h>
1046d0a991SJagan Teki #include <dm.h>
1146d0a991SJagan Teki #include <malloc.h>
1246d0a991SJagan Teki #include <spi.h>
1346d0a991SJagan Teki #include <asm/io.h>
1446d0a991SJagan Teki 
1546d0a991SJagan Teki DECLARE_GLOBAL_DATA_PTR;
1646d0a991SJagan Teki 
1746d0a991SJagan Teki /* zynq qspi register bit masks ZYNQ_QSPI_<REG>_<BIT>_MASK */
18736b4df1SJagan Teki #define ZYNQ_QSPI_CR_IFMODE_MASK	BIT(31)	/* Flash intrface mode*/
19736b4df1SJagan Teki #define ZYNQ_QSPI_CR_MSA_MASK		BIT(15)	/* Manual start enb */
20736b4df1SJagan Teki #define ZYNQ_QSPI_CR_MCS_MASK		BIT(14)	/* Manual chip select */
21736b4df1SJagan Teki #define ZYNQ_QSPI_CR_PCS_MASK		BIT(10)	/* Peri chip select */
229cf2ffb3SJagan Teki #define ZYNQ_QSPI_CR_FW_MASK		GENMASK(7, 6)	/* FIFO width */
239cf2ffb3SJagan Teki #define ZYNQ_QSPI_CR_SS_MASK		GENMASK(13, 10)	/* Slave Select */
249cf2ffb3SJagan Teki #define ZYNQ_QSPI_CR_BAUD_MASK		GENMASK(5, 3)	/* Baud rate div */
25736b4df1SJagan Teki #define ZYNQ_QSPI_CR_CPHA_MASK		BIT(2)	/* Clock phase */
26736b4df1SJagan Teki #define ZYNQ_QSPI_CR_CPOL_MASK		BIT(1)	/* Clock polarity */
27736b4df1SJagan Teki #define ZYNQ_QSPI_CR_MSTREN_MASK	BIT(0)	/* Mode select */
28736b4df1SJagan Teki #define ZYNQ_QSPI_IXR_RXNEMPTY_MASK	BIT(4)	/* RX_FIFO_not_empty */
29736b4df1SJagan Teki #define ZYNQ_QSPI_IXR_TXOW_MASK		BIT(2)	/* TX_FIFO_not_full */
309cf2ffb3SJagan Teki #define ZYNQ_QSPI_IXR_ALL_MASK		GENMASK(6, 0)	/* All IXR bits */
31736b4df1SJagan Teki #define ZYNQ_QSPI_ENR_SPI_EN_MASK	BIT(0)	/* SPI Enable */
3204a44d36SNathan Rossi #define ZYNQ_QSPI_LQSPICFG_LQMODE_MASK	BIT(31) /* Linear QSPI Mode */
3346d0a991SJagan Teki 
3446d0a991SJagan Teki /* zynq qspi Transmit Data Register */
3546d0a991SJagan Teki #define ZYNQ_QSPI_TXD_00_00_OFFSET	0x1C	/* Transmit 4-byte inst */
3646d0a991SJagan Teki #define ZYNQ_QSPI_TXD_00_01_OFFSET	0x80	/* Transmit 1-byte inst */
3746d0a991SJagan Teki #define ZYNQ_QSPI_TXD_00_10_OFFSET	0x84	/* Transmit 2-byte inst */
3846d0a991SJagan Teki #define ZYNQ_QSPI_TXD_00_11_OFFSET	0x88	/* Transmit 3-byte inst */
3946d0a991SJagan Teki 
4046d0a991SJagan Teki #define ZYNQ_QSPI_TXFIFO_THRESHOLD	1	/* Tx FIFO threshold level*/
4146d0a991SJagan Teki #define ZYNQ_QSPI_RXFIFO_THRESHOLD	32	/* Rx FIFO threshold level */
4246d0a991SJagan Teki 
4346d0a991SJagan Teki #define ZYNQ_QSPI_CR_BAUD_MAX		8	/* Baud rate divisor max val */
4446d0a991SJagan Teki #define ZYNQ_QSPI_CR_BAUD_SHIFT		3	/* Baud rate divisor shift */
4546d0a991SJagan Teki #define ZYNQ_QSPI_CR_SS_SHIFT		10	/* Slave select shift */
4646d0a991SJagan Teki 
4746d0a991SJagan Teki #define ZYNQ_QSPI_FIFO_DEPTH		63
4846d0a991SJagan Teki #ifndef CONFIG_SYS_ZYNQ_QSPI_WAIT
4946d0a991SJagan Teki #define CONFIG_SYS_ZYNQ_QSPI_WAIT	CONFIG_SYS_HZ/100	/* 10 ms */
5046d0a991SJagan Teki #endif
5146d0a991SJagan Teki 
5246d0a991SJagan Teki /* zynq qspi register set */
5346d0a991SJagan Teki struct zynq_qspi_regs {
5446d0a991SJagan Teki 	u32 cr;		/* 0x00 */
5546d0a991SJagan Teki 	u32 isr;	/* 0x04 */
5646d0a991SJagan Teki 	u32 ier;	/* 0x08 */
5746d0a991SJagan Teki 	u32 idr;	/* 0x0C */
5846d0a991SJagan Teki 	u32 imr;	/* 0x10 */
5946d0a991SJagan Teki 	u32 enr;	/* 0x14 */
6046d0a991SJagan Teki 	u32 dr;		/* 0x18 */
6146d0a991SJagan Teki 	u32 txd0r;	/* 0x1C */
6246d0a991SJagan Teki 	u32 drxr;	/* 0x20 */
6346d0a991SJagan Teki 	u32 sicr;	/* 0x24 */
6446d0a991SJagan Teki 	u32 txftr;	/* 0x28 */
6546d0a991SJagan Teki 	u32 rxftr;	/* 0x2C */
6646d0a991SJagan Teki 	u32 gpior;	/* 0x30 */
6746d0a991SJagan Teki 	u32 reserved0[19];
6846d0a991SJagan Teki 	u32 txd1r;	/* 0x80 */
6946d0a991SJagan Teki 	u32 txd2r;	/* 0x84 */
7046d0a991SJagan Teki 	u32 txd3r;	/* 0x88 */
7104a44d36SNathan Rossi 	u32 reserved1[5];
7204a44d36SNathan Rossi 	u32 lqspicfg;	/* 0xA0 */
7304a44d36SNathan Rossi 	u32 lqspists;	/* 0xA4 */
7446d0a991SJagan Teki };
7546d0a991SJagan Teki 
7646d0a991SJagan Teki /* zynq qspi platform data */
7746d0a991SJagan Teki struct zynq_qspi_platdata {
7846d0a991SJagan Teki 	struct zynq_qspi_regs *regs;
7946d0a991SJagan Teki 	u32 frequency;          /* input frequency */
8046d0a991SJagan Teki 	u32 speed_hz;
8146d0a991SJagan Teki };
8246d0a991SJagan Teki 
8346d0a991SJagan Teki /* zynq qspi priv */
8446d0a991SJagan Teki struct zynq_qspi_priv {
8546d0a991SJagan Teki 	struct zynq_qspi_regs *regs;
8646d0a991SJagan Teki 	u8 cs;
8746d0a991SJagan Teki 	u8 mode;
8846d0a991SJagan Teki 	u8 fifo_depth;
8946d0a991SJagan Teki 	u32 freq;		/* required frequency */
9046d0a991SJagan Teki 	const void *tx_buf;
9146d0a991SJagan Teki 	void *rx_buf;
9246d0a991SJagan Teki 	unsigned len;
9346d0a991SJagan Teki 	int bytes_to_transfer;
9446d0a991SJagan Teki 	int bytes_to_receive;
9546d0a991SJagan Teki 	unsigned int is_inst;
9646d0a991SJagan Teki 	unsigned cs_change:1;
9746d0a991SJagan Teki };
9846d0a991SJagan Teki 
zynq_qspi_ofdata_to_platdata(struct udevice * bus)9946d0a991SJagan Teki static int zynq_qspi_ofdata_to_platdata(struct udevice *bus)
10046d0a991SJagan Teki {
10146d0a991SJagan Teki 	struct zynq_qspi_platdata *plat = bus->platdata;
10246d0a991SJagan Teki 	const void *blob = gd->fdt_blob;
103e160f7d4SSimon Glass 	int node = dev_of_offset(bus);
10446d0a991SJagan Teki 
10546d0a991SJagan Teki 	plat->regs = (struct zynq_qspi_regs *)fdtdec_get_addr(blob,
10646d0a991SJagan Teki 							      node, "reg");
10746d0a991SJagan Teki 
10846d0a991SJagan Teki 	/* FIXME: Use 166MHz as a suitable default */
10946d0a991SJagan Teki 	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
11046d0a991SJagan Teki 					166666666);
11146d0a991SJagan Teki 	plat->speed_hz = plat->frequency / 2;
11246d0a991SJagan Teki 
11346d0a991SJagan Teki 	debug("%s: regs=%p max-frequency=%d\n", __func__,
11446d0a991SJagan Teki 	      plat->regs, plat->frequency);
11546d0a991SJagan Teki 
11646d0a991SJagan Teki 	return 0;
11746d0a991SJagan Teki }
11846d0a991SJagan Teki 
zynq_qspi_init_hw(struct zynq_qspi_priv * priv)11946d0a991SJagan Teki static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv)
12046d0a991SJagan Teki {
12146d0a991SJagan Teki 	struct zynq_qspi_regs *regs = priv->regs;
12246d0a991SJagan Teki 	u32 confr;
12346d0a991SJagan Teki 
12446d0a991SJagan Teki 	/* Disable QSPI */
12546d0a991SJagan Teki 	writel(~ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
12646d0a991SJagan Teki 
12746d0a991SJagan Teki 	/* Disable Interrupts */
12846d0a991SJagan Teki 	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->idr);
12946d0a991SJagan Teki 
13046d0a991SJagan Teki 	/* Clear the TX and RX threshold reg */
13146d0a991SJagan Teki 	writel(ZYNQ_QSPI_TXFIFO_THRESHOLD, &regs->txftr);
13246d0a991SJagan Teki 	writel(ZYNQ_QSPI_RXFIFO_THRESHOLD, &regs->rxftr);
13346d0a991SJagan Teki 
13446d0a991SJagan Teki 	/* Clear the RX FIFO */
13546d0a991SJagan Teki 	while (readl(&regs->isr) & ZYNQ_QSPI_IXR_RXNEMPTY_MASK)
13646d0a991SJagan Teki 		readl(&regs->drxr);
13746d0a991SJagan Teki 
13846d0a991SJagan Teki 	/* Clear Interrupts */
13946d0a991SJagan Teki 	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->isr);
14046d0a991SJagan Teki 
14146d0a991SJagan Teki 	/* Manual slave select and Auto start */
14246d0a991SJagan Teki 	confr = readl(&regs->cr);
14346d0a991SJagan Teki 	confr &= ~ZYNQ_QSPI_CR_MSA_MASK;
14446d0a991SJagan Teki 	confr |= ZYNQ_QSPI_CR_IFMODE_MASK | ZYNQ_QSPI_CR_MCS_MASK |
14546d0a991SJagan Teki 		ZYNQ_QSPI_CR_PCS_MASK | ZYNQ_QSPI_CR_FW_MASK |
14646d0a991SJagan Teki 		ZYNQ_QSPI_CR_MSTREN_MASK;
14746d0a991SJagan Teki 	writel(confr, &regs->cr);
14846d0a991SJagan Teki 
14904a44d36SNathan Rossi 	/* Disable the LQSPI feature */
15004a44d36SNathan Rossi 	confr = readl(&regs->lqspicfg);
15104a44d36SNathan Rossi 	confr &= ~ZYNQ_QSPI_LQSPICFG_LQMODE_MASK;
15204a44d36SNathan Rossi 	writel(confr, &regs->lqspicfg);
15304a44d36SNathan Rossi 
15446d0a991SJagan Teki 	/* Enable SPI */
15546d0a991SJagan Teki 	writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
15646d0a991SJagan Teki }
15746d0a991SJagan Teki 
zynq_qspi_probe(struct udevice * bus)15846d0a991SJagan Teki static int zynq_qspi_probe(struct udevice *bus)
15946d0a991SJagan Teki {
16046d0a991SJagan Teki 	struct zynq_qspi_platdata *plat = dev_get_platdata(bus);
16146d0a991SJagan Teki 	struct zynq_qspi_priv *priv = dev_get_priv(bus);
16246d0a991SJagan Teki 
16346d0a991SJagan Teki 	priv->regs = plat->regs;
16446d0a991SJagan Teki 	priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH;
16546d0a991SJagan Teki 
16646d0a991SJagan Teki 	/* init the zynq spi hw */
16746d0a991SJagan Teki 	zynq_qspi_init_hw(priv);
16846d0a991SJagan Teki 
16946d0a991SJagan Teki 	return 0;
17046d0a991SJagan Teki }
17146d0a991SJagan Teki 
17246d0a991SJagan Teki /*
17346d0a991SJagan Teki  * zynq_qspi_read_data - Copy data to RX buffer
17446d0a991SJagan Teki  * @zqspi:	Pointer to the zynq_qspi structure
17546d0a991SJagan Teki  * @data:	The 32 bit variable where data is stored
17646d0a991SJagan Teki  * @size:	Number of bytes to be copied from data to RX buffer
17746d0a991SJagan Teki  */
zynq_qspi_read_data(struct zynq_qspi_priv * priv,u32 data,u8 size)17846d0a991SJagan Teki static void zynq_qspi_read_data(struct zynq_qspi_priv *priv, u32 data, u8 size)
17946d0a991SJagan Teki {
18046d0a991SJagan Teki 	u8 byte3;
18146d0a991SJagan Teki 
18246d0a991SJagan Teki 	debug("%s: data 0x%04x rx_buf addr: 0x%08x size %d\n", __func__ ,
18346d0a991SJagan Teki 	      data, (unsigned)(priv->rx_buf), size);
18446d0a991SJagan Teki 
18546d0a991SJagan Teki 	if (priv->rx_buf) {
18646d0a991SJagan Teki 		switch (size) {
18746d0a991SJagan Teki 		case 1:
18846d0a991SJagan Teki 			*((u8 *)priv->rx_buf) = data;
18946d0a991SJagan Teki 			priv->rx_buf += 1;
19046d0a991SJagan Teki 			break;
19146d0a991SJagan Teki 		case 2:
19246d0a991SJagan Teki 			*((u16 *)priv->rx_buf) = data;
19346d0a991SJagan Teki 			priv->rx_buf += 2;
19446d0a991SJagan Teki 			break;
19546d0a991SJagan Teki 		case 3:
19646d0a991SJagan Teki 			*((u16 *)priv->rx_buf) = data;
19746d0a991SJagan Teki 			priv->rx_buf += 2;
19846d0a991SJagan Teki 			byte3 = (u8)(data >> 16);
19946d0a991SJagan Teki 			*((u8 *)priv->rx_buf) = byte3;
20046d0a991SJagan Teki 			priv->rx_buf += 1;
20146d0a991SJagan Teki 			break;
20246d0a991SJagan Teki 		case 4:
20346d0a991SJagan Teki 			/* Can not assume word aligned buffer */
20446d0a991SJagan Teki 			memcpy(priv->rx_buf, &data, size);
20546d0a991SJagan Teki 			priv->rx_buf += 4;
20646d0a991SJagan Teki 			break;
20746d0a991SJagan Teki 		default:
20846d0a991SJagan Teki 			/* This will never execute */
20946d0a991SJagan Teki 			break;
21046d0a991SJagan Teki 		}
21146d0a991SJagan Teki 	}
21246d0a991SJagan Teki 	priv->bytes_to_receive -= size;
21346d0a991SJagan Teki 	if (priv->bytes_to_receive < 0)
21446d0a991SJagan Teki 		priv->bytes_to_receive = 0;
21546d0a991SJagan Teki }
21646d0a991SJagan Teki 
21746d0a991SJagan Teki /*
21846d0a991SJagan Teki  * zynq_qspi_write_data - Copy data from TX buffer
21946d0a991SJagan Teki  * @zqspi:	Pointer to the zynq_qspi structure
22046d0a991SJagan Teki  * @data:	Pointer to the 32 bit variable where data is to be copied
22146d0a991SJagan Teki  * @size:	Number of bytes to be copied from TX buffer to data
22246d0a991SJagan Teki  */
zynq_qspi_write_data(struct zynq_qspi_priv * priv,u32 * data,u8 size)22346d0a991SJagan Teki static void zynq_qspi_write_data(struct  zynq_qspi_priv *priv,
22446d0a991SJagan Teki 		u32 *data, u8 size)
22546d0a991SJagan Teki {
22646d0a991SJagan Teki 	if (priv->tx_buf) {
22746d0a991SJagan Teki 		switch (size) {
22846d0a991SJagan Teki 		case 1:
22946d0a991SJagan Teki 			*data = *((u8 *)priv->tx_buf);
23046d0a991SJagan Teki 			priv->tx_buf += 1;
23146d0a991SJagan Teki 			*data |= 0xFFFFFF00;
23246d0a991SJagan Teki 			break;
23346d0a991SJagan Teki 		case 2:
23446d0a991SJagan Teki 			*data = *((u16 *)priv->tx_buf);
23546d0a991SJagan Teki 			priv->tx_buf += 2;
23646d0a991SJagan Teki 			*data |= 0xFFFF0000;
23746d0a991SJagan Teki 			break;
23846d0a991SJagan Teki 		case 3:
23946d0a991SJagan Teki 			*data = *((u16 *)priv->tx_buf);
24046d0a991SJagan Teki 			priv->tx_buf += 2;
24146d0a991SJagan Teki 			*data |= (*((u8 *)priv->tx_buf) << 16);
24246d0a991SJagan Teki 			priv->tx_buf += 1;
24346d0a991SJagan Teki 			*data |= 0xFF000000;
24446d0a991SJagan Teki 			break;
24546d0a991SJagan Teki 		case 4:
24646d0a991SJagan Teki 			/* Can not assume word aligned buffer */
24746d0a991SJagan Teki 			memcpy(data, priv->tx_buf, size);
24846d0a991SJagan Teki 			priv->tx_buf += 4;
24946d0a991SJagan Teki 			break;
25046d0a991SJagan Teki 		default:
25146d0a991SJagan Teki 			/* This will never execute */
25246d0a991SJagan Teki 			break;
25346d0a991SJagan Teki 		}
25446d0a991SJagan Teki 	} else {
25546d0a991SJagan Teki 		*data = 0;
25646d0a991SJagan Teki 	}
25746d0a991SJagan Teki 
25846d0a991SJagan Teki 	debug("%s: data 0x%08x tx_buf addr: 0x%08x size %d\n", __func__,
25946d0a991SJagan Teki 	      *data, (u32)priv->tx_buf, size);
26046d0a991SJagan Teki 
26146d0a991SJagan Teki 	priv->bytes_to_transfer -= size;
26246d0a991SJagan Teki 	if (priv->bytes_to_transfer < 0)
26346d0a991SJagan Teki 		priv->bytes_to_transfer = 0;
26446d0a991SJagan Teki }
26546d0a991SJagan Teki 
zynq_qspi_chipselect(struct zynq_qspi_priv * priv,int is_on)26646d0a991SJagan Teki static void zynq_qspi_chipselect(struct  zynq_qspi_priv *priv, int is_on)
26746d0a991SJagan Teki {
26846d0a991SJagan Teki 	u32 confr;
26946d0a991SJagan Teki 	struct zynq_qspi_regs *regs = priv->regs;
27046d0a991SJagan Teki 
27146d0a991SJagan Teki 	confr = readl(&regs->cr);
27246d0a991SJagan Teki 
27346d0a991SJagan Teki 	if (is_on) {
27446d0a991SJagan Teki 		/* Select the slave */
27546d0a991SJagan Teki 		confr &= ~ZYNQ_QSPI_CR_SS_MASK;
27646d0a991SJagan Teki 		confr |= (~(1 << priv->cs) << ZYNQ_QSPI_CR_SS_SHIFT) &
27746d0a991SJagan Teki 					ZYNQ_QSPI_CR_SS_MASK;
27846d0a991SJagan Teki 	} else
27946d0a991SJagan Teki 		/* Deselect the slave */
28046d0a991SJagan Teki 		confr |= ZYNQ_QSPI_CR_SS_MASK;
28146d0a991SJagan Teki 
28246d0a991SJagan Teki 	writel(confr, &regs->cr);
28346d0a991SJagan Teki }
28446d0a991SJagan Teki 
28546d0a991SJagan Teki /*
28646d0a991SJagan Teki  * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
28746d0a991SJagan Teki  * @zqspi:	Pointer to the zynq_qspi structure
28846d0a991SJagan Teki  */
zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv * priv,u32 size)28946d0a991SJagan Teki static void zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv *priv, u32 size)
29046d0a991SJagan Teki {
29146d0a991SJagan Teki 	u32 data = 0;
29246d0a991SJagan Teki 	u32 fifocount = 0;
29346d0a991SJagan Teki 	unsigned len, offset;
29446d0a991SJagan Teki 	struct zynq_qspi_regs *regs = priv->regs;
29546d0a991SJagan Teki 	static const unsigned offsets[4] = {
29646d0a991SJagan Teki 		ZYNQ_QSPI_TXD_00_00_OFFSET, ZYNQ_QSPI_TXD_00_01_OFFSET,
29746d0a991SJagan Teki 		ZYNQ_QSPI_TXD_00_10_OFFSET, ZYNQ_QSPI_TXD_00_11_OFFSET };
29846d0a991SJagan Teki 
29946d0a991SJagan Teki 	while ((fifocount < size) &&
30046d0a991SJagan Teki 			(priv->bytes_to_transfer > 0)) {
30146d0a991SJagan Teki 		if (priv->bytes_to_transfer >= 4) {
30246d0a991SJagan Teki 			if (priv->tx_buf) {
30346d0a991SJagan Teki 				memcpy(&data, priv->tx_buf, 4);
30446d0a991SJagan Teki 				priv->tx_buf += 4;
30546d0a991SJagan Teki 			} else {
30646d0a991SJagan Teki 				data = 0;
30746d0a991SJagan Teki 			}
30846d0a991SJagan Teki 			writel(data, &regs->txd0r);
30946d0a991SJagan Teki 			priv->bytes_to_transfer -= 4;
31046d0a991SJagan Teki 			fifocount++;
31146d0a991SJagan Teki 		} else {
31246d0a991SJagan Teki 			/* Write TXD1, TXD2, TXD3 only if TxFIFO is empty. */
31346d0a991SJagan Teki 			if (!(readl(&regs->isr)
31446d0a991SJagan Teki 					& ZYNQ_QSPI_IXR_TXOW_MASK) &&
31546d0a991SJagan Teki 					!priv->rx_buf)
31646d0a991SJagan Teki 				return;
31746d0a991SJagan Teki 			len = priv->bytes_to_transfer;
31846d0a991SJagan Teki 			zynq_qspi_write_data(priv, &data, len);
31946d0a991SJagan Teki 			offset = (priv->rx_buf) ? offsets[0] : offsets[len];
32046d0a991SJagan Teki 			writel(data, &regs->cr + (offset / 4));
32146d0a991SJagan Teki 		}
32246d0a991SJagan Teki 	}
32346d0a991SJagan Teki }
32446d0a991SJagan Teki 
32546d0a991SJagan Teki /*
32646d0a991SJagan Teki  * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller
32746d0a991SJagan Teki  * @zqspi:	Pointer to the zynq_qspi structure
32846d0a991SJagan Teki  *
32946d0a991SJagan Teki  * This function handles TX empty and Mode Fault interrupts only.
33046d0a991SJagan Teki  * On TX empty interrupt this function reads the received data from RX FIFO and
33146d0a991SJagan Teki  * fills the TX FIFO if there is any data remaining to be transferred.
33246d0a991SJagan Teki  * On Mode Fault interrupt this function indicates that transfer is completed,
33346d0a991SJagan Teki  * the SPI subsystem will identify the error as the remaining bytes to be
33446d0a991SJagan Teki  * transferred is non-zero.
33546d0a991SJagan Teki  *
33646d0a991SJagan Teki  * returns:	0 for poll timeout
33746d0a991SJagan Teki  *		1 transfer operation complete
33846d0a991SJagan Teki  */
zynq_qspi_irq_poll(struct zynq_qspi_priv * priv)33946d0a991SJagan Teki static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv)
34046d0a991SJagan Teki {
34146d0a991SJagan Teki 	struct zynq_qspi_regs *regs = priv->regs;
34246d0a991SJagan Teki 	u32 rxindex = 0;
34346d0a991SJagan Teki 	u32 rxcount;
34446d0a991SJagan Teki 	u32 status, timeout;
34546d0a991SJagan Teki 
34646d0a991SJagan Teki 	/* Poll until any of the interrupt status bits are set */
34746d0a991SJagan Teki 	timeout = get_timer(0);
34846d0a991SJagan Teki 	do {
34946d0a991SJagan Teki 		status = readl(&regs->isr);
35046d0a991SJagan Teki 	} while ((status == 0) &&
35146d0a991SJagan Teki 		(get_timer(timeout) < CONFIG_SYS_ZYNQ_QSPI_WAIT));
35246d0a991SJagan Teki 
35346d0a991SJagan Teki 	if (status == 0) {
35446d0a991SJagan Teki 		printf("zynq_qspi_irq_poll: Timeout!\n");
35546d0a991SJagan Teki 		return -ETIMEDOUT;
35646d0a991SJagan Teki 	}
35746d0a991SJagan Teki 
35846d0a991SJagan Teki 	writel(status, &regs->isr);
35946d0a991SJagan Teki 
36046d0a991SJagan Teki 	/* Disable all interrupts */
36146d0a991SJagan Teki 	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->idr);
36246d0a991SJagan Teki 	if ((status & ZYNQ_QSPI_IXR_TXOW_MASK) ||
36346d0a991SJagan Teki 	    (status & ZYNQ_QSPI_IXR_RXNEMPTY_MASK)) {
36446d0a991SJagan Teki 		/*
36546d0a991SJagan Teki 		 * This bit is set when Tx FIFO has < THRESHOLD entries. We have
36646d0a991SJagan Teki 		 * the THRESHOLD value set to 1, so this bit indicates Tx FIFO
36746d0a991SJagan Teki 		 * is empty
36846d0a991SJagan Teki 		 */
36946d0a991SJagan Teki 		rxcount = priv->bytes_to_receive - priv->bytes_to_transfer;
37046d0a991SJagan Teki 		rxcount = (rxcount % 4) ? ((rxcount/4)+1) : (rxcount/4);
37146d0a991SJagan Teki 		while ((rxindex < rxcount) &&
37246d0a991SJagan Teki 				(rxindex < ZYNQ_QSPI_RXFIFO_THRESHOLD)) {
37346d0a991SJagan Teki 			/* Read out the data from the RX FIFO */
37446d0a991SJagan Teki 			u32 data;
37546d0a991SJagan Teki 			data = readl(&regs->drxr);
37646d0a991SJagan Teki 
37746d0a991SJagan Teki 			if (priv->bytes_to_receive >= 4) {
37846d0a991SJagan Teki 				if (priv->rx_buf) {
37946d0a991SJagan Teki 					memcpy(priv->rx_buf, &data, 4);
38046d0a991SJagan Teki 					priv->rx_buf += 4;
38146d0a991SJagan Teki 				}
38246d0a991SJagan Teki 				priv->bytes_to_receive -= 4;
38346d0a991SJagan Teki 			} else {
38446d0a991SJagan Teki 				zynq_qspi_read_data(priv, data,
38546d0a991SJagan Teki 						    priv->bytes_to_receive);
38646d0a991SJagan Teki 			}
38746d0a991SJagan Teki 			rxindex++;
38846d0a991SJagan Teki 		}
38946d0a991SJagan Teki 
39046d0a991SJagan Teki 		if (priv->bytes_to_transfer) {
39146d0a991SJagan Teki 			/* There is more data to send */
39246d0a991SJagan Teki 			zynq_qspi_fill_tx_fifo(priv,
39346d0a991SJagan Teki 					       ZYNQ_QSPI_RXFIFO_THRESHOLD);
39446d0a991SJagan Teki 
39546d0a991SJagan Teki 			writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
39646d0a991SJagan Teki 		} else {
39746d0a991SJagan Teki 			/*
39846d0a991SJagan Teki 			 * If transfer and receive is completed then only send
39946d0a991SJagan Teki 			 * complete signal
40046d0a991SJagan Teki 			 */
40146d0a991SJagan Teki 			if (!priv->bytes_to_receive) {
40246d0a991SJagan Teki 				/* return operation complete */
40346d0a991SJagan Teki 				writel(ZYNQ_QSPI_IXR_ALL_MASK,
40446d0a991SJagan Teki 				       &regs->idr);
40546d0a991SJagan Teki 				return 1;
40646d0a991SJagan Teki 			}
40746d0a991SJagan Teki 		}
40846d0a991SJagan Teki 	}
40946d0a991SJagan Teki 
41046d0a991SJagan Teki 	return 0;
41146d0a991SJagan Teki }
41246d0a991SJagan Teki 
41346d0a991SJagan Teki /*
41446d0a991SJagan Teki  * zynq_qspi_start_transfer - Initiates the QSPI transfer
41546d0a991SJagan Teki  * @qspi:	Pointer to the spi_device structure
41646d0a991SJagan Teki  * @transfer:	Pointer to the spi_transfer structure which provide information
41746d0a991SJagan Teki  *		about next transfer parameters
41846d0a991SJagan Teki  *
41946d0a991SJagan Teki  * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
42046d0a991SJagan Teki  * transfer to be completed.
42146d0a991SJagan Teki  *
42246d0a991SJagan Teki  * returns:	Number of bytes transferred in the last transfer
42346d0a991SJagan Teki  */
zynq_qspi_start_transfer(struct zynq_qspi_priv * priv)42446d0a991SJagan Teki static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv)
42546d0a991SJagan Teki {
42646d0a991SJagan Teki 	u32 data = 0;
42746d0a991SJagan Teki 	struct zynq_qspi_regs *regs = priv->regs;
42846d0a991SJagan Teki 
42946d0a991SJagan Teki 	debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__,
43046d0a991SJagan Teki 	      (u32)priv, (u32)priv, priv->len);
43146d0a991SJagan Teki 
43246d0a991SJagan Teki 	priv->bytes_to_transfer = priv->len;
43346d0a991SJagan Teki 	priv->bytes_to_receive = priv->len;
43446d0a991SJagan Teki 
43546d0a991SJagan Teki 	if (priv->len < 4)
43646d0a991SJagan Teki 		zynq_qspi_fill_tx_fifo(priv, priv->len);
43746d0a991SJagan Teki 	else
43846d0a991SJagan Teki 		zynq_qspi_fill_tx_fifo(priv, priv->fifo_depth);
43946d0a991SJagan Teki 
44046d0a991SJagan Teki 	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
44146d0a991SJagan Teki 
44246d0a991SJagan Teki 	/* wait for completion */
44346d0a991SJagan Teki 	do {
44446d0a991SJagan Teki 		data = zynq_qspi_irq_poll(priv);
44546d0a991SJagan Teki 	} while (data == 0);
44646d0a991SJagan Teki 
44746d0a991SJagan Teki 	return (priv->len) - (priv->bytes_to_transfer);
44846d0a991SJagan Teki }
44946d0a991SJagan Teki 
zynq_qspi_transfer(struct zynq_qspi_priv * priv)45046d0a991SJagan Teki static int zynq_qspi_transfer(struct zynq_qspi_priv *priv)
45146d0a991SJagan Teki {
45246d0a991SJagan Teki 	unsigned cs_change = 1;
45346d0a991SJagan Teki 	int status = 0;
45446d0a991SJagan Teki 
45546d0a991SJagan Teki 	while (1) {
45646d0a991SJagan Teki 		/* Select the chip if required */
45746d0a991SJagan Teki 		if (cs_change)
45846d0a991SJagan Teki 			zynq_qspi_chipselect(priv, 1);
45946d0a991SJagan Teki 
46046d0a991SJagan Teki 		cs_change = priv->cs_change;
46146d0a991SJagan Teki 
46246d0a991SJagan Teki 		if (!priv->tx_buf && !priv->rx_buf && priv->len) {
46346d0a991SJagan Teki 			status = -1;
46446d0a991SJagan Teki 			break;
46546d0a991SJagan Teki 		}
46646d0a991SJagan Teki 
46746d0a991SJagan Teki 		/* Request the transfer */
46846d0a991SJagan Teki 		if (priv->len) {
46946d0a991SJagan Teki 			status = zynq_qspi_start_transfer(priv);
47046d0a991SJagan Teki 			priv->is_inst = 0;
47146d0a991SJagan Teki 		}
47246d0a991SJagan Teki 
47346d0a991SJagan Teki 		if (status != priv->len) {
47446d0a991SJagan Teki 			if (status > 0)
47546d0a991SJagan Teki 				status = -EMSGSIZE;
47646d0a991SJagan Teki 			debug("zynq_qspi_transfer:%d len:%d\n",
47746d0a991SJagan Teki 			      status, priv->len);
47846d0a991SJagan Teki 			break;
47946d0a991SJagan Teki 		}
48046d0a991SJagan Teki 		status = 0;
48146d0a991SJagan Teki 
48246d0a991SJagan Teki 		if (cs_change)
48346d0a991SJagan Teki 			/* Deselect the chip */
48446d0a991SJagan Teki 			zynq_qspi_chipselect(priv, 0);
48546d0a991SJagan Teki 
48646d0a991SJagan Teki 		break;
48746d0a991SJagan Teki 	}
48846d0a991SJagan Teki 
489*240cd756SVipul Kumar 	return status;
49046d0a991SJagan Teki }
49146d0a991SJagan Teki 
zynq_qspi_claim_bus(struct udevice * dev)49246d0a991SJagan Teki static int zynq_qspi_claim_bus(struct udevice *dev)
49346d0a991SJagan Teki {
49446d0a991SJagan Teki 	struct udevice *bus = dev->parent;
49546d0a991SJagan Teki 	struct zynq_qspi_priv *priv = dev_get_priv(bus);
49646d0a991SJagan Teki 	struct zynq_qspi_regs *regs = priv->regs;
49746d0a991SJagan Teki 
49846d0a991SJagan Teki 	writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
49946d0a991SJagan Teki 
50046d0a991SJagan Teki 	return 0;
50146d0a991SJagan Teki }
50246d0a991SJagan Teki 
zynq_qspi_release_bus(struct udevice * dev)50346d0a991SJagan Teki static int zynq_qspi_release_bus(struct udevice *dev)
50446d0a991SJagan Teki {
50546d0a991SJagan Teki 	struct udevice *bus = dev->parent;
50646d0a991SJagan Teki 	struct zynq_qspi_priv *priv = dev_get_priv(bus);
50746d0a991SJagan Teki 	struct zynq_qspi_regs *regs = priv->regs;
50846d0a991SJagan Teki 
50946d0a991SJagan Teki 	writel(~ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
51046d0a991SJagan Teki 
51146d0a991SJagan Teki 	return 0;
51246d0a991SJagan Teki }
51346d0a991SJagan Teki 
zynq_qspi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)51446d0a991SJagan Teki static int zynq_qspi_xfer(struct udevice *dev, unsigned int bitlen,
51546d0a991SJagan Teki 		const void *dout, void *din, unsigned long flags)
51646d0a991SJagan Teki {
51746d0a991SJagan Teki 	struct udevice *bus = dev->parent;
51846d0a991SJagan Teki 	struct zynq_qspi_priv *priv = dev_get_priv(bus);
51946d0a991SJagan Teki 	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
52046d0a991SJagan Teki 
52146d0a991SJagan Teki 	priv->cs = slave_plat->cs;
52246d0a991SJagan Teki 	priv->tx_buf = dout;
52346d0a991SJagan Teki 	priv->rx_buf = din;
52446d0a991SJagan Teki 	priv->len = bitlen / 8;
52546d0a991SJagan Teki 
526e5e0d68fSJagan Teki 	debug("zynq_qspi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
52746d0a991SJagan Teki 	      bus->seq, slave_plat->cs, bitlen, priv->len, flags);
52846d0a991SJagan Teki 
52946d0a991SJagan Teki 	/*
53046d0a991SJagan Teki 	 * Festering sore.
53146d0a991SJagan Teki 	 * Assume that the beginning of a transfer with bits to
53246d0a991SJagan Teki 	 * transmit must contain a device command.
53346d0a991SJagan Teki 	 */
53446d0a991SJagan Teki 	if (dout && flags & SPI_XFER_BEGIN)
53546d0a991SJagan Teki 		priv->is_inst = 1;
53646d0a991SJagan Teki 	else
53746d0a991SJagan Teki 		priv->is_inst = 0;
53846d0a991SJagan Teki 
53946d0a991SJagan Teki 	if (flags & SPI_XFER_END)
54046d0a991SJagan Teki 		priv->cs_change = 1;
54146d0a991SJagan Teki 	else
54246d0a991SJagan Teki 		priv->cs_change = 0;
54346d0a991SJagan Teki 
54446d0a991SJagan Teki 	zynq_qspi_transfer(priv);
54546d0a991SJagan Teki 
54646d0a991SJagan Teki 	return 0;
54746d0a991SJagan Teki }
54846d0a991SJagan Teki 
zynq_qspi_set_speed(struct udevice * bus,uint speed)54946d0a991SJagan Teki static int zynq_qspi_set_speed(struct udevice *bus, uint speed)
55046d0a991SJagan Teki {
55146d0a991SJagan Teki 	struct zynq_qspi_platdata *plat = bus->platdata;
55246d0a991SJagan Teki 	struct zynq_qspi_priv *priv = dev_get_priv(bus);
55346d0a991SJagan Teki 	struct zynq_qspi_regs *regs = priv->regs;
55446d0a991SJagan Teki 	uint32_t confr;
55546d0a991SJagan Teki 	u8 baud_rate_val = 0;
55646d0a991SJagan Teki 
55746d0a991SJagan Teki 	if (speed > plat->frequency)
55846d0a991SJagan Teki 		speed = plat->frequency;
55946d0a991SJagan Teki 
56046d0a991SJagan Teki 	/* Set the clock frequency */
56146d0a991SJagan Teki 	confr = readl(&regs->cr);
56246d0a991SJagan Teki 	if (speed == 0) {
56346d0a991SJagan Teki 		/* Set baudrate x8, if the freq is 0 */
56446d0a991SJagan Teki 		baud_rate_val = 0x2;
56546d0a991SJagan Teki 	} else if (plat->speed_hz != speed) {
56646d0a991SJagan Teki 		while ((baud_rate_val < ZYNQ_QSPI_CR_BAUD_MAX) &&
56746d0a991SJagan Teki 		       ((plat->frequency /
56846d0a991SJagan Teki 		       (2 << baud_rate_val)) > speed))
56946d0a991SJagan Teki 			baud_rate_val++;
57046d0a991SJagan Teki 
57146d0a991SJagan Teki 		plat->speed_hz = speed / (2 << baud_rate_val);
57246d0a991SJagan Teki 	}
57346d0a991SJagan Teki 	confr &= ~ZYNQ_QSPI_CR_BAUD_MASK;
57446d0a991SJagan Teki 	confr |= (baud_rate_val << ZYNQ_QSPI_CR_BAUD_SHIFT);
57546d0a991SJagan Teki 
57646d0a991SJagan Teki 	writel(confr, &regs->cr);
57746d0a991SJagan Teki 	priv->freq = speed;
57846d0a991SJagan Teki 
579e5e0d68fSJagan Teki 	debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
58046d0a991SJagan Teki 
58146d0a991SJagan Teki 	return 0;
58246d0a991SJagan Teki }
58346d0a991SJagan Teki 
zynq_qspi_set_mode(struct udevice * bus,uint mode)58446d0a991SJagan Teki static int zynq_qspi_set_mode(struct udevice *bus, uint mode)
58546d0a991SJagan Teki {
58646d0a991SJagan Teki 	struct zynq_qspi_priv *priv = dev_get_priv(bus);
58746d0a991SJagan Teki 	struct zynq_qspi_regs *regs = priv->regs;
58846d0a991SJagan Teki 	uint32_t confr;
58946d0a991SJagan Teki 
59046d0a991SJagan Teki 	/* Set the SPI Clock phase and polarities */
59146d0a991SJagan Teki 	confr = readl(&regs->cr);
59246d0a991SJagan Teki 	confr &= ~(ZYNQ_QSPI_CR_CPHA_MASK | ZYNQ_QSPI_CR_CPOL_MASK);
59346d0a991SJagan Teki 
5942775e918SJagan Teki 	if (mode & SPI_CPHA)
59546d0a991SJagan Teki 		confr |= ZYNQ_QSPI_CR_CPHA_MASK;
5962775e918SJagan Teki 	if (mode & SPI_CPOL)
59746d0a991SJagan Teki 		confr |= ZYNQ_QSPI_CR_CPOL_MASK;
59846d0a991SJagan Teki 
59946d0a991SJagan Teki 	writel(confr, &regs->cr);
60046d0a991SJagan Teki 	priv->mode = mode;
60146d0a991SJagan Teki 
602e5e0d68fSJagan Teki 	debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
60346d0a991SJagan Teki 
60446d0a991SJagan Teki 	return 0;
60546d0a991SJagan Teki }
60646d0a991SJagan Teki 
60746d0a991SJagan Teki static const struct dm_spi_ops zynq_qspi_ops = {
60846d0a991SJagan Teki 	.claim_bus      = zynq_qspi_claim_bus,
60946d0a991SJagan Teki 	.release_bus    = zynq_qspi_release_bus,
61046d0a991SJagan Teki 	.xfer           = zynq_qspi_xfer,
61146d0a991SJagan Teki 	.set_speed      = zynq_qspi_set_speed,
61246d0a991SJagan Teki 	.set_mode       = zynq_qspi_set_mode,
61346d0a991SJagan Teki };
61446d0a991SJagan Teki 
61546d0a991SJagan Teki static const struct udevice_id zynq_qspi_ids[] = {
61646d0a991SJagan Teki 	{ .compatible = "xlnx,zynq-qspi-1.0" },
61746d0a991SJagan Teki 	{ }
61846d0a991SJagan Teki };
61946d0a991SJagan Teki 
62046d0a991SJagan Teki U_BOOT_DRIVER(zynq_qspi) = {
62146d0a991SJagan Teki 	.name   = "zynq_qspi",
62246d0a991SJagan Teki 	.id     = UCLASS_SPI,
62346d0a991SJagan Teki 	.of_match = zynq_qspi_ids,
62446d0a991SJagan Teki 	.ops    = &zynq_qspi_ops,
62546d0a991SJagan Teki 	.ofdata_to_platdata = zynq_qspi_ofdata_to_platdata,
62646d0a991SJagan Teki 	.platdata_auto_alloc_size = sizeof(struct zynq_qspi_platdata),
62746d0a991SJagan Teki 	.priv_auto_alloc_size = sizeof(struct zynq_qspi_priv),
62846d0a991SJagan Teki 	.probe  = zynq_qspi_probe,
62946d0a991SJagan Teki };
630