Commit 6cbc8b5893b49d84abf1222e0c6984540314d466

Authored by Ye Li
1 parent 990b4fff61

fsl_qspi: Provide config to map full AHB space

iMX platforms provide large AHB mapped space for QSPI, each
controller has 256MB. However, current driver only maps small
size (AHB buffer size) of AHB space, this implementation
causes iMX failed to boot M4 with QSPI XIP image.

Add config CONFIG_FSL_QSPI_AHB_FULL_MAP (default enabled for iMX)
to address above problem.

When the config is set:
1. Full AHB space is divided to each CS.
2. A dedicated LUT entry is used for AHB read only.
3. The MODE instruction in LUT is replaced to standard ADDR instruction
4. The address in spi_mem_op is used to SFAR and AHB read

Signed-off-by: Ye Li <ye.li@nxp.com>

Showing 2 changed files with 80 additions and 10 deletions Side-by-side Diff

... ... @@ -420,6 +420,13 @@
420 420 used to access the SPI NOR flash on platforms embedding this
421 421 Freescale IP core.
422 422  
  423 +config FSL_QSPI_AHB_FULL_MAP
  424 + bool "Use full AHB memory map space"
  425 + depends on FSL_QSPI
  426 + default y if ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP || ARCH_IMX8M
  427 + help
  428 + Enable the Freescale QSPI driver to use full AHB memory map space
  429 +
423 430 config DAVINCI_SPI
424 431 bool "Davinci & Keystone SPI driver"
425 432 depends on ARCH_DAVINCI || ARCH_KEYSTONE
drivers/spi/fsl_qspi.c
... ... @@ -40,6 +40,7 @@
40 40 * read operation, so let's use the last entry (15).
41 41 */
42 42 #define SEQID_LUT 15
  43 +#define SEQID_LUT_AHB 14
43 44  
44 45 /* Registers used by the driver */
45 46 #define QUADSPI_MCR 0x00
... ... @@ -116,6 +117,10 @@
116 117 #define QUADSPI_LUT_REG(idx) \
117 118 (QUADSPI_LUT_BASE + QUADSPI_LUT_OFFSET + (idx) * 4)
118 119  
  120 +#define QUADSPI_AHB_LUT_OFFSET (SEQID_LUT_AHB * 4 * 4)
  121 +#define QUADSPI_AHB_LUT_REG(idx) \
  122 + (QUADSPI_LUT_BASE + QUADSPI_AHB_LUT_OFFSET + (idx) * 4)
  123 +
119 124 /* Instruction set for the LUT register */
120 125 #define LUT_STOP 0
121 126 #define LUT_CMD 1
... ... @@ -183,6 +188,11 @@
183 188 */
184 189 #define QUADSPI_QUIRK_USE_TDH_SETTING BIT(5)
185 190  
  191 +/*
  192 + * Controller only has Two CS on flash A, no flash B port
  193 + */
  194 +#define QUADSPI_QUIRK_SINGLE_BUS BIT(6)
  195 +
186 196 struct fsl_qspi_devtype_data {
187 197 unsigned int rxfifo;
188 198 unsigned int txfifo;
... ... @@ -230,7 +240,7 @@
230 240 .txfifo = SZ_64,
231 241 .ahb_buf_size = SZ_128,
232 242 .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK |
233   - QUADSPI_QUIRK_USE_TDH_SETTING,
  243 + QUADSPI_QUIRK_USE_TDH_SETTING | QUADSPI_QUIRK_SINGLE_BUS,
234 244 .little_endian = true,
235 245 };
236 246  
... ... @@ -263,6 +273,7 @@
263 273 void __iomem *iobase;
264 274 void __iomem *ahb_addr;
265 275 u32 memmap_phy;
  276 + u32 memmap_size;
266 277 const struct fsl_qspi_devtype_data *devtype_data;
267 278 int selected;
268 279 };
... ... @@ -297,6 +308,11 @@
297 308 return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING;
298 309 }
299 310  
  311 +static inline int needs_single_bus(struct fsl_qspi *q)
  312 +{
  313 + return q->devtype_data->quirks & QUADSPI_QUIRK_SINGLE_BUS;
  314 +}
  315 +
