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, ®s->enr);
12646d0a991SJagan Teki
12746d0a991SJagan Teki /* Disable Interrupts */
12846d0a991SJagan Teki writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->idr);
12946d0a991SJagan Teki
13046d0a991SJagan Teki /* Clear the TX and RX threshold reg */
13146d0a991SJagan Teki writel(ZYNQ_QSPI_TXFIFO_THRESHOLD, ®s->txftr);
13246d0a991SJagan Teki writel(ZYNQ_QSPI_RXFIFO_THRESHOLD, ®s->rxftr);
13346d0a991SJagan Teki
13446d0a991SJagan Teki /* Clear the RX FIFO */
13546d0a991SJagan Teki while (readl(®s->isr) & ZYNQ_QSPI_IXR_RXNEMPTY_MASK)
13646d0a991SJagan Teki readl(®s->drxr);
13746d0a991SJagan Teki
13846d0a991SJagan Teki /* Clear Interrupts */
13946d0a991SJagan Teki writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->isr);
14046d0a991SJagan Teki
14146d0a991SJagan Teki /* Manual slave select and Auto start */
14246d0a991SJagan Teki confr = readl(®s->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, ®s->cr);
14846d0a991SJagan Teki
14904a44d36SNathan Rossi /* Disable the LQSPI feature */
15004a44d36SNathan Rossi confr = readl(®s->lqspicfg);
15104a44d36SNathan Rossi confr &= ~ZYNQ_QSPI_LQSPICFG_LQMODE_MASK;
15204a44d36SNathan Rossi writel(confr, ®s->lqspicfg);
15304a44d36SNathan Rossi
15446d0a991SJagan Teki /* Enable SPI */
15546d0a991SJagan Teki writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, ®s->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(®s->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, ®s->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, ®s->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(®s->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, ®s->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(®s->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, ®s->isr);
35946d0a991SJagan Teki
36046d0a991SJagan Teki /* Disable all interrupts */
36146d0a991SJagan Teki writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->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(®s->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, ®s->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 ®s->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, ®s->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, ®s->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, ®s->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(®s->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, ®s->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(®s->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, ®s->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