blob: b69d992b28abba41cc5326770985224aa748378f [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 <common.h>
11#include <dm.h>
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -070012#include <dm/device_compat.h>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Jagan Teki7fbea8a2015-08-17 18:38:06 +053014#include <malloc.h>
15#include <spi.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060016#include <asm/global_data.h>
Jagan Teki7fbea8a2015-08-17 18:38:06 +053017#include <asm/io.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060018#include <linux/bitops.h>
T Karthik Reddy7daf8562022-01-30 22:22:40 -070019#include <spi-mem.h>
Jagan Teki7fbea8a2015-08-17 18:38:06 +053020
21DECLARE_GLOBAL_DATA_PTR;
22
23/* zynq qspi register bit masks ZYNQ_QSPI_<REG>_<BIT>_MASK */
Jagan Tekif94b3f72015-10-22 20:40:16 +053024#define ZYNQ_QSPI_CR_IFMODE_MASK BIT(31) /* Flash intrface mode*/
25#define ZYNQ_QSPI_CR_MSA_MASK BIT(15) /* Manual start enb */
26#define ZYNQ_QSPI_CR_MCS_MASK BIT(14) /* Manual chip select */
27#define ZYNQ_QSPI_CR_PCS_MASK BIT(10) /* Peri chip select */
Jagan Tekie1af6ae2015-10-22 21:06:37 +053028#define ZYNQ_QSPI_CR_FW_MASK GENMASK(7, 6) /* FIFO width */
29#define ZYNQ_QSPI_CR_SS_MASK GENMASK(13, 10) /* Slave Select */
30#define ZYNQ_QSPI_CR_BAUD_MASK GENMASK(5, 3) /* Baud rate div */
Jagan Tekif94b3f72015-10-22 20:40:16 +053031#define ZYNQ_QSPI_CR_CPHA_MASK BIT(2) /* Clock phase */
32#define ZYNQ_QSPI_CR_CPOL_MASK BIT(1) /* Clock polarity */
33#define ZYNQ_QSPI_CR_MSTREN_MASK BIT(0) /* Mode select */
34#define ZYNQ_QSPI_IXR_RXNEMPTY_MASK BIT(4) /* RX_FIFO_not_empty */
35#define ZYNQ_QSPI_IXR_TXOW_MASK BIT(2) /* TX_FIFO_not_full */
Jagan Tekie1af6ae2015-10-22 21:06:37 +053036#define ZYNQ_QSPI_IXR_ALL_MASK GENMASK(6, 0) /* All IXR bits */
Jagan Tekif94b3f72015-10-22 20:40:16 +053037#define ZYNQ_QSPI_ENR_SPI_EN_MASK BIT(0) /* SPI Enable */
Nathan Rossib1150782015-12-09 00:44:40 +100038#define ZYNQ_QSPI_LQSPICFG_LQMODE_MASK BIT(31) /* Linear QSPI Mode */
Jagan Teki7fbea8a2015-08-17 18:38:06 +053039
40/* zynq qspi Transmit Data Register */
41#define ZYNQ_QSPI_TXD_00_00_OFFSET 0x1C /* Transmit 4-byte inst */
42#define ZYNQ_QSPI_TXD_00_01_OFFSET 0x80 /* Transmit 1-byte inst */
43#define ZYNQ_QSPI_TXD_00_10_OFFSET 0x84 /* Transmit 2-byte inst */
44#define ZYNQ_QSPI_TXD_00_11_OFFSET 0x88 /* Transmit 3-byte inst */
45
46#define ZYNQ_QSPI_TXFIFO_THRESHOLD 1 /* Tx FIFO threshold level*/
47#define ZYNQ_QSPI_RXFIFO_THRESHOLD 32 /* Rx FIFO threshold level */
48
49#define ZYNQ_QSPI_CR_BAUD_MAX 8 /* Baud rate divisor max val */
50#define ZYNQ_QSPI_CR_BAUD_SHIFT 3 /* Baud rate divisor shift */
51#define ZYNQ_QSPI_CR_SS_SHIFT 10 /* Slave select shift */
52
Siva Durga Prasad Paladugu4495fd62022-01-30 22:22:39 -070053#define ZYNQ_QSPI_MAX_BAUD_RATE 0x7
54#define ZYNQ_QSPI_DEFAULT_BAUD_RATE 0x2
55
Jagan Teki7fbea8a2015-08-17 18:38:06 +053056#define ZYNQ_QSPI_FIFO_DEPTH 63
Ashok Reddy Somacaecfe62020-05-18 01:11:00 -060057#define ZYNQ_QSPI_WAIT (CONFIG_SYS_HZ / 100) /* 10 ms */
Jagan Teki7fbea8a2015-08-17 18:38:06 +053058
59/* zynq qspi register set */
60struct zynq_qspi_regs {
61 u32 cr; /* 0x00 */
62 u32 isr; /* 0x04 */
63 u32 ier; /* 0x08 */
64 u32 idr; /* 0x0C */
65 u32 imr; /* 0x10 */
66 u32 enr; /* 0x14 */
67 u32 dr; /* 0x18 */
68 u32 txd0r; /* 0x1C */
69 u32 drxr; /* 0x20 */
70 u32 sicr; /* 0x24 */
71 u32 txftr; /* 0x28 */
72 u32 rxftr; /* 0x2C */
73 u32 gpior; /* 0x30 */
74 u32 reserved0[19];
75 u32 txd1r; /* 0x80 */
76 u32 txd2r; /* 0x84 */
77 u32 txd3r; /* 0x88 */
Nathan Rossib1150782015-12-09 00:44:40 +100078 u32 reserved1[5];
79 u32 lqspicfg; /* 0xA0 */
80 u32 lqspists; /* 0xA4 */
Jagan Teki7fbea8a2015-08-17 18:38:06 +053081};
82
83/* zynq qspi platform data */
Simon Glassb75b15b2020-12-03 16:55:23 -070084struct zynq_qspi_plat {
Jagan Teki7fbea8a2015-08-17 18:38:06 +053085 struct zynq_qspi_regs *regs;
86 u32 frequency; /* input frequency */
87 u32 speed_hz;
88};
89
90/* zynq qspi priv */
91struct zynq_qspi_priv {
92 struct zynq_qspi_regs *regs;
93 u8 cs;
94 u8 mode;
95 u8 fifo_depth;
96 u32 freq; /* required frequency */
97 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
177static int zynq_qspi_probe(struct udevice *bus)
178{
Simon Glassb75b15b2020-12-03 16:55:23 -0700179 struct zynq_qspi_plat *plat = dev_get_plat(bus);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530180 struct zynq_qspi_priv *priv = dev_get_priv(bus);
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -0700181 struct clk clk;
182 unsigned long clock;
183 int ret;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530184
185 priv->regs = plat->regs;
186 priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH;
187
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -0700188 ret = clk_get_by_name(bus, "ref_clk", &clk);
189 if (ret < 0) {
190 dev_err(bus, "failed to get clock\n");
191 return ret;
192 }
193
194 clock = clk_get_rate(&clk);
195 if (IS_ERR_VALUE(clock)) {
196 dev_err(bus, "failed to get rate\n");
197 return clock;
198 }
199
200 ret = clk_enable(&clk);
Michal Simek41710952021-02-09 15:28:15 +0100201 if (ret) {
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -0700202 dev_err(bus, "failed to enable clock\n");
203 return ret;
204 }
205
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530206 /* init the zynq spi hw */
207 zynq_qspi_init_hw(priv);
208
T Karthik Reddyb1f0d3d2020-02-04 05:47:45 -0700209 plat->frequency = clock;
210 plat->speed_hz = plat->frequency / 2;
211
212 debug("%s: max-frequency=%d\n", __func__, plat->speed_hz);
213
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530214 return 0;
215}
216
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700217/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530218 * zynq_qspi_read_data - Copy data to RX buffer
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700219 * @priv: Pointer to the zynq_qspi_priv structure
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530220 * @data: The 32 bit variable where data is stored
221 * @size: Number of bytes to be copied from data to RX buffer
222 */
223static void zynq_qspi_read_data(struct zynq_qspi_priv *priv, u32 data, u8 size)
224{
225 u8 byte3;
226
227 debug("%s: data 0x%04x rx_buf addr: 0x%08x size %d\n", __func__ ,
228 data, (unsigned)(priv->rx_buf), size);
229
230 if (priv->rx_buf) {
231 switch (size) {
232 case 1:
233 *((u8 *)priv->rx_buf) = data;
234 priv->rx_buf += 1;
235 break;
236 case 2:
Siva Durga Prasad Paladugu99844ac2022-01-30 22:22:37 -0700237 *((u8 *)priv->rx_buf) = data;
238 priv->rx_buf += 1;
239 *((u8 *)priv->rx_buf) = (u8)(data >> 8);
240 priv->rx_buf += 1;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530241 break;
242 case 3:
Siva Durga Prasad Paladugu99844ac2022-01-30 22:22:37 -0700243 *((u8 *)priv->rx_buf) = data;
244 priv->rx_buf += 1;
245 *((u8 *)priv->rx_buf) = (u8)(data >> 8);
246 priv->rx_buf += 1;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530247 byte3 = (u8)(data >> 16);
248 *((u8 *)priv->rx_buf) = byte3;
249 priv->rx_buf += 1;
250 break;
251 case 4:
252 /* Can not assume word aligned buffer */
253 memcpy(priv->rx_buf, &data, size);
254 priv->rx_buf += 4;
255 break;
256 default:
257 /* This will never execute */
258 break;
259 }
260 }
261 priv->bytes_to_receive -= size;
262 if (priv->bytes_to_receive < 0)
263 priv->bytes_to_receive = 0;
264}
265
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700266/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530267 * zynq_qspi_write_data - Copy data from TX buffer
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700268 * @priv: Pointer to the zynq_qspi_priv structure
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530269 * @data: Pointer to the 32 bit variable where data is to be copied
270 * @size: Number of bytes to be copied from TX buffer to data
271 */
272static void zynq_qspi_write_data(struct zynq_qspi_priv *priv,
273 u32 *data, u8 size)
274{
275 if (priv->tx_buf) {
276 switch (size) {
277 case 1:
278 *data = *((u8 *)priv->tx_buf);
279 priv->tx_buf += 1;
280 *data |= 0xFFFFFF00;
281 break;
282 case 2:
Siva Durga Prasad Paladugu5ff1e242022-01-30 22:22:38 -0700283 *data = *((u8 *)priv->tx_buf);
284 priv->tx_buf += 1;
285 *data |= (*((u8 *)priv->tx_buf) << 8);
286 priv->tx_buf += 1;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530287 *data |= 0xFFFF0000;
288 break;
289 case 3:
Siva Durga Prasad Paladugu5ff1e242022-01-30 22:22:38 -0700290 *data = *((u8 *)priv->tx_buf);
291 priv->tx_buf += 1;
292 *data |= (*((u8 *)priv->tx_buf) << 8);
293 priv->tx_buf += 1;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530294 *data |= (*((u8 *)priv->tx_buf) << 16);
295 priv->tx_buf += 1;
296 *data |= 0xFF000000;
297 break;
298 case 4:
299 /* Can not assume word aligned buffer */
300 memcpy(data, priv->tx_buf, size);
301 priv->tx_buf += 4;
302 break;
303 default:
304 /* This will never execute */
305 break;
306 }
307 } else {
308 *data = 0;
309 }
310
311 debug("%s: data 0x%08x tx_buf addr: 0x%08x size %d\n", __func__,
312 *data, (u32)priv->tx_buf, size);
313
314 priv->bytes_to_transfer -= size;
315 if (priv->bytes_to_transfer < 0)
316 priv->bytes_to_transfer = 0;
317}
318
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700319/**
320 * zynq_qspi_chipselect - Select or deselect the chip select line
321 * @priv: Pointer to the zynq_qspi_priv structure
322 * @is_on: Select(1) or deselect (0) the chip select line
323 */
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530324static void zynq_qspi_chipselect(struct zynq_qspi_priv *priv, int is_on)
325{
326 u32 confr;
327 struct zynq_qspi_regs *regs = priv->regs;
328
329 confr = readl(&regs->cr);
330
331 if (is_on) {
332 /* Select the slave */
333 confr &= ~ZYNQ_QSPI_CR_SS_MASK;
334 confr |= (~(1 << priv->cs) << ZYNQ_QSPI_CR_SS_SHIFT) &
335 ZYNQ_QSPI_CR_SS_MASK;
336 } else
337 /* Deselect the slave */
338 confr |= ZYNQ_QSPI_CR_SS_MASK;
339
340 writel(confr, &regs->cr);
341}
342
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700343/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530344 * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700345 * @priv: Pointer to the zynq_qspi_priv structure
346 * @size: Number of bytes to be copied to fifo
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530347 */
348static void zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv *priv, u32 size)
349{
350 u32 data = 0;
351 u32 fifocount = 0;
352 unsigned len, offset;
353 struct zynq_qspi_regs *regs = priv->regs;
354 static const unsigned offsets[4] = {
355 ZYNQ_QSPI_TXD_00_00_OFFSET, ZYNQ_QSPI_TXD_00_01_OFFSET,
356 ZYNQ_QSPI_TXD_00_10_OFFSET, ZYNQ_QSPI_TXD_00_11_OFFSET };
357
358 while ((fifocount < size) &&
359 (priv->bytes_to_transfer > 0)) {
360 if (priv->bytes_to_transfer >= 4) {
361 if (priv->tx_buf) {
362 memcpy(&data, priv->tx_buf, 4);
363 priv->tx_buf += 4;
364 } else {
365 data = 0;
366 }
367 writel(data, &regs->txd0r);
368 priv->bytes_to_transfer -= 4;
369 fifocount++;
370 } else {
371 /* Write TXD1, TXD2, TXD3 only if TxFIFO is empty. */
372 if (!(readl(&regs->isr)
373 & ZYNQ_QSPI_IXR_TXOW_MASK) &&
374 !priv->rx_buf)
375 return;
376 len = priv->bytes_to_transfer;
377 zynq_qspi_write_data(priv, &data, len);
378 offset = (priv->rx_buf) ? offsets[0] : offsets[len];
379 writel(data, &regs->cr + (offset / 4));
380 }
381 }
382}
383
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700384/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530385 * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700386 * @priv: Pointer to the zynq_qspi structure
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530387 *
388 * This function handles TX empty and Mode Fault interrupts only.
389 * On TX empty interrupt this function reads the received data from RX FIFO and
390 * fills the TX FIFO if there is any data remaining to be transferred.
391 * On Mode Fault interrupt this function indicates that transfer is completed,
392 * the SPI subsystem will identify the error as the remaining bytes to be
393 * transferred is non-zero.
394 *
395 * returns: 0 for poll timeout
396 * 1 transfer operation complete
397 */
398static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv)
399{
400 struct zynq_qspi_regs *regs = priv->regs;
401 u32 rxindex = 0;
402 u32 rxcount;
403 u32 status, timeout;
404
405 /* Poll until any of the interrupt status bits are set */
406 timeout = get_timer(0);
407 do {
408 status = readl(&regs->isr);
409 } while ((status == 0) &&
Ashok Reddy Somacaecfe62020-05-18 01:11:00 -0600410 (get_timer(timeout) < ZYNQ_QSPI_WAIT));
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530411
412 if (status == 0) {
413 printf("zynq_qspi_irq_poll: Timeout!\n");
414 return -ETIMEDOUT;
415 }
416
417 writel(status, &regs->isr);
418
419 /* Disable all interrupts */
420 writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->idr);
421 if ((status & ZYNQ_QSPI_IXR_TXOW_MASK) ||
422 (status & ZYNQ_QSPI_IXR_RXNEMPTY_MASK)) {
423 /*
424 * This bit is set when Tx FIFO has < THRESHOLD entries. We have
425 * the THRESHOLD value set to 1, so this bit indicates Tx FIFO
426 * is empty
427 */
428 rxcount = priv->bytes_to_receive - priv->bytes_to_transfer;
429 rxcount = (rxcount % 4) ? ((rxcount/4)+1) : (rxcount/4);
430 while ((rxindex < rxcount) &&
431 (rxindex < ZYNQ_QSPI_RXFIFO_THRESHOLD)) {
432 /* Read out the data from the RX FIFO */
433 u32 data;
434 data = readl(&regs->drxr);
435
436 if (priv->bytes_to_receive >= 4) {
437 if (priv->rx_buf) {
438 memcpy(priv->rx_buf, &data, 4);
439 priv->rx_buf += 4;
440 }
441 priv->bytes_to_receive -= 4;
442 } else {
443 zynq_qspi_read_data(priv, data,
444 priv->bytes_to_receive);
445 }
446 rxindex++;
447 }
448
449 if (priv->bytes_to_transfer) {
450 /* There is more data to send */
451 zynq_qspi_fill_tx_fifo(priv,
452 ZYNQ_QSPI_RXFIFO_THRESHOLD);
453
454 writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
455 } else {
456 /*
457 * If transfer and receive is completed then only send
458 * complete signal
459 */
460 if (!priv->bytes_to_receive) {
461 /* return operation complete */
462 writel(ZYNQ_QSPI_IXR_ALL_MASK,
463 &regs->idr);
464 return 1;
465 }
466 }
467 }
468
469 return 0;
470}
471
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700472/**
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530473 * zynq_qspi_start_transfer - Initiates the QSPI transfer
Ashok Reddy Soma27e770a2020-01-28 07:39:04 -0700474 * @priv: Pointer to the zynq_qspi_priv structure
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530475 *
476 * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
477 * transfer to be completed.
478 *
479 * returns: Number of bytes transferred in the last transfer
480 */
481static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv)
482{
483 u32 data = 0;
484 struct zynq_qspi_regs *regs = priv->regs;
485
486 debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__,
487 (u32)priv, (u32)priv, priv->len);
488
489 priv->bytes_to_transfer = priv->len;
490 priv->bytes_to_receive = priv->len;
491
492 if (priv->len < 4)
493 zynq_qspi_fill_tx_fifo(priv, priv->len);
494 else
495 zynq_qspi_fill_tx_fifo(priv, priv->fifo_depth);
496
497 writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530498
499 /* wait for completion */
500 do {
501 data = zynq_qspi_irq_poll(priv);
502 } while (data == 0);
503
504 return (priv->len) - (priv->bytes_to_transfer);
505}
506
507static int zynq_qspi_transfer(struct zynq_qspi_priv *priv)
508{
509 unsigned cs_change = 1;
510 int status = 0;
511
512 while (1) {
513 /* Select the chip if required */
514 if (cs_change)
515 zynq_qspi_chipselect(priv, 1);
516
517 cs_change = priv->cs_change;
518
519 if (!priv->tx_buf && !priv->rx_buf && priv->len) {
520 status = -1;
521 break;
522 }
523
524 /* Request the transfer */
525 if (priv->len) {
526 status = zynq_qspi_start_transfer(priv);
527 priv->is_inst = 0;
528 }
529
530 if (status != priv->len) {
531 if (status > 0)
532 status = -EMSGSIZE;
533 debug("zynq_qspi_transfer:%d len:%d\n",
534 status, priv->len);
535 break;
536 }
537 status = 0;
538
539 if (cs_change)
540 /* Deselect the chip */
541 zynq_qspi_chipselect(priv, 0);
542
543 break;
544 }
545
Vipul Kumar72cf0c92018-06-25 14:13:57 +0530546 return status;
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530547}
548
549static int zynq_qspi_claim_bus(struct udevice *dev)
550{
551 struct udevice *bus = dev->parent;
552 struct zynq_qspi_priv *priv = dev_get_priv(bus);
553 struct zynq_qspi_regs *regs = priv->regs;
554
555 writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
556
557 return 0;
558}
559
560static int zynq_qspi_release_bus(struct udevice *dev)
561{
562 struct udevice *bus = dev->parent;
563 struct zynq_qspi_priv *priv = dev_get_priv(bus);
564 struct zynq_qspi_regs *regs = priv->regs;
565
566 writel(~ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
567
568 return 0;
569}
570
571static int zynq_qspi_xfer(struct udevice *dev, unsigned int bitlen,
572 const void *dout, void *din, unsigned long flags)
573{
574 struct udevice *bus = dev->parent;
575 struct zynq_qspi_priv *priv = dev_get_priv(bus);
Simon Glassb75b15b2020-12-03 16:55:23 -0700576 struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530577
578 priv->cs = slave_plat->cs;
579 priv->tx_buf = dout;
580 priv->rx_buf = din;
581 priv->len = bitlen / 8;
582
Jagan Tekicc7ae3d2015-10-25 09:31:54 +0530583 debug("zynq_qspi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
Simon Glass75e534b2020-12-16 21:20:07 -0700584 dev_seq(bus), slave_plat->cs, bitlen, priv->len, flags);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530585
586 /*
587 * Festering sore.
588 * Assume that the beginning of a transfer with bits to
589 * transmit must contain a device command.
590 */
591 if (dout && flags & SPI_XFER_BEGIN)
592 priv->is_inst = 1;
593 else
594 priv->is_inst = 0;
595
596 if (flags & SPI_XFER_END)
597 priv->cs_change = 1;
598 else
599 priv->cs_change = 0;
600
601 zynq_qspi_transfer(priv);
602
603 return 0;
604}
605
606static int zynq_qspi_set_speed(struct udevice *bus, uint speed)
607{
Simon Glass95588622020-12-22 19:30:28 -0700608 struct zynq_qspi_plat *plat = dev_get_plat(bus);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530609 struct zynq_qspi_priv *priv = dev_get_priv(bus);
610 struct zynq_qspi_regs *regs = priv->regs;
611 uint32_t confr;
612 u8 baud_rate_val = 0;
613
614 if (speed > plat->frequency)
615 speed = plat->frequency;
616
617 /* Set the clock frequency */
618 confr = readl(&regs->cr);
619 if (speed == 0) {
620 /* Set baudrate x8, if the freq is 0 */
621 baud_rate_val = 0x2;
622 } else if (plat->speed_hz != speed) {
623 while ((baud_rate_val < ZYNQ_QSPI_CR_BAUD_MAX) &&
624 ((plat->frequency /
625 (2 << baud_rate_val)) > speed))
626 baud_rate_val++;
627
Siva Durga Prasad Paladugu4495fd62022-01-30 22:22:39 -0700628 if (baud_rate_val > ZYNQ_QSPI_MAX_BAUD_RATE)
629 baud_rate_val = ZYNQ_QSPI_DEFAULT_BAUD_RATE;
630
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530631 plat->speed_hz = speed / (2 << baud_rate_val);
632 }
633 confr &= ~ZYNQ_QSPI_CR_BAUD_MASK;
634 confr |= (baud_rate_val << ZYNQ_QSPI_CR_BAUD_SHIFT);
635
636 writel(confr, &regs->cr);
637 priv->freq = speed;
638
Jagan Tekicc7ae3d2015-10-25 09:31:54 +0530639 debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530640
641 return 0;
642}
643
644static int zynq_qspi_set_mode(struct udevice *bus, uint mode)
645{
646 struct zynq_qspi_priv *priv = dev_get_priv(bus);
647 struct zynq_qspi_regs *regs = priv->regs;
648 uint32_t confr;
649
650 /* Set the SPI Clock phase and polarities */
651 confr = readl(&regs->cr);
652 confr &= ~(ZYNQ_QSPI_CR_CPHA_MASK | ZYNQ_QSPI_CR_CPOL_MASK);
653
Jagan Tekic27f1c12015-09-08 01:39:44 +0530654 if (mode & SPI_CPHA)
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530655 confr |= ZYNQ_QSPI_CR_CPHA_MASK;
Jagan Tekic27f1c12015-09-08 01:39:44 +0530656 if (mode & SPI_CPOL)
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530657 confr |= ZYNQ_QSPI_CR_CPOL_MASK;
658
659 writel(confr, &regs->cr);
660 priv->mode = mode;
661
Jagan Tekicc7ae3d2015-10-25 09:31:54 +0530662 debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530663
664 return 0;
665}
666
T Karthik Reddy7daf8562022-01-30 22:22:40 -0700667static int zynq_qspi_exec_op(struct spi_slave *slave,
668 const struct spi_mem_op *op)
669{
670 int op_len, pos = 0, ret, i;
671 unsigned int flag = 0;
672 const u8 *tx_buf = NULL;
673 u8 *rx_buf = NULL;
674
675 if (op->data.nbytes) {
676 if (op->data.dir == SPI_MEM_DATA_IN)
677 rx_buf = op->data.buf.in;
678 else
679 tx_buf = op->data.buf.out;
680 }
681
682 op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
683
684 u8 op_buf[op_len];
685
686 op_buf[pos++] = op->cmd.opcode;
687
688 if (op->addr.nbytes) {
689 for (i = 0; i < op->addr.nbytes; i++)
690 op_buf[pos + i] = op->addr.val >>
691 (8 * (op->addr.nbytes - i - 1));
692
693 pos += op->addr.nbytes;
694 }
695
696 if (op->dummy.nbytes)
697 memset(op_buf + pos, 0xff, op->dummy.nbytes);
698
699 /* 1st transfer: opcode + address + dummy cycles */
700 /* Make sure to set END bit if no tx or rx data messages follow */
701 if (!tx_buf && !rx_buf)
702 flag |= SPI_XFER_END;
703
704 ret = zynq_qspi_xfer(slave->dev, op_len * 8, op_buf, NULL,
705 flag | SPI_XFER_BEGIN);
706 if (ret)
707 return ret;
708
709 /* 2nd transfer: rx or tx data path */
710 if (tx_buf || rx_buf) {
711 ret = zynq_qspi_xfer(slave->dev, op->data.nbytes * 8, tx_buf,
712 rx_buf, flag | SPI_XFER_END);
713 if (ret)
714 return ret;
715 }
716
717 spi_release_bus(slave);
718
719 return 0;
720}
721
722static const struct spi_controller_mem_ops zynq_qspi_mem_ops = {
723 .exec_op = zynq_qspi_exec_op,
724};
725
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530726static const struct dm_spi_ops zynq_qspi_ops = {
727 .claim_bus = zynq_qspi_claim_bus,
728 .release_bus = zynq_qspi_release_bus,
729 .xfer = zynq_qspi_xfer,
730 .set_speed = zynq_qspi_set_speed,
731 .set_mode = zynq_qspi_set_mode,
T Karthik Reddy7daf8562022-01-30 22:22:40 -0700732 .mem_ops = &zynq_qspi_mem_ops,
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530733};
734
735static const struct udevice_id zynq_qspi_ids[] = {
736 { .compatible = "xlnx,zynq-qspi-1.0" },
737 { }
738};
739
740U_BOOT_DRIVER(zynq_qspi) = {
741 .name = "zynq_qspi",
742 .id = UCLASS_SPI,
743 .of_match = zynq_qspi_ids,
744 .ops = &zynq_qspi_ops,
Simon Glassaad29ae2020-12-03 16:55:21 -0700745 .of_to_plat = zynq_qspi_of_to_plat,
Simon Glassb75b15b2020-12-03 16:55:23 -0700746 .plat_auto = sizeof(struct zynq_qspi_plat),
Simon Glass8a2b47f2020-12-03 16:55:17 -0700747 .priv_auto = sizeof(struct zynq_qspi_priv),
Jagan Teki7fbea8a2015-08-17 18:38:06 +0530748 .probe = zynq_qspi_probe,
749};