300 316 /*
301 317 * An IC bug makes it necessary to rearrange the 32-bit data.
302 318 * Later chips, such as IMX6SLX, have fixed this bug.
... ... @@ -399,6 +415,14 @@
399 415 lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
400 416 op->cmd.opcode);
401 417  
  418 +#ifdef CONFIG_FSL_QSPI_AHB_FULL_MAP
  419 + if (op->addr.nbytes) {
  420 + lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_ADDR,
  421 + LUT_PAD(op->addr.buswidth),
  422 + (op->addr.nbytes == 4)? 0x20 : 0x18);
  423 + lutidx++;
  424 + }
  425 +#else
402 426 /*
403 427 * For some unknown reason, using LUT_ADDR doesn't work in some
404 428 * cases (at least with only one byte long addresses), so
... ... @@ -412,6 +436,7 @@
412 436 addrbyte);
413 437 lutidx++;
414 438 }
  439 +#endif
415 440  
416 441 if (op->dummy.nbytes) {
417 442 lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY,
... ... @@ -443,6 +468,14 @@
443 468 for (i = 0; i < ARRAY_SIZE(lutval); i++)
444 469 qspi_writel(q, lutval[i], base + QUADSPI_LUT_REG(i));
445 470  
  471 +#ifdef CONFIG_FSL_QSPI_AHB_FULL_MAP
  472 + if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN &&
  473 + op->addr.nbytes) {
  474 + for (i = 0; i < ARRAY_SIZE(lutval); i++)
  475 + qspi_writel(q, lutval[i], base + QUADSPI_AHB_LUT_REG(i));
  476 + }
  477 +#endif
  478 +
446 479 /* lock LUT */
447 480 qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
448 481 qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
449 482  
450 483  
... ... @@ -485,10 +518,27 @@
485 518 fsl_qspi_invalidate(q);
486 519 }
487 520  
  521 +static u32 fsl_qspi_memsize_per_cs(struct fsl_qspi *q)
  522 +{
  523 +#ifdef CONFIG_FSL_QSPI_AHB_FULL_MAP
  524 + if (needs_single_bus(q))
  525 + return q->memmap_size / 2;
  526 + else
  527 + return q->memmap_size / 4;
  528 +#else
  529 + return ALIGN(q->devtype_data->ahb_buf_size, 0x400);
  530 +#endif
  531 +}
  532 +
488 533 static void fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op)
489 534 {
  535 + void __iomem *ahb_read_addr = q->ahb_addr;
  536 +#ifdef CONFIG_FSL_QSPI_AHB_FULL_MAP
  537 + if (op->addr.nbytes)
  538 + ahb_read_addr += op->addr.val;
  539 +#endif
490 540 memcpy_fromio(op->data.buf.in,
491   - q->ahb_addr + q->selected * ALIGN(q->devtype_data->ahb_buf_size, 0x400),
  541 + ahb_read_addr + q->selected * fsl_qspi_memsize_per_cs(q),
492 542 op->data.nbytes);
493 543 }
494 544  
495 545  
... ... @@ -591,8 +641,12 @@
591 641 if (needs_amba_base_offset(q))
592 642 addr_offset = q->memmap_phy;
593 643  
  644 +#ifdef CONFIG_FSL_QSPI_AHB_FULL_MAP
  645 + if (op->addr.nbytes)
  646 + addr_offset += op->addr.val;
  647 +#endif
594 648 qspi_writel(q,
595   - q->selected * ALIGN(q->devtype_data->ahb_buf_size, 0x400) + addr_offset,
  649 + q->selected * fsl_qspi_memsize_per_cs(q) + addr_offset,
596 650 base + QUADSPI_SFAR);
597 651  
598 652 qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) |
... ... @@ -649,7 +703,7 @@
649 703 static int fsl_qspi_default_setup(struct fsl_qspi *q)
650 704 {
651 705 void __iomem *base = q->iobase;
652   - u32 reg, addr_offset = 0;
  706 + u32 reg, addr_offset = 0, memsize_cs;
653 707  
654 708 /* Reset the module */
655 709 qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
656 710  
... ... @@ -681,8 +735,13 @@
681 735 qspi_writel(q, 0, base + QUADSPI_BUF1IND);
682 736 qspi_writel(q, 0, base + QUADSPI_BUF2IND);
683 737  
  738 +#ifdef CONFIG_FSL_QSPI_AHB_FULL_MAP
  739 + qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT_AHB),
  740 + q->iobase + QUADSPI_BFGENCR);
  741 +#else
684 742 qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT),
685 743 q->iobase + QUADSPI_BFGENCR);
  744 +#endif
686 745 qspi_writel(q, QUADSPI_RBCT_WMRK_MASK, base + QUADSPI_RBCT);
687 746 qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK |
688 747 QUADSPI_BUF3CR_ADATSZ(q->devtype_data->ahb_buf_size / 8),
689 748  
690 749  
... ... @@ -698,14 +757,17 @@
698 757 * We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD,
699 758 * SFB2AD accordingly.
700 759 */
701   - qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) + addr_offset,
  760 + memsize_cs = fsl_qspi_memsize_per_cs(q);
  761 + qspi_writel(q, memsize_cs + addr_offset,
702 762 base + QUADSPI_SFA1AD);
703   - qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) * 2 + addr_offset,
  763 + qspi_writel(q, memsize_cs * 2 + addr_offset,
704 764 base + QUADSPI_SFA2AD);
705   - qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) * 3 + addr_offset,
706   - base + QUADSPI_SFB1AD);
707   - qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) * 4 + addr_offset,
708   - base + QUADSPI_SFB2AD);
  765 + if (!needs_single_bus(q)) {
  766 + qspi_writel(q, memsize_cs * 3 + addr_offset,
  767 + base + QUADSPI_SFB1AD);
  768 + qspi_writel(q, memsize_cs * 4 + addr_offset,
  769 + base + QUADSPI_SFB2AD);
  770 + }
709 771  
710 772 q->selected = -1;
711 773  
... ... @@ -753,6 +815,7 @@
753 815  
754 816 q->ahb_addr = map_physmem(res.start, res.end - res.start, MAP_NOCACHE);
755 817 q->memmap_phy = res.start;
  818 + q->memmap_size = res.end - res.start;
756 819  
757 820 dm_bus->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency",
758 821 66000000);