1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <common.h>
29#include <asm/io.h>
30#include <linux/errno.h>
31#include <wait_bit.h>
32#include <spi.h>
33#include <spi_flash.h>
34#include <malloc.h>
35#include "cadence_qspi.h"
36#include <dm.h>
37
38__weak int spi_nor_wait_till_ready(struct spi_nor *nor)
39{
40 return 0;
41}
42
43__weak int cadence_qspi_apb_dma_read(struct cadence_spi_platdata *plat,
44 unsigned int n_rx, u8 *rxbuf)
45{
46 return 0;
47}
48
49__weak
50int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_platdata *plat)
51{
52 return 0;
53}
54
55static unsigned int cadence_qspi_apb_cmd2addr(const unsigned char *addr_buf,
56 unsigned int addr_width)
57{
58 unsigned int addr;
59
60 addr = (addr_buf[0] << 16) | (addr_buf[1] << 8) | addr_buf[2];
61
62 if (addr_width == 4)
63 addr = (addr << 8) | addr_buf[3];
64
65 return addr;
66}
67
68void cadence_qspi_apb_controller_enable(void *reg_base)
69{
70 unsigned int reg;
71 reg = readl(reg_base + CQSPI_REG_CONFIG);
72 reg |= CQSPI_REG_CONFIG_ENABLE;
73 writel(reg, reg_base + CQSPI_REG_CONFIG);
74}
75
76void cadence_qspi_apb_controller_disable(void *reg_base)
77{
78 unsigned int reg;
79 reg = readl(reg_base + CQSPI_REG_CONFIG);
80 reg &= ~CQSPI_REG_CONFIG_ENABLE;
81 writel(reg, reg_base + CQSPI_REG_CONFIG);
82}
83
84
85static unsigned int cadence_qspi_wait_idle(void *reg_base)
86{
87 unsigned int start, count = 0;
88
89 unsigned int timeout = 5000;
90
91 start = get_timer(0);
92 for ( ; get_timer(start) < timeout ; ) {
93 if (CQSPI_REG_IS_IDLE(reg_base))
94 count++;
95 else
96 count = 0;
97
98
99
100
101 if (count >= CQSPI_POLL_IDLE_RETRY)
102 return 1;
103 }
104
105
106 printf("QSPI: QSPI is still busy after poll for %d times.\n",
107 CQSPI_REG_RETRY);
108 return 0;
109}
110
111void cadence_qspi_apb_readdata_capture(void *reg_base,
112 unsigned int bypass, unsigned int delay)
113{
114 unsigned int reg;
115 cadence_qspi_apb_controller_disable(reg_base);
116
117 reg = readl(reg_base + CQSPI_REG_RD_DATA_CAPTURE);
118
119 if (bypass)
120 reg |= CQSPI_REG_RD_DATA_CAPTURE_BYPASS;
121 else
122 reg &= ~CQSPI_REG_RD_DATA_CAPTURE_BYPASS;
123
124 reg &= ~(CQSPI_REG_RD_DATA_CAPTURE_DELAY_MASK
125 << CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB);
126
127 reg |= (delay & CQSPI_REG_RD_DATA_CAPTURE_DELAY_MASK)
128 << CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB;
129
130 writel(reg, reg_base + CQSPI_REG_RD_DATA_CAPTURE);
131
132 cadence_qspi_apb_controller_enable(reg_base);
133}
134
135void cadence_qspi_apb_config_baudrate_div(void *reg_base,
136 unsigned int ref_clk_hz, unsigned int sclk_hz)
137{
138 unsigned int reg;
139 unsigned int div;
140
141 cadence_qspi_apb_controller_disable(reg_base);
142 reg = readl(reg_base + CQSPI_REG_CONFIG);
143 reg &= ~(CQSPI_REG_CONFIG_BAUD_MASK << CQSPI_REG_CONFIG_BAUD_LSB);
144
145
146
147
148
149
150 div = DIV_ROUND_UP(ref_clk_hz, sclk_hz * 2) - 1;
151
152
153 if (div > CQSPI_REG_CONFIG_BAUD_MASK)
154 div = CQSPI_REG_CONFIG_BAUD_MASK;
155
156 debug("%s: ref_clk %dHz sclk %dHz Div 0x%x, actual %dHz\n", __func__,
157 ref_clk_hz, sclk_hz, div, ref_clk_hz / (2 * (div + 1)));
158
159 reg |= (div << CQSPI_REG_CONFIG_BAUD_LSB);
160 writel(reg, reg_base + CQSPI_REG_CONFIG);
161
162 cadence_qspi_apb_controller_enable(reg_base);
163}
164
165void cadence_qspi_apb_set_clk_mode(void *reg_base, uint mode)
166{
167 unsigned int reg;
168
169 cadence_qspi_apb_controller_disable(reg_base);
170 reg = readl(reg_base + CQSPI_REG_CONFIG);
171 reg &= ~(CQSPI_REG_CONFIG_CLK_POL | CQSPI_REG_CONFIG_CLK_PHA);
172
173 if (mode & SPI_CPOL)
174 reg |= CQSPI_REG_CONFIG_CLK_POL;
175 if (mode & SPI_CPHA)
176 reg |= CQSPI_REG_CONFIG_CLK_PHA;
177
178 writel(reg, reg_base + CQSPI_REG_CONFIG);
179
180 cadence_qspi_apb_controller_enable(reg_base);
181}
182
183void cadence_qspi_apb_chipselect(void *reg_base,
184 unsigned int chip_select, unsigned int decoder_enable)
185{
186 unsigned int reg;
187
188 cadence_qspi_apb_controller_disable(reg_base);
189
190 debug("%s : chipselect %d decode %d\n", __func__, chip_select,
191 decoder_enable);
192
193 reg = readl(reg_base + CQSPI_REG_CONFIG);
194
195 if (decoder_enable) {
196 reg |= CQSPI_REG_CONFIG_DECODE;
197 } else {
198 reg &= ~CQSPI_REG_CONFIG_DECODE;
199
200
201
202
203
204
205 chip_select = 0xF & ~(1 << chip_select);
206 }
207
208 reg &= ~(CQSPI_REG_CONFIG_CHIPSELECT_MASK
209 << CQSPI_REG_CONFIG_CHIPSELECT_LSB);
210 reg |= (chip_select & CQSPI_REG_CONFIG_CHIPSELECT_MASK)
211 << CQSPI_REG_CONFIG_CHIPSELECT_LSB;
212 writel(reg, reg_base + CQSPI_REG_CONFIG);
213
214 cadence_qspi_apb_controller_enable(reg_base);
215}
216
217void cadence_qspi_apb_delay(void *reg_base,
218 unsigned int ref_clk, unsigned int sclk_hz,
219 unsigned int tshsl_ns, unsigned int tsd2d_ns,
220 unsigned int tchsh_ns, unsigned int tslch_ns)
221{
222 unsigned int ref_clk_ns;
223 unsigned int sclk_ns;
224 unsigned int tshsl, tchsh, tslch, tsd2d;
225 unsigned int reg;
226
227 cadence_qspi_apb_controller_disable(reg_base);
228
229
230 ref_clk_ns = DIV_ROUND_UP(1000000000, ref_clk);
231
232
233 sclk_ns = DIV_ROUND_UP(1000000000, sclk_hz);
234
235
236 if (tshsl_ns >= sclk_ns + ref_clk_ns)
237 tshsl_ns -= sclk_ns + ref_clk_ns;
238 if (tchsh_ns >= sclk_ns + 3 * ref_clk_ns)
239 tchsh_ns -= sclk_ns + 3 * ref_clk_ns;
240 tshsl = DIV_ROUND_UP(tshsl_ns, ref_clk_ns);
241 tchsh = DIV_ROUND_UP(tchsh_ns, ref_clk_ns);
242 tslch = DIV_ROUND_UP(tslch_ns, ref_clk_ns);
243 tsd2d = DIV_ROUND_UP(tsd2d_ns, ref_clk_ns);
244
245 reg = ((tshsl & CQSPI_REG_DELAY_TSHSL_MASK)
246 << CQSPI_REG_DELAY_TSHSL_LSB);
247 reg |= ((tchsh & CQSPI_REG_DELAY_TCHSH_MASK)
248 << CQSPI_REG_DELAY_TCHSH_LSB);
249 reg |= ((tslch & CQSPI_REG_DELAY_TSLCH_MASK)
250 << CQSPI_REG_DELAY_TSLCH_LSB);
251 reg |= ((tsd2d & CQSPI_REG_DELAY_TSD2D_MASK)
252 << CQSPI_REG_DELAY_TSD2D_LSB);
253 writel(reg, reg_base + CQSPI_REG_DELAY);
254
255 cadence_qspi_apb_controller_enable(reg_base);
256}
257
258void cadence_qspi_apb_controller_init(struct cadence_spi_platdata *plat)
259{
260 unsigned reg;
261
262 cadence_qspi_apb_controller_disable(plat->regbase);
263
264
265 reg = readl(plat->regbase + CQSPI_REG_SIZE);
266
267 reg &= ~(CQSPI_REG_SIZE_PAGE_MASK << CQSPI_REG_SIZE_PAGE_LSB);
268 reg &= ~(CQSPI_REG_SIZE_BLOCK_MASK << CQSPI_REG_SIZE_BLOCK_LSB);
269 reg |= (plat->page_size << CQSPI_REG_SIZE_PAGE_LSB);
270 reg |= (plat->block_size << CQSPI_REG_SIZE_BLOCK_LSB);
271 writel(reg, plat->regbase + CQSPI_REG_SIZE);
272
273
274 writel(0, plat->regbase + CQSPI_REG_REMAP);
275
276
277 writel(0, plat->regbase + CQSPI_REG_RD_INSTR);
278
279
280 writel(CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK,
281 plat->regbase + CQSPI_REG_PHY_CONFIG);
282
283 reg = readl(plat->regbase + CQSPI_REG_RD_DATA_CAPTURE);
284 reg &= ~CQSPI_REG_READCAPTURE_DQS_ENABLE;
285 reg &= ~(CQSPI_REG_RD_DATA_CAPTURE_DELAY_MASK
286 << CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB);
287 writel(reg, plat->regbase + CQSPI_REG_RD_DATA_CAPTURE);
288
289
290 writel(plat->fifo_depth / 2, plat->regbase + CQSPI_REG_SRAMPARTITION);
291
292
293 writel(0, plat->regbase + CQSPI_REG_IRQMASK);
294
295 reg = readl(plat->regbase + CQSPI_REG_CONFIG);
296 reg &= ~CQSPI_REG_CONFIG_DTR_PROT_EN_MASK;
297 reg &= ~CQSPI_REG_CONFIG_PHY_ENABLE_MASK;
298 reg &= ~CQSPI_REG_CONFIG_DIRECT;
299 reg &= ~(CQSPI_REG_CONFIG_CHIPSELECT_MASK
300 << CQSPI_REG_CONFIG_CHIPSELECT_LSB);
301 if (plat->is_dma)
302 reg |= CQSPI_REG_CONFIG_ENBL_DMA;
303
304 writel(reg, plat->regbase + CQSPI_REG_CONFIG);
305
306 cadence_qspi_apb_controller_enable(plat->regbase);
307}
308
309int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg)
310{
311 unsigned int retry = CQSPI_REG_RETRY;
312
313
314 writel(reg, reg_base + CQSPI_REG_CMDCTRL);
315
316 reg |= CQSPI_REG_CMDCTRL_EXECUTE;
317 writel(reg, reg_base + CQSPI_REG_CMDCTRL);
318
319 while (retry--) {
320 reg = readl(reg_base + CQSPI_REG_CMDCTRL);
321 if ((reg & CQSPI_REG_CMDCTRL_INPROGRESS) == 0)
322 break;
323 udelay(1);
324 }
325
326 if (!retry) {
327 printf("QSPI: flash command execution timeout\n");
328 return -EIO;
329 }
330
331
332 if (!cadence_qspi_wait_idle(reg_base))
333 return -EIO;
334
335 return 0;
336}
337
338
339int cadence_qspi_apb_command_read(void *reg_base,
340 unsigned int cmdlen, const u8 *cmdbuf, unsigned int rxlen,
341 u8 *rxbuf)
342{
343 unsigned int reg;
344 unsigned int read_len;
345 int status;
346
347 if (!cmdlen || rxlen > CQSPI_STIG_DATA_LEN_MAX || rxbuf == NULL) {
348 printf("QSPI: Invalid input arguments cmdlen %d rxlen %d\n",
349 cmdlen, rxlen);
350 return -EINVAL;
351 }
352
353 reg = cmdbuf[0] << CQSPI_REG_CMDCTRL_OPCODE_LSB;
354
355 reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB);
356
357
358 reg |= (((rxlen - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK)
359 << CQSPI_REG_CMDCTRL_RD_BYTES_LSB);
360 status = cadence_qspi_apb_exec_flash_cmd(reg_base, reg);
361 if (status != 0)
362 return status;
363
364 reg = readl(reg_base + CQSPI_REG_CMDREADDATALOWER);
365
366
367 read_len = (rxlen > 4) ? 4 : rxlen;
368 memcpy(rxbuf, ®, read_len);
369 rxbuf += read_len;
370
371 if (rxlen > 4) {
372 reg = readl(reg_base + CQSPI_REG_CMDREADDATAUPPER);
373
374 read_len = rxlen - read_len;
375 memcpy(rxbuf, ®, read_len);
376 }
377 return 0;
378}
379
380
381int cadence_qspi_apb_command_write(struct udevice *dev,
382 unsigned int cmdlen, const u8 *cmd,
383 unsigned int txlen, const u8 *txbuf)
384{
385 struct udevice *bus = (struct udevice *) dev->parent;
386 struct cadence_spi_platdata *plat = bus->platdata;
387#ifdef CONFIG_SPI_FLASH
388 struct spi_nor *nor = dev_get_uclass_priv(dev);
389#endif
390 void *reg_base = plat->regbase;
391 unsigned int reg = 0;
392 unsigned int addr_value = 0;
393 unsigned int wr_data;
394 unsigned int wr_len;
395 bool pageprgm = false;
396 unsigned int pgmlen = 0;
397 int ret;
398 u8 cmdbuf[32];
399
400 memcpy(cmdbuf, cmd, cmdlen);
401 if (!cmdlen || cmdlen > 5 || cmdbuf == NULL) {
402 printf("QSPI: Invalid input arguments cmdlen %d txlen %d\n",
403 cmdlen, txlen);
404 return -EINVAL;
405 }
406
407 if (txlen > 8) {
408 if (plat->stg_pgm) {
409 pageprgm = true;
410 pgmlen = txlen;
411 txlen = 8;
412 } else {
413 printf("%s Invalid txlen %d\n", __func__, txlen);
414 return -EINVAL;
415 }
416 }
417
418 reg |= cmdbuf[0] << CQSPI_REG_CMDCTRL_OPCODE_LSB;
419
420 if (cmdlen == 4 || cmdlen == 5) {
421
422 reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
423
424 reg |= ((cmdlen - 2) & CQSPI_REG_CMDCTRL_ADD_BYTES_MASK)
425 << CQSPI_REG_CMDCTRL_ADD_BYTES_LSB;
426
427 addr_value = cadence_qspi_apb_cmd2addr(&cmdbuf[1],
428 cmdlen >= 5 ? 4 : 3);
429
430 writel(addr_value, reg_base + CQSPI_REG_CMDADDRESS);
431 }
432
433 if (txlen) {
434
435 reg |= (0x1 << CQSPI_REG_CMDCTRL_WR_EN_LSB);
436 reg |= ((txlen - 1) & CQSPI_REG_CMDCTRL_WR_BYTES_MASK)
437 << CQSPI_REG_CMDCTRL_WR_BYTES_LSB;
438
439 wr_len = txlen > 4 ? 4 : txlen;
440 memcpy(&wr_data, txbuf, wr_len);
441 writel(wr_data, reg_base +
442 CQSPI_REG_CMDWRITEDATALOWER);
443
444 if (txlen > 4) {
445 txbuf += wr_len;
446 wr_len = txlen - wr_len;
447 memcpy(&wr_data, txbuf, wr_len);
448 writel(wr_data, reg_base +
449 CQSPI_REG_CMDWRITEDATAUPPER);
450 }
451
452 if (pageprgm) {
453 pgmlen -= txlen;
454 txbuf += wr_len;
455 addr_value += txlen;
456 }
457 }
458
459
460 ret = cadence_qspi_apb_exec_flash_cmd(reg_base, reg);
461 if (ret)
462 return ret;
463
464#ifdef CONFIG_SPI_FLASH
465 ret = spi_nor_wait_till_ready(nor);
466 if (ret < 0) {
467 printf("%s: Program timeout\n", __func__);
468 return ret;
469 }
470#endif
471
472 while (pgmlen) {
473 reg = 0x6 << CQSPI_REG_CMDCTRL_OPCODE_LSB;
474 ret = cadence_qspi_apb_exec_flash_cmd(reg_base, reg);
475 if (ret)
476 return ret;
477
478 reg = cmdbuf[0] << CQSPI_REG_CMDCTRL_OPCODE_LSB;
479 reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
480 reg |= ((cmdlen - 2) & CQSPI_REG_CMDCTRL_ADD_BYTES_MASK)
481 << CQSPI_REG_CMDCTRL_ADD_BYTES_LSB;
482 writel(addr_value, reg_base + CQSPI_REG_CMDADDRESS);
483
484 reg |= (0x1 << CQSPI_REG_CMDCTRL_WR_EN_LSB);
485 reg |= ((txlen - 1) & CQSPI_REG_CMDCTRL_WR_BYTES_MASK)
486 << CQSPI_REG_CMDCTRL_WR_BYTES_LSB;
487 wr_len = txlen > 4 ? 4 : txlen;
488 memcpy(&wr_data, txbuf, wr_len);
489 writel(wr_data, reg_base +
490 CQSPI_REG_CMDWRITEDATALOWER);
491
492 if (txlen > 4) {
493 txbuf += wr_len;
494 wr_len = txlen - wr_len;
495 memcpy(&wr_data, txbuf, wr_len);
496 writel(wr_data, reg_base +
497 CQSPI_REG_CMDWRITEDATAUPPER);
498 }
499
500 pgmlen -= txlen;
501 txbuf += wr_len;
502 addr_value += txlen;
503 txlen = pgmlen > 8 ? 8 : pgmlen;
504
505 ret = cadence_qspi_apb_exec_flash_cmd(reg_base, reg);
506 if (ret)
507 return ret;
508
509#ifdef CONFIG_SPI_FLASH
510 ret = spi_nor_wait_till_ready(nor);
511 if (ret < 0) {
512 printf("%s: Program timeout\n", __func__);
513 return ret;
514 }
515#endif
516 }
517
518 return 0;
519}
520
521
522int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat,
523 unsigned int cmdlen, unsigned int rx_width, const u8 *cmdbuf)
524{
525 unsigned int reg;
526 unsigned int rd_reg;
527 unsigned int addr_value;
528 unsigned int dummy_clk;
529 unsigned int dummy_bytes;
530 unsigned int addr_bytes;
531
532
533
534
535
536
537
538
539 if (cmdlen >= 5)
540
541 addr_bytes = cmdlen - 2;
542 else
543
544 addr_bytes = cmdlen - 1;
545
546
547 writel(plat->trigger_address,
548 plat->regbase + CQSPI_REG_INDIRECTTRIGGER);
549
550
551 rd_reg = cmdbuf[0] << CQSPI_REG_RD_INSTR_OPCODE_LSB;
552
553 if (rx_width & SPI_RX_QUAD)
554
555 rd_reg |= CQSPI_INST_TYPE_QUAD << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB;
556
557 if (rx_width & SPI_RX_OCTAL)
558
559 rd_reg |= CQSPI_INST_TYPE_OCTAL <<
560 CQSPI_REG_RD_INSTR_TYPE_DATA_LSB;
561
562
563 addr_value = cadence_qspi_apb_cmd2addr(&cmdbuf[1], addr_bytes);
564 writel(addr_value, plat->regbase + CQSPI_REG_INDIRECTRDSTARTADDR);
565
566
567 dummy_bytes = cmdlen - addr_bytes - 1;
568 if (dummy_bytes) {
569 if (dummy_bytes > CQSPI_DUMMY_BYTES_MAX)
570 dummy_bytes = CQSPI_DUMMY_BYTES_MAX;
571
572 rd_reg |= (1 << CQSPI_REG_RD_INSTR_MODE_EN_LSB);
573#if defined(CONFIG_SPL_SPI_XIP) && defined(CONFIG_SPL_BUILD)
574 writel(0x0, plat->regbase + CQSPI_REG_MODE_BIT);
575#else
576 writel(0xFF, plat->regbase + CQSPI_REG_MODE_BIT);
577#endif
578
579
580 dummy_clk = dummy_bytes * CQSPI_DUMMY_CLKS_PER_BYTE;
581
582 dummy_clk -= CQSPI_DUMMY_CLKS_PER_BYTE;
583
584 if (dummy_clk)
585 rd_reg |= (dummy_clk & CQSPI_REG_RD_INSTR_DUMMY_MASK)
586 << CQSPI_REG_RD_INSTR_DUMMY_LSB;
587 }
588
589 writel(rd_reg, plat->regbase + CQSPI_REG_RD_INSTR);
590
591
592 reg = readl(plat->regbase + CQSPI_REG_SIZE);
593 reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
594 reg |= (addr_bytes - 1);
595 writel(reg, plat->regbase + CQSPI_REG_SIZE);
596 return 0;
597}
598
599static u32 cadence_qspi_get_rd_sram_level(struct cadence_spi_platdata *plat)
600{
601 u32 reg = readl(plat->regbase + CQSPI_REG_SDRAMLEVEL);
602 reg >>= CQSPI_REG_SDRAMLEVEL_RD_LSB;
603 return reg & CQSPI_REG_SDRAMLEVEL_RD_MASK;
604}
605
606static int cadence_qspi_wait_for_data(struct cadence_spi_platdata *plat)
607{
608 unsigned int timeout = 10000;
609 u32 reg;
610
611 while (timeout--) {
612 reg = cadence_qspi_get_rd_sram_level(plat);
613 if (reg)
614 return reg;
615 udelay(1);
616 }
617
618 return -ETIMEDOUT;
619}
620
621int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
622 unsigned int n_rx, u8 *rxbuf)
623{
624 unsigned int remaining = n_rx;
625 unsigned int bytes_to_read = 0;
626 int ret;
627
628 writel(n_rx, plat->regbase + CQSPI_REG_INDIRECTRDBYTES);
629
630
631 writel(CQSPI_REG_INDIRECTRD_START,
632 plat->regbase + CQSPI_REG_INDIRECTRD);
633
634 while (remaining > 0) {
635 ret = cadence_qspi_wait_for_data(plat);
636 if (ret < 0) {
637 printf("Indirect write timed out (%i)\n", ret);
638 goto failrd;
639 }
640
641 bytes_to_read = ret;
642
643 while (bytes_to_read != 0) {
644 bytes_to_read *= plat->fifo_width;
645 bytes_to_read = bytes_to_read > remaining ?
646 remaining : bytes_to_read;
647
648
649
650
651 if (((uintptr_t)rxbuf % 4) || (bytes_to_read % 4))
652 readsb(plat->ahbbase, rxbuf, bytes_to_read);
653 else
654 readsl(plat->ahbbase, rxbuf,
655 bytes_to_read >> 2);
656 rxbuf += bytes_to_read;
657 remaining -= bytes_to_read;
658 bytes_to_read = cadence_qspi_get_rd_sram_level(plat);
659 }
660 }
661
662
663 ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTRD,
664 CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
665 if (ret) {
666 printf("Indirect read completion error (%i)\n", ret);
667 goto failrd;
668 }
669
670
671 writel(CQSPI_REG_INDIRECTRD_DONE,
672 plat->regbase + CQSPI_REG_INDIRECTRD);
673
674 return 0;
675
676failrd:
677
678 writel(CQSPI_REG_INDIRECTRD_CANCEL,
679 plat->regbase + CQSPI_REG_INDIRECTRD);
680 return ret;
681}
682
683
684int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat,
685 unsigned int cmdlen, unsigned int tx_width, const u8 *cmdbuf)
686{
687 unsigned int reg;
688 unsigned int addr_bytes = cmdlen > 4 ? 4 : 3;
689
690 if (cmdlen < 4 || cmdbuf == NULL) {
691 printf("QSPI: Invalid input argument, len %d cmdbuf %p\n",
692 cmdlen, cmdbuf);
693 return -EINVAL;
694 }
695
696 writel(plat->trigger_address,
697 plat->regbase + CQSPI_REG_INDIRECTTRIGGER);
698
699
700 reg = cmdbuf[0] << CQSPI_REG_WR_INSTR_OPCODE_LSB;
701
702 if (tx_width & SPI_TX_QUAD)
703 reg |= CQSPI_INST_TYPE_QUAD << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB;
704
705 writel(reg, plat->regbase + CQSPI_REG_WR_INSTR);
706
707
708 reg = cadence_qspi_apb_cmd2addr(&cmdbuf[1], addr_bytes);
709 writel(reg, plat->regbase + CQSPI_REG_INDIRECTWRSTARTADDR);
710
711 reg = readl(plat->regbase + CQSPI_REG_SIZE);
712 reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
713 reg |= (addr_bytes - 1);
714 writel(reg, plat->regbase + CQSPI_REG_SIZE);
715 return 0;
716}
717
718int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
719 unsigned int n_tx, const u8 *txbuf)
720{
721 unsigned int page_size = plat->page_size;
722 unsigned int remaining = n_tx;
723 const u8 *bb_txbuf = txbuf;
724 void *bounce_buf = NULL;
725 unsigned int write_bytes;
726 int ret;
727
728
729
730
731
732 if ((uintptr_t)txbuf % 4) {
733 bounce_buf = malloc(n_tx);
734 if (!bounce_buf)
735 return -ENOMEM;
736 memcpy(bounce_buf, txbuf, n_tx);
737 bb_txbuf = bounce_buf;
738 }
739
740
741 writel(n_tx, plat->regbase + CQSPI_REG_INDIRECTWRBYTES);
742
743
744 writel(CQSPI_REG_INDIRECTWR_START,
745 plat->regbase + CQSPI_REG_INDIRECTWR);
746
747 while (remaining > 0) {
748 write_bytes = remaining > page_size ? page_size : remaining;
749 writesl(plat->ahbbase, bb_txbuf, write_bytes >> 2);
750 if (write_bytes % 4)
751 writesb(plat->ahbbase,
752 bb_txbuf + rounddown(write_bytes, 4),
753 write_bytes % 4);
754
755 ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_SDRAMLEVEL,
756 CQSPI_REG_SDRAMLEVEL_WR_MASK <<
757 CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
758 if (ret) {
759 printf("Indirect write timed out (%i)\n", ret);
760 goto failwr;
761 }
762
763 bb_txbuf += write_bytes;
764 remaining -= write_bytes;
765 }
766
767
768 ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTWR,
769 CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
770 if (ret) {
771 printf("Indirect write completion error (%i)\n", ret);
772 goto failwr;
773 }
774
775
776 writel(CQSPI_REG_INDIRECTWR_DONE,
777 plat->regbase + CQSPI_REG_INDIRECTWR);
778 if (bounce_buf)
779 free(bounce_buf);
780 return 0;
781
782failwr:
783
784 writel(CQSPI_REG_INDIRECTWR_CANCEL,
785 plat->regbase + CQSPI_REG_INDIRECTWR);
786 if (bounce_buf)
787 free(bounce_buf);
788 return ret;
789}
790
791void cadence_qspi_apb_enter_xip(void *reg_base, char xip_dummy)
792{
793 unsigned int reg;
794
795
796 reg = readl(reg_base + CQSPI_REG_CONFIG);
797 reg |= CQSPI_REG_CONFIG_ENABLE;
798 reg |= CQSPI_REG_CONFIG_DIRECT;
799 reg |= CQSPI_REG_CONFIG_XIP_IMM;
800 writel(reg, reg_base + CQSPI_REG_CONFIG);
801
802
803 writel(xip_dummy, reg_base + CQSPI_REG_MODE_BIT);
804
805
806 reg = readl(reg_base + CQSPI_REG_RD_INSTR);
807 reg |= (1 << CQSPI_REG_RD_INSTR_MODE_EN_LSB);
808 writel(reg, reg_base + CQSPI_REG_RD_INSTR);
809}
810