void cadence_qspi_switch_cs(struct struct_cqspi *cadence_qspi, unsigned int cs) { unsigned int reg; struct platform_device *pdev = cadence_qspi->pdev; struct cqspi_platform_data *pdata = pdev->dev.platform_data; struct cqspi_flash_pdata *f_pdata = &(pdata->f_pdata[cs]); void __iomem *iobase = cadence_qspi->iobase; pr_debug("%s\n", __func__); cadence_qspi_apb_controller_disable(iobase); /* Configure page size and block size. */ reg = CQSPI_READL(iobase + CQSPI_REG_SIZE); /* clear the previous value */ reg &= ~(CQSPI_REG_SIZE_PAGE_MASK << CQSPI_REG_SIZE_PAGE_LSB); reg &= ~(CQSPI_REG_SIZE_BLOCK_MASK << CQSPI_REG_SIZE_BLOCK_LSB); reg |= (f_pdata->page_size << CQSPI_REG_SIZE_PAGE_LSB); reg |= (f_pdata->block_size << CQSPI_REG_SIZE_BLOCK_LSB); CQSPI_WRITEL(reg, iobase + CQSPI_REG_SIZE); /* configure the chip select */ cadence_qspi_apb_chipselect (iobase, cs, pdata->ext_decoder); cadence_qspi_apb_controller_enable(iobase); return; }
static int cadence_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct udevice *bus = dev->parent; struct cadence_spi_platdata *plat = bus->platdata; struct cadence_spi_priv *priv = dev_get_priv(bus); void *base = priv->regbase; u8 *cmd_buf = priv->cmd_buf; size_t data_bytes; int err = 0; u32 mode = CQSPI_STIG_WRITE; if (flags & SPI_XFER_BEGIN) { /* copy command to local buffer */ priv->cmd_len = bitlen / 8; memcpy(cmd_buf, dout, priv->cmd_len); } if (flags == (SPI_XFER_BEGIN | SPI_XFER_END)) { /* if start and end bit are set, the data bytes is 0. */ data_bytes = 0; } else { data_bytes = bitlen / 8; } debug("%s: len=%d [bytes]\n", __func__, data_bytes); /* Set Chip select */ cadence_qspi_apb_chipselect(base, spi_chip_select(dev), CONFIG_CQSPI_DECODER); if ((flags & SPI_XFER_END) || (flags == 0)) { if (priv->cmd_len == 0) { printf("QSPI: Error, command is empty.\n"); return -1; } if (din && data_bytes) { /* read */ /* Use STIG if no address. */ if (!CQSPI_IS_ADDR(priv->cmd_len)) mode = CQSPI_STIG_READ; else mode = CQSPI_INDIRECT_READ; } else if (dout && !(flags & SPI_XFER_BEGIN)) { /* write */ if (!CQSPI_IS_ADDR(priv->cmd_len)) mode = CQSPI_STIG_WRITE; else mode = CQSPI_INDIRECT_WRITE; } switch (mode) { case CQSPI_STIG_READ: err = cadence_qspi_apb_command_read( base, priv->cmd_len, cmd_buf, data_bytes, din); break; case CQSPI_STIG_WRITE: err = cadence_qspi_apb_command_write(base, priv->cmd_len, cmd_buf, data_bytes, dout); break; case CQSPI_INDIRECT_READ: err = cadence_qspi_apb_indirect_read_setup(plat, priv->cmd_len, cmd_buf); if (!err) { err = cadence_qspi_apb_indirect_read_execute (plat, data_bytes, din); } break; case CQSPI_INDIRECT_WRITE: err = cadence_qspi_apb_indirect_write_setup (plat, priv->cmd_len, cmd_buf); if (!err) { err = cadence_qspi_apb_indirect_write_execute (plat, data_bytes, dout); } break; default: err = -1; break; } if (flags & SPI_XFER_END) { /* clear command buffer */ memset(cmd_buf, 0, sizeof(priv->cmd_buf)); priv->cmd_len = 0; } } return err; }