* read operation, so let's use the last entry (15).
*/
#define SEQID_LUT 15
+#define SEQID_LUT_AHB 14
/* Registers used by the driver */
#define QUADSPI_MCR 0x00
#define QUADSPI_LUT_REG(idx) \
(QUADSPI_LUT_BASE + QUADSPI_LUT_OFFSET + (idx) * 4)
+#define QUADSPI_AHB_LUT_OFFSET (SEQID_LUT_AHB * 4 * 4)
+#define QUADSPI_AHB_LUT_REG(idx) \
+ (QUADSPI_LUT_BASE + QUADSPI_AHB_LUT_OFFSET + (idx) * 4)
+
/* Instruction set for the LUT register */
#define LUT_STOP 0
#define LUT_CMD 1
*/
#define QUADSPI_QUIRK_USE_TDH_SETTING BIT(5)
+/*
+ * Controller only has Two CS on flash A, no flash B port
+ */
+#define QUADSPI_QUIRK_SINGLE_BUS BIT(6)
+
struct fsl_qspi_devtype_data {
unsigned int rxfifo;
unsigned int txfifo;
.txfifo = SZ_64,
.ahb_buf_size = SZ_128,
.quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK |
- QUADSPI_QUIRK_USE_TDH_SETTING,
+ QUADSPI_QUIRK_USE_TDH_SETTING | QUADSPI_QUIRK_SINGLE_BUS,
.little_endian = true,
};
void __iomem *iobase;
void __iomem *ahb_addr;
u32 memmap_phy;
+ u32 memmap_size;
const struct fsl_qspi_devtype_data *devtype_data;
int selected;
};
return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING;
}
+static inline int needs_single_bus(struct fsl_qspi *q)
+{
+ return q->devtype_data->quirks & QUADSPI_QUIRK_SINGLE_BUS;
+}
+
/*
* An IC bug makes it necessary to rearrange the 32-bit data.
* Later chips, such as IMX6SLX, have fixed this bug.
lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
op->cmd.opcode);
- /*
- * For some unknown reason, using LUT_ADDR doesn't work in some
- * cases (at least with only one byte long addresses), so
- * let's use LUT_MODE to write the address bytes one by one
- */
- for (i = 0; i < op->addr.nbytes; i++) {
- u8 addrbyte = op->addr.val >> (8 * (op->addr.nbytes - i - 1));
-
- lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_MODE,
- LUT_PAD(op->addr.buswidth),
- addrbyte);
- lutidx++;
+ if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+ if (op->addr.nbytes) {
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_ADDR,
+ LUT_PAD(op->addr.buswidth),
+ (op->addr.nbytes == 4) ? 0x20 : 0x18);
+ lutidx++;
+ }
+ } else {
+ /*
+ * For some unknown reason, using LUT_ADDR doesn't work in some
+ * cases (at least with only one byte long addresses), so
+ * let's use LUT_MODE to write the address bytes one by one
+ */
+ for (i = 0; i < op->addr.nbytes; i++) {
+ u8 addrbyte = op->addr.val >> (8 * (op->addr.nbytes - i - 1));
+
+ lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_MODE,
+ LUT_PAD(op->addr.buswidth),
+ addrbyte);
+ lutidx++;
+ }
}
if (op->dummy.nbytes) {
for (i = 0; i < ARRAY_SIZE(lutval); i++)
qspi_writel(q, lutval[i], base + QUADSPI_LUT_REG(i));
+ if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN &&
+ op->addr.nbytes) {
+ for (i = 0; i < ARRAY_SIZE(lutval); i++)
+ qspi_writel(q, lutval[i], base + QUADSPI_AHB_LUT_REG(i));
+ }
+ }
+
/* lock LUT */
qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
fsl_qspi_invalidate(q);
}
+static u32 fsl_qspi_memsize_per_cs(struct fsl_qspi *q)
+{
+ if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+ if (needs_single_bus(q))
+ return q->memmap_size / 2;
+ else
+ return q->memmap_size / 4;
+ } else {
+ return ALIGN(q->devtype_data->ahb_buf_size, 0x400);
+ }
+}
+
static void fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op)
{
+ void __iomem *ahb_read_addr = q->ahb_addr;
+
+ if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+ if (op->addr.nbytes)
+ ahb_read_addr += op->addr.val;
+ }
+
memcpy_fromio(op->data.buf.in,
- q->ahb_addr + q->selected * ALIGN(q->devtype_data->ahb_buf_size, 0x400),
+ ahb_read_addr + q->selected * fsl_qspi_memsize_per_cs(q),
op->data.nbytes);
}
if (needs_amba_base_offset(q))
addr_offset = q->memmap_phy;
+ if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+ if (op->addr.nbytes)
+ addr_offset += op->addr.val;
+ }
+
qspi_writel(q,
- q->selected * ALIGN(q->devtype_data->ahb_buf_size, 0x400) + addr_offset,
+ q->selected * fsl_qspi_memsize_per_cs(q) + addr_offset,
base + QUADSPI_SFAR);
qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) |
static int fsl_qspi_default_setup(struct fsl_qspi *q)
{
void __iomem *base = q->iobase;
- u32 reg, addr_offset = 0;
+ u32 reg, addr_offset = 0, memsize_cs;
/* Reset the module */
qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
qspi_writel(q, 0, base + QUADSPI_BUF1IND);
qspi_writel(q, 0, base + QUADSPI_BUF2IND);
- qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT),
- q->iobase + QUADSPI_BFGENCR);
+ if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP))
+ qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT_AHB),
+ q->iobase + QUADSPI_BFGENCR);
+ else
+ qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT),
+ q->iobase + QUADSPI_BFGENCR);
+
qspi_writel(q, QUADSPI_RBCT_WMRK_MASK, base + QUADSPI_RBCT);
qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK |
QUADSPI_BUF3CR_ADATSZ(q->devtype_data->ahb_buf_size / 8),
* We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD,
* SFB2AD accordingly.
*/
- qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) + addr_offset,
+ memsize_cs = fsl_qspi_memsize_per_cs(q);
+ qspi_writel(q, memsize_cs + addr_offset,
base + QUADSPI_SFA1AD);
- qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) * 2 + addr_offset,
+ qspi_writel(q, memsize_cs * 2 + addr_offset,
base + QUADSPI_SFA2AD);
- qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) * 3 + addr_offset,
- base + QUADSPI_SFB1AD);
- qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) * 4 + addr_offset,
- base + QUADSPI_SFB2AD);
+ if (!needs_single_bus(q)) {
+ qspi_writel(q, memsize_cs * 3 + addr_offset,
+ base + QUADSPI_SFB1AD);
+ qspi_writel(q, memsize_cs * 4 + addr_offset,
+ base + QUADSPI_SFB2AD);
+ }
q->selected = -1;
q->ahb_addr = map_physmem(res.start, res.end - res.start, MAP_NOCACHE);
q->memmap_phy = res.start;
+ q->memmap_size = res.end - res.start;
dm_bus->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency",
66000000);