blob: b71b9a6fd6c8ed73d182810034ab1057f40dff16 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Jagan Teki7fbea8a2015-08-17 18:38:06 +05302/*
3 * (C) Copyright 2013 Xilinx, Inc.
4 * (C) Copyright 2015 Jagan Teki <jteki@openedev.com>
5 *
6 * Xilinx Zynq Quad-SPI(QSPI) controller driver (master mode only)
Jagan Teki7fbea8a2015-08-17 18:38:06 +05307 */
8
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -07009#include <clk.h>
Jagan Teki7fbea8a2015-08-17 18:38:06 +053010#include <dm.h>
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -070011#include <dm/device_compat.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Jagan Teki7fbea8a2015-08-17 18:38:06 +053013#include <malloc.h>
14#include <spi.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060015#include <asm/global_data.h>
Jagan Teki7fbea8a2015-08-17 18:38:06 +053016#include <asm/io.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060017#include <linux/bitops.h>
T Karthik Reddy7daf8562022-01-30 22:22:40 -070018#include <spi-mem.h>
Jagan Teki7fbea8a2015-08-17 18:38:06 +053019
20DECLARE_GLOBAL_DATA_PTR;
21
22/* zynq qspi register bit masks ZYNQ_QSPI_<REG>_<BIT>_MASK */
Jagan Tekif94b3f72015-10-22 20:40:16 +053023#define ZYNQ_QSPI_CR_IFMODE_MASK BIT(31) /* Flash intrface mode*/
24#define ZYNQ_QSPI_CR_MSA_MASK BIT(15) /* Manual start enb */
25#define ZYNQ_QSPI_CR_MCS_MASK BIT(14) /* Manual chip select */
26#define ZYNQ_QSPI_CR_PCS_MASK BIT(10) /* Peri chip select */
Jagan Tekie1af6ae2015-10-22 21:06:37 +053027#define ZYNQ_QSPI_CR_FW_MASK GENMASK(7, 6) /* FIFO width */
28#define ZYNQ_QSPI_CR_SS_MASK GENMASK(13, 10) /* Slave Select */
29#define ZYNQ_QSPI_CR_BAUD_MASK GENMASK(5, 3) /* Baud rate div */
Jagan Tekif94b3f72015-10-22 20:40:16 +053030#define ZYNQ_QSPI_CR_CPHA_MASK BIT(2) /* Clock phase */
31#define ZYNQ_QSPI_CR_CPOL_MASK BIT(1) /* Clock polarity */
32#define ZYNQ_QSPI_CR_MSTREN_MASK BIT(0) /* Mode select */
33#define ZYNQ_QSPI_IXR_RXNEMPTY_MASK BIT(4) /* RX_FIFO_not_empty */
34#define ZYNQ_QSPI_IXR_TXOW_MASK BIT(2) /* TX_FIFO_not_full */
Jagan Tekie1af6ae2015-10-22 21:06:37 +053035#define ZYNQ_QSPI_IXR_ALL_MASK GENMASK(6, 0) /* All IXR bits */
Jagan Tekif94b3f72015-10-22 20:40:16 +053036#define ZYNQ_QSPI_ENR_SPI_EN_MASK BIT(0) /* SPI Enable */
Nathan Rossib1150782015-12-09 00:44:40 +100037#define ZYNQ_QSPI_LQSPICFG_LQMODE_MASK BIT(31) /* Linear QSPI Mode */
Jagan Teki7fbea8a2015-08-17 18:38:06 +053038
39/* zynq qspi Transmit Data Register */
40#define ZYNQ_QSPI_TXD_00_00_OFFSET 0x1C /* Transmit 4-byte inst */
41#define ZYNQ_QSPI_TXD_00_01_OFFSET 0x80 /* Transmit 1-byte inst */
42#define ZYNQ_QSPI_TXD_00_10_OFFSET 0x84 /* Transmit 2-byte inst */
43#define ZYNQ_QSPI_TXD_00_11_OFFSET 0x88 /* Transmit 3-byte inst */
44
45#define ZYNQ_QSPI_TXFIFO_THRESHOLD 1 /* Tx FIFO threshold level*/
46#define ZYNQ_QSPI_RXFIFO_THRESHOLD 32 /* Rx FIFO threshold level */
47
48#define ZYNQ_QSPI_CR_BAUD_MAX 8 /* Baud rate divisor max val */
49#define ZYNQ_QSPI_CR_BAUD_SHIFT 3 /* Baud rate divisor shift */
50#define ZYNQ_QSPI_CR_SS_SHIFT 10 /* Slave select shift */
51
Siva Durga Prasad Paladugu4495fd62022-01-30 22:22:39 -070052#define ZYNQ_QSPI_MAX_BAUD_RATE 0x7
53#define ZYNQ_QSPI_DEFAULT_BAUD_RATE 0x2
54
Jagan Teki7fbea8a2015-08-17 18:38:06 +053055#define ZYNQ_QSPI_FIFO_DEPTH 63
Ashok Reddy Somacaecfe62020-05-18 01:11:00 -060056#define ZYNQ_QSPI_WAIT (CONFIG_SYS_HZ / 100) /* 10 ms */
Jagan Teki7fbea8a2015-08-17 18:38:06 +053057
58/* zynq qspi register set */
59struct zynq_qspi_regs {
60 u32 cr; /* 0x00 */
61 u32 isr; /* 0x04 */
62 u32 ier; /* 0x08 */
63 u32 idr; /* 0x0C */
64 u32 imr; /* 0x10 */
65 u32 enr; /* 0x14 */
66 u32 dr; /* 0x18 */
67 u32 txd0r; /* 0x1C */
68 u32 drxr; /* 0x20 */
69 u32 sicr; /* 0x24 */
70 u32 txftr; /* 0x28 */
71 u32 rxftr; /* 0x2C */
72 u32 gpior; /* 0x30 */
73 u32 reserved0[19];
74 u32 txd1r; /* 0x80 */
75 u32 txd2r; /* 0x84 */
76 u32 txd3r; /* 0x88 */
Nathan Rossib1150782015-12-09 00:44:40 +100077 u32 reserved1[5];
78 u32 lqspicfg; /* 0xA0 */
79 u32 lqspists; /* 0xA4 */
Jagan Teki7fbea8a2015-08-17 18:38:06 +053080};
81
82/* zynq qspi platform data */
Simon Glassb75b15b2020-12-03 16:55:23 -070083struct zynq_qspi_plat {
Jagan Teki7fbea8a2015-08-17 18:38:06 +053084 struct zynq_qspi_regs *regs;
85 u32 frequency; /* input frequency */
86 u32 speed_hz;
87};
88
89/* zynq qspi priv */
90struct zynq_qspi_priv {
91 struct zynq_qspi_regs *regs;
92 u8 cs;
93 u8 mode;
94 u8 fifo_depth;
95 u32 freq; /* required frequency */
Siva Durga Prasad Paladugu4ebe3a02022-07-15 19:31:16 +053096 u32 max_hz;
Jagan Teki7fbea8a2015-08-17 18:38:06 +053097 const void *tx_buf;
98 void *rx_buf;
99 unsigned len;
100 int bytes_to_transfer;
101 int bytes_to_receive;
102 unsigned int is_inst;
103 unsigned cs_change:1;
104};
105
Simon Glassaad29ae2020-12-03 16:55:21 -0700106static int zynq_qspi_of_to_plat(struct udevice *bus)
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530107{
Simon Glass95588622020-12-22 19:30:28 -0700108 struct zynq_qspi_plat *plat = dev_get_plat(bus);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530109 const void *blob = gd->fdt_blob;
Simon Glassdd79d6e2017-01-17 16:52:55 -0700110 int node = dev_of_offset(bus);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530111
112 plat->regs = (struct zynq_qspi_regs *)fdtdec_get_addr(blob,
113 node, "reg");
114
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530115 return 0;
116}
117
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700118/**
119 * zynq_qspi_init_hw - Initialize the hardware
120 * @priv: Pointer to the zynq_qspi_priv structure
121 *
122 * The default settings of the QSPI controller's configurable parameters on
123 * reset are
124 * - Master mode
125 * - Baud rate divisor is set to 2
126 * - Threshold value for TX FIFO not full interrupt is set to 1
127 * - Flash memory interface mode enabled
128 * - Size of the word to be transferred as 8 bit
129 * This function performs the following actions
130 * - Disable and clear all the interrupts
131 * - Enable manual slave select
132 * - Enable auto start
133 * - Deselect all the chip select lines
134 * - Set the size of the word to be transferred as 32 bit
135 * - Set the little endian mode of TX FIFO and
136 * - Enable the QSPI controller
137 */
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530138static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv)
139{
140 struct zynq_qspi_regs *regs = priv->regs;
141 u32 confr;
142
143 /* Disable QSPI */
144 writel(~ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
145
146 /* Disable Interrupts */
147 writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->idr);
148
149 /* Clear the TX and RX threshold reg */
150 writel(ZYNQ_QSPI_TXFIFO_THRESHOLD, &regs->txftr);
151 writel(ZYNQ_QSPI_RXFIFO_THRESHOLD, &regs->rxftr);
152
153 /* Clear the RX FIFO */
154 while (readl(&regs->isr) & ZYNQ_QSPI_IXR_RXNEMPTY_MASK)
155 readl(&regs->drxr);
156
157 /* Clear Interrupts */
158 writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->isr);
159
160 /* Manual slave select and Auto start */
161 confr = readl(&regs->cr);
162 confr &= ~ZYNQ_QSPI_CR_MSA_MASK;
163 confr |= ZYNQ_QSPI_CR_IFMODE_MASK | ZYNQ_QSPI_CR_MCS_MASK |
164 ZYNQ_QSPI_CR_PCS_MASK | ZYNQ_QSPI_CR_FW_MASK |
165 ZYNQ_QSPI_CR_MSTREN_MASK;
166 writel(confr, &regs->cr);
167
Nathan Rossib1150782015-12-09 00:44:40 +1000168 /* Disable the LQSPI feature */
169 confr = readl(&regs->lqspicfg);
170 confr &= ~ZYNQ_QSPI_LQSPICFG_LQMODE_MASK;
171 writel(confr, &regs->lqspicfg);
172
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530173 /* Enable SPI */
174 writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
175}
176
Siva Durga Prasad Paladugu4ebe3a02022-07-15 19:31:16 +0530177static int zynq_qspi_child_pre_probe(struct udevice *bus)
178{
179 struct spi_slave *slave = dev_get_parent_priv(bus);
180 struct zynq_qspi_priv *priv = dev_get_priv(bus->parent);
181
182 priv->max_hz = slave->max_hz;
183
184 return 0;
185}
186
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530187static int zynq_qspi_probe(struct udevice *bus)
188{
Simon Glassb75b15b2020-12-03 16:55:23 -0700189 struct zynq_qspi_plat *plat = dev_get_plat(bus);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530190 struct zynq_qspi_priv *priv = dev_get_priv(bus);
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -0700191 struct clk clk;
192 unsigned long clock;
193 int ret;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530194
195 priv->regs = plat->regs;
196 priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH;
197
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -0700198 ret = clk_get_by_name(bus, "ref_clk", &clk);
199 if (ret < 0) {
200 dev_err(bus, "failed to get clock\n");
201 return ret;
202 }
203
204 clock = clk_get_rate(&clk);
205 if (IS_ERR_VALUE(clock)) {
206 dev_err(bus, "failed to get rate\n");
207 return clock;
208 }
209
210 ret = clk_enable(&clk);
Michal Simek41710952021-02-09 15:28:15 +0100211 if (ret) {
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -0700212 dev_err(bus, "failed to enable clock\n");
213 return ret;
214 }
215
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530216 /* init the zynq spi hw */
217 zynq_qspi_init_hw(priv);
218
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -0700219 plat->frequency = clock;
220 plat->speed_hz = plat->frequency / 2;
221
222 debug("%s: max-frequency=%d\n", __func__, plat->speed_hz);
223
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530224 return 0;
225}
226
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700227/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530228 * zynq_qspi_read_data - Copy data to RX buffer
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700229 * @priv: Pointer to the zynq_qspi_priv structure
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530230 * @data: The 32 bit variable where data is stored
231 * @size: Number of bytes to be copied from data to RX buffer
232 */
233static void zynq_qspi_read_data(struct zynq_qspi_priv *priv, u32 data, u8 size)
234{
235 u8 byte3;
236
237 debug("%s: data 0x%04x rx_buf addr: 0x%08x size %d\n", __func__ ,
238 data, (unsigned)(priv->rx_buf), size);
239
240 if (priv->rx_buf) {
241 switch (size) {
242 case 1:
243 *((u8 *)priv->rx_buf) = data;
244 priv->rx_buf += 1;
245 break;
246 case 2:
Siva Durga Prasad Paladugu99844ac2022-01-30 22:22:37 -0700247 *((u8 *)priv->rx_buf) = data;
248 priv->rx_buf += 1;
249 *((u8 *)priv->rx_buf) = (u8)(data >> 8);
250 priv->rx_buf += 1;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530251 break;
252 case 3:
Siva Durga Prasad Paladugu99844ac2022-01-30 22:22:37 -0700253 *((u8 *)priv->rx_buf) = data;
254 priv->rx_buf += 1;
255 *((u8 *)priv->rx_buf) = (u8)(data >> 8);
256 priv->rx_buf += 1;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530257 byte3 = (u8)(data >> 16);
258 *((u8 *)priv->rx_buf) = byte3;
259 priv->rx_buf += 1;
260 break;
261 case 4:
262 /* Can not assume word aligned buffer */
263 memcpy(priv->rx_buf, &data, size);
264 priv->rx_buf += 4;
265 break;
266 default:
267 /* This will never execute */
268 break;
269 }
270 }
271 priv->bytes_to_receive -= size;
272 if (priv->bytes_to_receive < 0)
273 priv->bytes_to_receive = 0;
274}
275
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700276/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530277 * zynq_qspi_write_data - Copy data from TX buffer
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700278 * @priv: Pointer to the zynq_qspi_priv structure
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530279 * @data: Pointer to the 32 bit variable where data is to be copied
280 * @size: Number of bytes to be copied from TX buffer to data
281 */
282static void zynq_qspi_write_data(struct zynq_qspi_priv *priv,
283 u32 *data, u8 size)
284{
285 if (priv->tx_buf) {
286 switch (size) {
287 case 1:
288 *data = *((u8 *)priv->tx_buf);
289 priv->tx_buf += 1;
290 *data |= 0xFFFFFF00;
291 break;
292 case 2:
Siva Durga Prasad Paladugu5ff1e242022-01-30 22:22:38 -0700293 *data = *((u8 *)priv->tx_buf);
294 priv->tx_buf += 1;
295 *data |= (*((u8 *)priv->tx_buf) << 8);
296 priv->tx_buf += 1;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530297 *data |= 0xFFFF0000;
298 break;
299 case 3:
Siva Durga Prasad Paladugu5ff1e242022-01-30 22:22:38 -0700300 *data = *((u8 *)priv->tx_buf);
301 priv->tx_buf += 1;
302 *data |= (*((u8 *)priv->tx_buf) << 8);
303 priv->tx_buf += 1;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530304 *data |= (*((u8 *)priv->tx_buf) << 16);
305 priv->tx_buf += 1;
306 *data |= 0xFF000000;
307 break;
308 case 4:
309 /* Can not assume word aligned buffer */
310 memcpy(data, priv->tx_buf, size);
311 priv->tx_buf += 4;
312 break;
313 default:
314 /* This will never execute */
315 break;
316 }
317 } else {
318 *data = 0;
319 }
320
321 debug("%s: data 0x%08x tx_buf addr: 0x%08x size %d\n", __func__,
322 *data, (u32)priv->tx_buf, size);
323
324 priv->bytes_to_transfer -= size;
325 if (priv->bytes_to_transfer < 0)
326 priv->bytes_to_transfer = 0;
327}
328
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700329/**
330 * zynq_qspi_chipselect - Select or deselect the chip select line
331 * @priv: Pointer to the zynq_qspi_priv structure
332 * @is_on: Select(1) or deselect (0) the chip select line
333 */
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530334static void zynq_qspi_chipselect(struct zynq_qspi_priv *priv, int is_on)
335{
336 u32 confr;
337 struct zynq_qspi_regs *regs = priv->regs;
338
339 confr = readl(&regs->cr);
340
341 if (is_on) {
342 /* Select the slave */
343 confr &= ~ZYNQ_QSPI_CR_SS_MASK;
344 confr |= (~(1 << priv->cs) << ZYNQ_QSPI_CR_SS_SHIFT) &
345 ZYNQ_QSPI_CR_SS_MASK;
346 } else
347 /* Deselect the slave */
348 confr |= ZYNQ_QSPI_CR_SS_MASK;
349
350 writel(confr, &regs->cr);
351}
352
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700353/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530354 * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700355 * @priv: Pointer to the zynq_qspi_priv structure
356 * @size: Number of bytes to be copied to fifo
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530357 */
358static void zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv *priv, u32 size)
359{
360 u32 data = 0;
361 u32 fifocount = 0;
362 unsigned len, offset;
363 struct zynq_qspi_regs *regs = priv->regs;
364 static const unsigned offsets[4] = {
365 ZYNQ_QSPI_TXD_00_00_OFFSET, ZYNQ_QSPI_TXD_00_01_OFFSET,
366 ZYNQ_QSPI_TXD_00_10_OFFSET, ZYNQ_QSPI_TXD_00_11_OFFSET };
367
368 while ((fifocount < size) &&
369 (priv->bytes_to_transfer > 0)) {
370 if (priv->bytes_to_transfer >= 4) {
371 if (priv->tx_buf) {
372 memcpy(&data, priv->tx_buf, 4);
373 priv->tx_buf += 4;
374 } else {
375 data = 0;
376 }
377 writel(data, &regs->txd0r);
378 priv->bytes_to_transfer -= 4;
379 fifocount++;
380 } else {
381 /* Write TXD1, TXD2, TXD3 only if TxFIFO is empty. */
382 if (!(readl(&regs->isr)
383 & ZYNQ_QSPI_IXR_TXOW_MASK) &&
384 !priv->rx_buf)
385 return;
386 len = priv->bytes_to_transfer;
387 zynq_qspi_write_data(priv, &data, len);
388 offset = (priv->rx_buf) ? offsets[0] : offsets[len];
389 writel(data, &regs->cr + (offset / 4));
390 }
391 }
392}
393
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700394/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530395 * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700396 * @priv: Pointer to the zynq_qspi structure
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530397 *
398 * This function handles TX empty and Mode Fault interrupts only.
399 * On TX empty interrupt this function reads the received data from RX FIFO and
400 * fills the TX FIFO if there is any data remaining to be transferred.
401 * On Mode Fault interrupt this function indicates that transfer is completed,
402 * the SPI subsystem will identify the error as the remaining bytes to be
403 * transferred is non-zero.
404 *
405 * returns: 0 for poll timeout
406 * 1 transfer operation complete
407 */
408static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv)
409{
410 struct zynq_qspi_regs *regs = priv->regs;
411 u32 rxindex = 0;
412 u32 rxcount;
413 u32 status, timeout;
414
415 /* Poll until any of the interrupt status bits are set */
416 timeout = get_timer(0);
417 do {
418 status = readl(&regs->isr);
419 } while ((status == 0) &&
Ashok Reddy Somacaecfe62020-05-18 01:11:00 -0600420 (get_timer(timeout) < ZYNQ_QSPI_WAIT));
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530421
422 if (status == 0) {
423 printf("zynq_qspi_irq_poll: Timeout!\n");
424 return -ETIMEDOUT;
425 }
426
427 writel(status, &regs->isr);
428
429 /* Disable all interrupts */
430 writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->idr);
431 if ((status & ZYNQ_QSPI_IXR_TXOW_MASK) ||
432 (status & ZYNQ_QSPI_IXR_RXNEMPTY_MASK)) {
433 /*
434 * This bit is set when Tx FIFO has < THRESHOLD entries. We have
435 * the THRESHOLD value set to 1, so this bit indicates Tx FIFO
436 * is empty
437 */
438 rxcount = priv->bytes_to_receive - priv->bytes_to_transfer;
439 rxcount = (rxcount % 4) ? ((rxcount/4)+1) : (rxcount/4);
440 while ((rxindex < rxcount) &&
441 (rxindex < ZYNQ_QSPI_RXFIFO_THRESHOLD)) {
442 /* Read out the data from the RX FIFO */
443 u32 data;
444 data = readl(&regs->drxr);
445
446 if (priv->bytes_to_receive >= 4) {
447 if (priv->rx_buf) {
448 memcpy(priv->rx_buf, &data, 4);
449 priv->rx_buf += 4;
450 }
451 priv->bytes_to_receive -= 4;
452 } else {
453 zynq_qspi_read_data(priv, data,
454 priv->bytes_to_receive);
455 }
456 rxindex++;
457 }
458
459 if (priv->bytes_to_transfer) {
460 /* There is more data to send */
461 zynq_qspi_fill_tx_fifo(priv,
462 ZYNQ_QSPI_RXFIFO_THRESHOLD);
463
464 writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
465 } else {
466 /*
467 * If transfer and receive is completed then only send
468 * complete signal
469 */
470 if (!priv->bytes_to_receive) {
471 /* return operation complete */
472 writel(ZYNQ_QSPI_IXR_ALL_MASK,
473 &regs->idr);
474 return 1;
475 }
476 }
477 }
478
479 return 0;
480}
481
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700482/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530483 * zynq_qspi_start_transfer - Initiates the QSPI transfer
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700484 * @priv: Pointer to the zynq_qspi_priv structure
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530485 *
486 * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
487 * transfer to be completed.
488 *
489 * returns: Number of bytes transferred in the last transfer
490 */
491static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv)
492{
493 u32 data = 0;
494 struct zynq_qspi_regs *regs = priv->regs;
495
496 debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__,
497 (u32)priv, (u32)priv, priv->len);
498
499 priv->bytes_to_transfer = priv->len;
500 priv->bytes_to_receive = priv->len;
501
502 if (priv->len < 4)
503 zynq_qspi_fill_tx_fifo(priv, priv->len);
504 else
505 zynq_qspi_fill_tx_fifo(priv, priv->fifo_depth);
506
507 writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530508
509 /* wait for completion */
510 do {
511 data = zynq_qspi_irq_poll(priv);
512 } while (data == 0);
513
514 return (priv->len) - (priv->bytes_to_transfer);
515}
516
517static int zynq_qspi_transfer(struct zynq_qspi_priv *priv)
518{
519 unsigned cs_change = 1;
520 int status = 0;
521
522 while (1) {
523 /* Select the chip if required */
524 if (cs_change)
525 zynq_qspi_chipselect(priv, 1);
526
527 cs_change = priv->cs_change;
528
529 if (!priv->tx_buf && !priv->rx_buf && priv->len) {
530 status = -1;
531 break;
532 }
533
534 /* Request the transfer */
535 if (priv->len) {
536 status = zynq_qspi_start_transfer(priv);
537 priv->is_inst = 0;
538 }
539
540 if (status != priv->len) {
541 if (status > 0)
542 status = -EMSGSIZE;
543 debug("zynq_qspi_transfer:%d len:%d\n",
544 status, priv->len);
545 break;
546 }
547 status = 0;
548
549 if (cs_change)
550 /* Deselect the chip */
551 zynq_qspi_chipselect(priv, 0);
552
553 break;
554 }
555
Vipul Kumar72cf0c92018-06-25 14:13:57 +0530556 return status;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530557}
558
559static int zynq_qspi_claim_bus(struct udevice *dev)
560{
561 struct udevice *bus = dev->parent;
562 struct zynq_qspi_priv *priv = dev_get_priv(bus);
563 struct zynq_qspi_regs *regs = priv->regs;
564
565 writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
566
567 return 0;
568}
569
570static int zynq_qspi_release_bus(struct udevice *dev)
571{
572 struct udevice *bus = dev->parent;
573 struct zynq_qspi_priv *priv = dev_get_priv(bus);
574 struct zynq_qspi_regs *regs = priv->regs;
575
576 writel(~ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
577
578 return 0;
579}
580
581static int zynq_qspi_xfer(struct udevice *dev, unsigned int bitlen,
582 const void *dout, void *din, unsigned long flags)
583{
584 struct udevice *bus = dev->parent;
585 struct zynq_qspi_priv *priv = dev_get_priv(bus);
Simon Glassb75b15b2020-12-03 16:55:23 -0700586 struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530587
588 priv->cs = slave_plat->cs;
589 priv->tx_buf = dout;
590 priv->rx_buf = din;
591 priv->len = bitlen / 8;
592
Jagan Tekicc7ae3d2015-10-25 09:31:54 +0530593 debug("zynq_qspi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
Simon Glass75e534b2020-12-16 21:20:07 -0700594 dev_seq(bus), slave_plat->cs, bitlen, priv->len, flags);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530595
596 /*
597 * Festering sore.
598 * Assume that the beginning of a transfer with bits to
599 * transmit must contain a device command.
600 */
601 if (dout && flags & SPI_XFER_BEGIN)
602 priv->is_inst = 1;
603 else
604 priv->is_inst = 0;
605
606 if (flags & SPI_XFER_END)
607 priv->cs_change = 1;
608 else
609 priv->cs_change = 0;
610
611 zynq_qspi_transfer(priv);
612
613 return 0;
614}
615
616static int zynq_qspi_set_speed(struct udevice *bus, uint speed)
617{
Simon Glass95588622020-12-22 19:30:28 -0700618 struct zynq_qspi_plat *plat = dev_get_plat(bus);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530619 struct zynq_qspi_priv *priv = dev_get_priv(bus);
620 struct zynq_qspi_regs *regs = priv->regs;
621 uint32_t confr;
622 u8 baud_rate_val = 0;
623
Ashok Reddy Soma24109742022-07-15 19:31:19 +0530624 if (!speed || speed > priv->max_hz)
625 speed = priv->max_hz;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530626
627 /* Set the clock frequency */
628 confr = readl(&regs->cr);
Ashok Reddy Soma24109742022-07-15 19:31:19 +0530629 if (plat->speed_hz != speed) {
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530630 while ((baud_rate_val < ZYNQ_QSPI_CR_BAUD_MAX) &&
631 ((plat->frequency /
632 (2 << baud_rate_val)) > speed))
633 baud_rate_val++;
634
Siva Durga Prasad Paladugu4495fd62022-01-30 22:22:39 -0700635 if (baud_rate_val > ZYNQ_QSPI_MAX_BAUD_RATE)
636 baud_rate_val = ZYNQ_QSPI_DEFAULT_BAUD_RATE;
637
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530638 plat->speed_hz = speed / (2 << baud_rate_val);
639 }
640 confr &= ~ZYNQ_QSPI_CR_BAUD_MASK;
641 confr |= (baud_rate_val << ZYNQ_QSPI_CR_BAUD_SHIFT);
642
643 writel(confr, &regs->cr);
644 priv->freq = speed;
645
Jagan Tekicc7ae3d2015-10-25 09:31:54 +0530646 debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530647
648 return 0;
649}
650
651static int zynq_qspi_set_mode(struct udevice *bus, uint mode)
652{
653 struct zynq_qspi_priv *priv = dev_get_priv(bus);
654 struct zynq_qspi_regs *regs = priv->regs;
655 uint32_t confr;
656
657 /* Set the SPI Clock phase and polarities */
658 confr = readl(&regs->cr);
659 confr &= ~(ZYNQ_QSPI_CR_CPHA_MASK | ZYNQ_QSPI_CR_CPOL_MASK);
660
Jagan Tekic27f1c12015-09-08 01:39:44 +0530661 if (mode & SPI_CPHA)
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530662 confr |= ZYNQ_QSPI_CR_CPHA_MASK;
Jagan Tekic27f1c12015-09-08 01:39:44 +0530663 if (mode & SPI_CPOL)
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530664 confr |= ZYNQ_QSPI_CR_CPOL_MASK;
665
666 writel(confr, &regs->cr);
667 priv->mode = mode;
668
Jagan Tekicc7ae3d2015-10-25 09:31:54 +0530669 debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530670
671 return 0;
672}
673
T Karthik Reddy7daf8562022-01-30 22:22:40 -0700674static int zynq_qspi_exec_op(struct spi_slave *slave,
675 const struct spi_mem_op *op)
676{
677 int op_len, pos = 0, ret, i;
678 unsigned int flag = 0;
679 const u8 *tx_buf = NULL;
680 u8 *rx_buf = NULL;
681
682 if (op->data.nbytes) {
683 if (op->data.dir == SPI_MEM_DATA_IN)
684 rx_buf = op->data.buf.in;
685 else
686 tx_buf = op->data.buf.out;
687 }
688
689 op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
690
691 u8 op_buf[op_len];
692
693 op_buf[pos++] = op->cmd.opcode;
694
695 if (op->addr.nbytes) {
696 for (i = 0; i < op->addr.nbytes; i++)
697 op_buf[pos + i] = op->addr.val >>
698 (8 * (op->addr.nbytes - i - 1));
699
700 pos += op->addr.nbytes;
701 }
702
Stefan Herbrechtsmeier139ec862023-04-27 08:53:54 +0200703 if (op->dummy.nbytes)
704 memset(op_buf + pos, 0xff, op->dummy.nbytes);
T Karthik Reddy7daf8562022-01-30 22:22:40 -0700705
706 /* 1st transfer: opcode + address + dummy cycles */
707 /* Make sure to set END bit if no tx or rx data messages follow */
708 if (!tx_buf && !rx_buf)
709 flag |= SPI_XFER_END;
710
711 ret = zynq_qspi_xfer(slave->dev, op_len * 8, op_buf, NULL,
712 flag | SPI_XFER_BEGIN);
713 if (ret)
714 return ret;
715
716 /* 2nd transfer: rx or tx data path */
717 if (tx_buf || rx_buf) {
718 ret = zynq_qspi_xfer(slave->dev, op->data.nbytes * 8, tx_buf,
719 rx_buf, flag | SPI_XFER_END);
720 if (ret)
721 return ret;
722 }
723
724 spi_release_bus(slave);
725
726 return 0;
727}
728
Ashok Reddy Soma525a8e42022-07-15 19:31:18 +0530729static int zynq_qspi_check_buswidth(struct spi_slave *slave, u8 width)
730{
731 u32 mode = slave->mode;
732
733 switch (width) {
734 case 1:
735 return 0;
736 case 2:
737 if (mode & SPI_RX_DUAL)
738 return 0;
739 break;
740 case 4:
741 if (mode & SPI_RX_QUAD)
742 return 0;
743 break;
744 }
745
746 return -EOPNOTSUPP;
747}
748
Algapally Santosh Sagardbf91352023-06-14 03:03:56 -0600749static bool zynq_qspi_mem_exec_op(struct spi_slave *slave,
750 const struct spi_mem_op *op)
Ashok Reddy Soma525a8e42022-07-15 19:31:18 +0530751{
752 if (zynq_qspi_check_buswidth(slave, op->cmd.buswidth))
753 return false;
754
755 if (op->addr.nbytes &&
756 zynq_qspi_check_buswidth(slave, op->addr.buswidth))
757 return false;
758
759 if (op->dummy.nbytes &&
760 zynq_qspi_check_buswidth(slave, op->dummy.buswidth))
761 return false;
762
763 if (op->data.dir != SPI_MEM_NO_DATA &&
764 zynq_qspi_check_buswidth(slave, op->data.buswidth))
765 return false;
766
767 return true;
768}
769
T Karthik Reddy7daf8562022-01-30 22:22:40 -0700770static const struct spi_controller_mem_ops zynq_qspi_mem_ops = {
771 .exec_op = zynq_qspi_exec_op,
Ashok Reddy Soma525a8e42022-07-15 19:31:18 +0530772 .supports_op = zynq_qspi_mem_exec_op,
T Karthik Reddy7daf8562022-01-30 22:22:40 -0700773};
774
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530775static const struct dm_spi_ops zynq_qspi_ops = {
776 .claim_bus = zynq_qspi_claim_bus,
777 .release_bus = zynq_qspi_release_bus,
778 .xfer = zynq_qspi_xfer,
779 .set_speed = zynq_qspi_set_speed,
780 .set_mode = zynq_qspi_set_mode,
T Karthik Reddy7daf8562022-01-30 22:22:40 -0700781 .mem_ops = &zynq_qspi_mem_ops,
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530782};
783
784static const struct udevice_id zynq_qspi_ids[] = {
785 { .compatible = "xlnx,zynq-qspi-1.0" },
786 { }
787};
788
789U_BOOT_DRIVER(zynq_qspi) = {
790 .name = "zynq_qspi",
791 .id = UCLASS_SPI,
792 .of_match = zynq_qspi_ids,
793 .ops = &zynq_qspi_ops,
Simon Glassaad29ae2020-12-03 16:55:21 -0700794 .of_to_plat = zynq_qspi_of_to_plat,
Simon Glassb75b15b2020-12-03 16:55:23 -0700795 .plat_auto = sizeof(struct zynq_qspi_plat),
Simon Glass8a2b47f2020-12-03 16:55:17 -0700796 .priv_auto = sizeof(struct zynq_qspi_priv),
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530797 .probe = zynq_qspi_probe,
Siva Durga Prasad Paladugu4ebe3a02022-07-15 19:31:16 +0530798 .child_pre_probe = zynq_qspi_child_pre_probe,
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530799};