static void zynqmp_qspi_genfifo_cmd(struct zynqmp_qspi_priv *priv) { u8 command = 1; u32 gen_fifo_cmd; u32 bytecount = 0; struct zynqmp_qspi_regs *regs = priv->regs; while (priv->len) { gen_fifo_cmd = zynqmp_qspi_bus_select(priv); gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_TX; if (command) { command = 0; last_cmd = *(u8 *)priv->tx_buf; } gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI; gen_fifo_cmd |= *(u8 *)priv->tx_buf; bytecount++; priv->len--; priv->tx_buf = (u8 *)priv->tx_buf + 1; debug("GFIFO_CMD_Cmd = 0x%x\n", gen_fifo_cmd); writel(gen_fifo_cmd, ®s->genfifo); } }
static void zynqmp_qspi_genfifo_cmd(struct zynqmp_qspi_priv *priv) { u8 command = 1; u32 gen_fifo_cmd; u32 bytecount = 0; if (priv->dummy_bytes) priv->len -= priv->dummy_bytes; while (priv->len) { gen_fifo_cmd = zynqmp_qspi_bus_select(priv); gen_fifo_cmd |= GQSPI_GFIFO_TX; if (command) { command = 0; last_cmd = *(u8 *)priv->tx_buf; } gen_fifo_cmd |= GQSPI_SPI_MODE_SPI; gen_fifo_cmd |= *(u8 *)priv->tx_buf; bytecount++; priv->len--; priv->tx_buf = (u8 *)priv->tx_buf + 1; debug("GFIFO_CMD_Cmd = 0x%x\n", gen_fifo_cmd); zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd); } if (priv->dummy_bytes) { gen_fifo_cmd = zynqmp_qspi_bus_select(priv); gen_fifo_cmd &= ~(GQSPI_GFIFO_TX | GQSPI_GFIFO_RX); if (priv->tx_rx_mode & SPI_RX_QUAD) gen_fifo_cmd |= GQSPI_SPI_MODE_QSPI; else if (priv->tx_rx_mode & SPI_RX_DUAL) gen_fifo_cmd |= GQSPI_SPI_MODE_DUAL_SPI; else gen_fifo_cmd |= GQSPI_SPI_MODE_SPI; gen_fifo_cmd |= GQSPI_GFIFO_DATA_XFR_MASK; gen_fifo_cmd |= (priv->dummy_bytes * 8); zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd); } }
static int zynqmp_qspi_genfifo_fill_rx(struct zynqmp_qspi_priv *priv) { u32 gen_fifo_cmd; u32 *buf; u32 actuallen = priv->len; gen_fifo_cmd = zynqmp_qspi_bus_select(priv); gen_fifo_cmd |= GQSPI_GFIFO_RX | GQSPI_GFIFO_DATA_XFR_MASK; if (last_cmd == QUAD_OUT_READ_CMD) gen_fifo_cmd |= GQSPI_SPI_MODE_QSPI; else if (last_cmd == DUAL_OUTPUT_FASTRD_CMD) gen_fifo_cmd |= GQSPI_SPI_MODE_DUAL_SPI; else gen_fifo_cmd |= GQSPI_SPI_MODE_SPI; if (priv->stripe) gen_fifo_cmd |= GQSPI_GFIFO_STRIPE_MASK; /* * Check if receive buffer is aligned to 4 byte and length * is multiples of four byte as we are using dma to receive. */ if ((!((unsigned long)priv->rx_buf & (GQSPI_DMA_ALIGN - 1)) && !(actuallen % GQSPI_DMA_ALIGN)) || priv->io_mode) { buf = (u32 *)priv->rx_buf; if (priv->io_mode) return zynqmp_qspi_start_io(priv, gen_fifo_cmd, buf); else return zynqmp_qspi_start_dma(priv, gen_fifo_cmd, buf); } ALLOC_CACHE_ALIGN_BUFFER(u8, tmp, roundup(priv->len, GQSPI_DMA_ALIGN)); buf = (u32 *)tmp; return zynqmp_qspi_start_dma(priv, gen_fifo_cmd, buf); }
static void zynqmp_qspi_chipselect(struct zynqmp_qspi_priv *priv, int is_on) { u32 gqspi_fifo_reg = 0; if (is_on) { gqspi_fifo_reg = zynqmp_qspi_bus_select(priv); gqspi_fifo_reg |= GQSPI_SPI_MODE_SPI | GQSPI_IMD_DATA_CS_ASSERT; } else { if (priv->is_dual == SF_DUAL_PARALLEL_FLASH) gqspi_fifo_reg = GQSPI_GFIFO_UP_BUS | GQSPI_GFIFO_LOW_BUS; else if (priv->u_page) gqspi_fifo_reg = GQSPI_GFIFO_UP_BUS; else gqspi_fifo_reg = GQSPI_GFIFO_LOW_BUS; gqspi_fifo_reg |= GQSPI_IMD_DATA_CS_DEASSERT; } debug("GFIFO_CMD_CS: 0x%x\n", gqspi_fifo_reg); zynqmp_qspi_fill_gen_fifo(priv, gqspi_fifo_reg); }
static int zynqmp_qspi_genfifo_fill_tx(struct zynqmp_qspi_priv *priv) { u32 gen_fifo_cmd; u32 len; int ret = 0; struct zynqmp_qspi_regs *regs = priv->regs; gen_fifo_cmd = zynqmp_qspi_bus_select(priv); gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_TX | ZYNQMP_QSPI_GFIFO_DATA_XFR_MASK; if (priv->stripe) gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_STRIPE_MASK; if (last_cmd == QUAD_PAGE_PROGRAM_CMD) gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_QSPI; else gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI; while (priv->len) { len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd); writel(gen_fifo_cmd, ®s->genfifo); debug("GFIFO_CMD_TX:0x%x\n", gen_fifo_cmd); if (gen_fifo_cmd & ZYNQMP_QSPI_GFIFO_EXP_MASK) ret = zynqmp_qspi_fill_tx_fifo(priv, 1 << len); else ret = zynqmp_qspi_fill_tx_fifo(priv, len); if (ret) return ret; } return ret; }
static void zynqmp_qspi_chipselect(struct zynqmp_qspi_priv *priv, int is_on) { u32 gqspi_fifo_reg = 0; struct zynqmp_qspi_regs *regs = priv->regs; if (is_on) { gqspi_fifo_reg = zynqmp_qspi_bus_select(priv); gqspi_fifo_reg |= ZYNQMP_QSPI_SPI_MODE_SPI | ZYNQMP_QSPI_IMD_DATA_CS_ASSERT; } else { if (priv->is_dual == SF_DUAL_PARALLEL_FLASH) gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_UP_BUS | ZYNQMP_QSPI_GFIFO_LOW_BUS; else if (priv->u_page) gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_UP_BUS; else gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS; gqspi_fifo_reg |= ZYNQMP_QSPI_IMD_DATA_CS_DEASSERT; } debug("GFIFO_CMD_CS: 0x%x\n", gqspi_fifo_reg); writel(gqspi_fifo_reg, ®s->genfifo); }
static int zynqmp_qspi_genfifo_fill_rx(struct zynqmp_qspi_priv *priv) { u32 gen_fifo_cmd; u32 *buf; u32 addr; u32 size, len; u32 timeout = 10000000; u32 actuallen = priv->len; struct zynqmp_qspi_regs *regs = priv->regs; struct zynqmp_qspi_dma_regs *dma_regs = priv->dma_regs; gen_fifo_cmd = zynqmp_qspi_bus_select(priv); gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_RX | ZYNQMP_QSPI_GFIFO_DATA_XFR_MASK; if (last_cmd == QUAD_OUT_READ_CMD) gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_QSPI; else gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI; if (priv->stripe) gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_STRIPE_MASK; if (!((u32)priv->rx_buf & 0x3) && !(actuallen % 4)) { buf = (u32 *)priv->rx_buf; } else { ALLOC_CACHE_ALIGN_BUFFER(u8, tmp, roundup(priv->len, 4)); buf = (u32 *)tmp; } writel((u32)buf, &dma_regs->dmadst); writel(roundup(priv->len, 4), &dma_regs->dmasize); writel(ZYNQMP_QSPI_DMA_DST_I_STS_MASK, &dma_regs->dmaier); addr = (u32)buf; size = roundup(priv->len, ARCH_DMA_MINALIGN); flush_dcache_range(addr, addr+size); while (priv->len) { len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd); if (!(gen_fifo_cmd & ZYNQMP_QSPI_GFIFO_EXP_MASK) && (len % 4)) { gen_fifo_cmd &= ~(0xFF); gen_fifo_cmd |= (len/4 + 1) * 4; } writel(gen_fifo_cmd, ®s->genfifo); debug("GFIFO_CMD_RX:0x%x\n", gen_fifo_cmd); } while (timeout) { if (readl(&dma_regs->dmaisr) & ZYNQMP_QSPI_DMA_DST_I_STS_DONE) { writel(ZYNQMP_QSPI_DMA_DST_I_STS_DONE, &dma_regs->dmaisr); break; } timeout--; } debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n", (unsigned long)buf, (unsigned long)priv->rx_buf, *buf, actuallen); if (!timeout) { debug("DMA Timeout:0x%x\n", readl(&dma_regs->dmaisr)); return -1; } if (buf != priv->rx_buf) memcpy(priv->rx_buf, buf, actuallen); return 0; }