Hi Simon, On 07/11/19 1:25 AM, Simon Goldschmidt wrote: > Hi Vignesh, > > On Thu, Oct 17, 2019 at 2:31 PM Vignesh Raghavendra <vigne...@ti.com> wrote: >> >> Hi Simon, >> >> On 17/10/19 4:50 PM, Simon Goldschmidt wrote: >>> On Mon, Oct 14, 2019 at 3:27 PM Vignesh Raghavendra <vigne...@ti.com> wrote: >>>> >>>> Current Cadence QSPI driver has few limitations. It assumes all read >>>> operations to be in Quad mode and thus does not support SFDP parsing. >>>> Also, adding support for new mode such as Octal mode would not be >>>> possible with current configuration. Therefore move the driver over to >>>> spi-mem >>>> framework. This has added advantage that driver can be used to support >>>> SPI NAND memories too. >>>> Hence, move driver over to new spi-mem APIs. >>>> >>>> Please note that this gets rid of mode bit setting done when >>>> CONFIG_SPL_SPI_XIP is defined as there does not seem to be any user to >>>> that config option. >>> >>> I just have tried this on an socfgpa cylone5 board with an mt25ql256a, but >>> it does not seem to work: when leaving spi-rx-bus-width and spi-tx-bus-width >>> at 4 in my devicetree, SFDP parsing works, but reading data afterwards >>> produces invalid results (I haven't tested what's wrong there). >>> >> >> Thanks for testing! >> >> spi-tx-bus-width = 4 was not supported before so I haven't added support >> for that mode in this series. That change will be a separate series. >> >> Could you try with spi-tx-bus-width = 1 and spi-rx-bus-width = 4 and see >> if that works? >> >> If that does not work then could you disable SFDP parsing (but keep >> spi-rx-bus-width = 4) and see if that works. This should narrow down >> whether SFDP parsing is broken or if driver has an issue. > > Sorry, I still haven't found the time at work to test this. I'll keep trying. > Keeping that aside, if this driver is converted to spi-mem, is there any > chance of getting this into SPL while not getting standard SPI drivers in? > > On socfpga, I have a standard SPI driver (designware_spi) enabled but that > results in both the cadence_qspi and designware_spi being included in SPL > aside > well when boot-from-SPI is enabled. > > Does that somehow change when cadence_qspi is an spi-mem driver? >
I dont think so. Only solution I can think of is to create a separate SPL specific config for designware_spi and disable that for socfpga. Regards Vignesh > Thanks, > Simon > >> >> Regards >> Vignesh >> >>> It works as expected when not parsing SFDP or setting the bus-width to 1. >>> So the change itself probably works, but SFDP parsing is broken? >>> >>> I did the tests with this applied first: >>> https://patchwork.ozlabs.org/project/uboot/list/?series=135505 >>> >>> Regards, >>> Simon >>> >>> >>>> >>>> Signed-off-by: Vignesh Raghavendra <vigne...@ti.com> >>>> --- >>>> drivers/spi/cadence_qspi.c | 136 +++++++++++++-------------------- >>>> drivers/spi/cadence_qspi.h | 9 +-- >>>> drivers/spi/cadence_qspi_apb.c | 124 ++++++++---------------------- >>>> 3 files changed, 91 insertions(+), 178 deletions(-) >>>> >>>> diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c >>>> index e2e54cd27723..673a2e9a6c4c 100644 >>>> --- a/drivers/spi/cadence_qspi.c >>>> +++ b/drivers/spi/cadence_qspi.c >>>> @@ -10,6 +10,7 @@ >>>> #include <malloc.h> >>>> #include <reset.h> >>>> #include <spi.h> >>>> +#include <spi-mem.h> >>>> #include <linux/errno.h> >>>> #include "cadence_qspi.h" >>>> >>>> @@ -34,12 +35,21 @@ static int cadence_spi_write_speed(struct udevice >>>> *bus, uint hz) >>>> return 0; >>>> } >>>> >>>> +static int cadence_spi_read_id(void *reg_base, u8 len, u8 *idcode) >>>> +{ >>>> + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x9F, 1), >>>> + SPI_MEM_OP_NO_ADDR, >>>> + SPI_MEM_OP_NO_DUMMY, >>>> + SPI_MEM_OP_DATA_IN(len, idcode, >>>> 1)); >>>> + >>>> + return cadence_qspi_apb_command_read(reg_base, &op); >>>> +} >>>> + >>>> /* Calibration sequence to determine the read data capture delay register >>>> */ >>>> static int spi_calibration(struct udevice *bus, uint hz) >>>> { >>>> struct cadence_spi_priv *priv = dev_get_priv(bus); >>>> void *base = priv->regbase; >>>> - u8 opcode_rdid = 0x9F; >>>> unsigned int idcode = 0, temp = 0; >>>> int err = 0, i, range_lo = -1, range_hi = -1; >>>> >>>> @@ -53,8 +63,7 @@ static int spi_calibration(struct udevice *bus, uint hz) >>>> cadence_qspi_apb_controller_enable(base); >>>> >>>> /* read the ID which will be our golden value */ >>>> - err = cadence_qspi_apb_command_read(base, 1, &opcode_rdid, >>>> - 3, (u8 *)&idcode); >>>> + err = cadence_spi_read_id(base, 3, (u8 *)&idcode); >>>> if (err) { >>>> puts("SF: Calibration failed (read)\n"); >>>> return err; >>>> @@ -73,8 +82,7 @@ static int spi_calibration(struct udevice *bus, uint hz) >>>> cadence_qspi_apb_controller_enable(base); >>>> >>>> /* issue a RDID to get the ID value */ >>>> - err = cadence_qspi_apb_command_read(base, 1, &opcode_rdid, >>>> - 3, (u8 *)&temp); >>>> + err = cadence_spi_read_id(base, 3, (u8 *)&temp); >>>> if (err) { >>>> puts("SF: Calibration failed (read)\n"); >>>> return err; >>>> @@ -195,96 +203,56 @@ static int cadence_spi_set_mode(struct udevice *bus, >>>> uint mode) >>>> return 0; >>>> } >>>> >>>> -static int cadence_spi_xfer(struct udevice *dev, unsigned int bitlen, >>>> - const void *dout, void *din, unsigned long >>>> flags) >>>> +static int cadence_spi_mem_exec_op(struct spi_slave *spi, >>>> + const struct spi_mem_op *op) >>>> { >>>> - struct udevice *bus = dev->parent; >>>> + struct udevice *bus = spi->dev->parent; >>>> struct cadence_spi_platdata *plat = bus->platdata; >>>> struct cadence_spi_priv *priv = dev_get_priv(bus); >>>> - struct dm_spi_slave_platdata *dm_plat = >>>> dev_get_parent_platdata(dev); >>>> 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=%zu [bytes]\n", __func__, data_bytes); >>>> + u32 mode; >>>> >>>> /* Set Chip select */ >>>> - cadence_qspi_apb_chipselect(base, spi_chip_select(dev), >>>> + cadence_qspi_apb_chipselect(base, spi_chip_select(spi->dev), >>>> plat->is_decoded_cs); >>>> >>>> - 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); >>>> + if (op->data.dir == SPI_MEM_DATA_IN && op->data.buf.in) { >>>> + if (!op->addr.nbytes) >>>> + mode = CQSPI_STIG_READ; >>>> + else >>>> + mode = CQSPI_INDIRECT_READ; >>>> + } else { >>>> + if (!op->addr.nbytes || !op->data.buf.out) >>>> + mode = CQSPI_STIG_WRITE; >>>> + else >>>> + mode = CQSPI_INDIRECT_WRITE; >>>> + } >>>> >>>> + switch (mode) { >>>> + case CQSPI_STIG_READ: >>>> + err = cadence_qspi_apb_command_read(base, op); >>>> break; >>>> - case CQSPI_STIG_WRITE: >>>> - err = cadence_qspi_apb_command_write(base, >>>> - priv->cmd_len, cmd_buf, >>>> - data_bytes, dout); >>>> + case CQSPI_STIG_WRITE: >>>> + err = cadence_qspi_apb_command_write(base, op); >>>> break; >>>> - case CQSPI_INDIRECT_READ: >>>> - err = cadence_qspi_apb_indirect_read_setup(plat, >>>> - priv->cmd_len, dm_plat->mode, 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, dm_plat->mode, >>>> cmd_buf); >>>> - if (!err) { >>>> - err = >>>> cadence_qspi_apb_indirect_write_execute >>>> - (plat, data_bytes, dout); >>>> - } >>>> - break; >>>> - default: >>>> - err = -1; >>>> - break; >>>> + case CQSPI_INDIRECT_READ: >>>> + err = cadence_qspi_apb_indirect_read_setup(plat, op); >>>> + if (!err) { >>>> + err = cadence_qspi_apb_indirect_read_execute >>>> + (plat, op->data.nbytes, op->data.buf.in); >>>> } >>>> - >>>> - if (flags & SPI_XFER_END) { >>>> - /* clear command buffer */ >>>> - memset(cmd_buf, 0, sizeof(priv->cmd_buf)); >>>> - priv->cmd_len = 0; >>>> + break; >>>> + case CQSPI_INDIRECT_WRITE: >>>> + err = cadence_qspi_apb_indirect_write_setup(plat, op); >>>> + if (!err) { >>>> + err = cadence_qspi_apb_indirect_write_execute >>>> + (plat, op->data.nbytes, op->data.buf.out); >>>> } >>>> + break; >>>> + default: >>>> + err = -1; >>>> + break; >>>> } >>>> >>>> return err; >>>> @@ -332,10 +300,14 @@ static int cadence_spi_ofdata_to_platdata(struct >>>> udevice *bus) >>>> return 0; >>>> } >>>> >>>> +static const struct spi_controller_mem_ops cadence_spi_mem_ops = { >>>> + .exec_op = cadence_spi_mem_exec_op, >>>> +}; >>>> + >>>> static const struct dm_spi_ops cadence_spi_ops = { >>>> - .xfer = cadence_spi_xfer, >>>> .set_speed = cadence_spi_set_speed, >>>> .set_mode = cadence_spi_set_mode, >>>> + .mem_ops = &cadence_spi_mem_ops, >>>> /* >>>> * cs_info is not needed, since we require all chip selects to be >>>> * in the device tree explicitly >>>> diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h >>>> index 20cceca239f8..e655b027d788 100644 >>>> --- a/drivers/spi/cadence_qspi.h >>>> +++ b/drivers/spi/cadence_qspi.h >>>> @@ -54,17 +54,16 @@ void cadence_qspi_apb_controller_enable(void >>>> *reg_base_addr); >>>> void cadence_qspi_apb_controller_disable(void *reg_base_addr); >>>> >>>> int cadence_qspi_apb_command_read(void *reg_base_addr, >>>> - unsigned int cmdlen, const u8 *cmdbuf, unsigned int rxlen, u8 >>>> *rxbuf); >>>> + const struct spi_mem_op *op); >>>> int cadence_qspi_apb_command_write(void *reg_base_addr, >>>> - unsigned int cmdlen, const u8 *cmdbuf, >>>> - unsigned int txlen, const u8 *txbuf); >>>> + const struct spi_mem_op *op); >>>> >>>> int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata >>>> *plat, >>>> - unsigned int cmdlen, unsigned int rx_width, const u8 *cmdbuf); >>>> + const struct spi_mem_op *op); >>>> int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata >>>> *plat, >>>> unsigned int rxlen, u8 *rxbuf); >>>> int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata >>>> *plat, >>>> - unsigned int cmdlen, unsigned int tx_width, const u8 *cmdbuf); >>>> + const struct spi_mem_op *op); >>>> int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata >>>> *plat, >>>> unsigned int txlen, const u8 *txbuf); >>>> >>>> diff --git a/drivers/spi/cadence_qspi_apb.c >>>> b/drivers/spi/cadence_qspi_apb.c >>>> index 55a7501913a8..8dd0495dfcf4 100644 >>>> --- a/drivers/spi/cadence_qspi_apb.c >>>> +++ b/drivers/spi/cadence_qspi_apb.c >>>> @@ -30,6 +30,7 @@ >>>> #include <linux/errno.h> >>>> #include <wait_bit.h> >>>> #include <spi.h> >>>> +#include <spi-mem.h> >>>> #include <malloc.h> >>>> #include "cadence_qspi.h" >>>> >>>> @@ -172,19 +173,6 @@ >>>> (((readl(reg_base + CQSPI_REG_SDRAMLEVEL)) >> \ >>>> CQSPI_REG_SDRAMLEVEL_WR_LSB) & CQSPI_REG_SDRAMLEVEL_WR_MASK) >>>> >>>> -static unsigned int cadence_qspi_apb_cmd2addr(const unsigned char >>>> *addr_buf, >>>> - unsigned int addr_width) >>>> -{ >>>> - unsigned int addr; >>>> - >>>> - addr = (addr_buf[0] << 16) | (addr_buf[1] << 8) | addr_buf[2]; >>>> - >>>> - if (addr_width == 4) >>>> - addr = (addr << 8) | addr_buf[3]; >>>> - >>>> - return addr; >>>> -} >>>> - >>>> void cadence_qspi_apb_controller_enable(void *reg_base) >>>> { >>>> unsigned int reg; >>>> @@ -433,21 +421,20 @@ static int cadence_qspi_apb_exec_flash_cmd(void >>>> *reg_base, >>>> } >>>> >>>> /* For command RDID, RDSR. */ >>>> -int cadence_qspi_apb_command_read(void *reg_base, >>>> - unsigned int cmdlen, const u8 *cmdbuf, unsigned int rxlen, >>>> - u8 *rxbuf) >>>> +int cadence_qspi_apb_command_read(void *reg_base, const struct spi_mem_op >>>> *op) >>>> { >>>> unsigned int reg; >>>> unsigned int read_len; >>>> int status; >>>> + unsigned int rxlen = op->data.nbytes; >>>> + void *rxbuf = op->data.buf.in; >>>> >>>> - if (!cmdlen || rxlen > CQSPI_STIG_DATA_LEN_MAX || rxbuf == NULL) { >>>> - printf("QSPI: Invalid input arguments cmdlen %d rxlen >>>> %d\n", >>>> - cmdlen, rxlen); >>>> + if (rxlen > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) { >>>> + printf("QSPI: Invalid input arguments rxlen %u\n", rxlen); >>>> return -EINVAL; >>>> } >>>> >>>> - reg = cmdbuf[0] << CQSPI_REG_CMDCTRL_OPCODE_LSB; >>>> + reg = op->cmd.opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; >>>> >>>> reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB); >>>> >>>> @@ -475,34 +462,30 @@ int cadence_qspi_apb_command_read(void *reg_base, >>>> } >>>> >>>> /* For commands: WRSR, WREN, WRDI, CHIP_ERASE, BE, etc. */ >>>> -int cadence_qspi_apb_command_write(void *reg_base, unsigned int cmdlen, >>>> - const u8 *cmdbuf, unsigned int txlen, const u8 *txbuf) >>>> +int cadence_qspi_apb_command_write(void *reg_base, const struct >>>> spi_mem_op *op) >>>> { >>>> unsigned int reg = 0; >>>> - unsigned int addr_value; >>>> unsigned int wr_data; >>>> unsigned int wr_len; >>>> + unsigned int txlen = op->data.nbytes; >>>> + const void *txbuf = op->data.buf.out; >>>> + u32 addr; >>>> + >>>> + /* Reorder address to SPI bus order if only transferring address */ >>>> + if (!txlen) { >>>> + addr = cpu_to_be32(op->addr.val); >>>> + if (op->addr.nbytes == 3) >>>> + addr >>= 8; >>>> + txbuf = &addr; >>>> + txlen = op->addr.nbytes; >>>> + } >>>> >>>> - if (!cmdlen || cmdlen > 5 || txlen > 8 || cmdbuf == NULL) { >>>> - printf("QSPI: Invalid input arguments cmdlen %d txlen >>>> %d\n", >>>> - cmdlen, txlen); >>>> + if (txlen > CQSPI_STIG_DATA_LEN_MAX) { >>>> + printf("QSPI: Invalid input arguments txlen %u\n", txlen); >>>> return -EINVAL; >>>> } >>>> >>>> - reg |= cmdbuf[0] << CQSPI_REG_CMDCTRL_OPCODE_LSB; >>>> - >>>> - if (cmdlen == 4 || cmdlen == 5) { >>>> - /* Command with address */ >>>> - reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB); >>>> - /* Number of bytes to write. */ >>>> - reg |= ((cmdlen - 2) & CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) >>>> - << CQSPI_REG_CMDCTRL_ADD_BYTES_LSB; >>>> - /* Get address */ >>>> - addr_value = cadence_qspi_apb_cmd2addr(&cmdbuf[1], >>>> - cmdlen >= 5 ? 4 : 3); >>>> - >>>> - writel(addr_value, reg_base + CQSPI_REG_CMDADDRESS); >>>> - } >>>> + reg |= op->cmd.opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; >>>> >>>> if (txlen) { >>>> /* writing data = yes */ >>>> @@ -530,61 +513,32 @@ int cadence_qspi_apb_command_write(void *reg_base, >>>> unsigned int cmdlen, >>>> >>>> /* Opcode + Address (3/4 bytes) + dummy bytes (0-4 bytes) */ >>>> int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata >>>> *plat, >>>> - unsigned int cmdlen, unsigned int rx_width, const u8 *cmdbuf) >>>> + const struct spi_mem_op *op) >>>> { >>>> unsigned int reg; >>>> unsigned int rd_reg; >>>> - unsigned int addr_value; >>>> unsigned int dummy_clk; >>>> - unsigned int dummy_bytes; >>>> - unsigned int addr_bytes; >>>> - >>>> - /* >>>> - * Identify addr_byte. All NOR flash device drivers are using fast >>>> read >>>> - * which always expecting 1 dummy byte, 1 cmd byte and 3/4 addr >>>> byte. >>>> - * With that, the length is in value of 5 or 6. Only FRAM chip from >>>> - * ramtron using normal read (which won't need dummy byte). >>>> - * Unlikely NOR flash using normal read due to performance issue. >>>> - */ >>>> - if (cmdlen >= 5) >>>> - /* to cater fast read where cmd + addr + dummy */ >>>> - addr_bytes = cmdlen - 2; >>>> - else >>>> - /* for normal read (only ramtron as of now) */ >>>> - addr_bytes = cmdlen - 1; >>>> + unsigned int dummy_bytes = op->dummy.nbytes; >>>> >>>> /* Setup the indirect trigger address */ >>>> writel(plat->trigger_address, >>>> plat->regbase + CQSPI_REG_INDIRECTTRIGGER); >>>> >>>> /* Configure the opcode */ >>>> - rd_reg = cmdbuf[0] << CQSPI_REG_RD_INSTR_OPCODE_LSB; >>>> + rd_reg = op->cmd.opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB; >>>> >>>> - if (rx_width & SPI_RX_QUAD) >>>> + if (op->data.buswidth == 4) >>>> /* Instruction and address at DQ0, data at DQ0-3. */ >>>> rd_reg |= CQSPI_INST_TYPE_QUAD << >>>> CQSPI_REG_RD_INSTR_TYPE_DATA_LSB; >>>> >>>> - /* Get address */ >>>> - addr_value = cadence_qspi_apb_cmd2addr(&cmdbuf[1], addr_bytes); >>>> - writel(addr_value, plat->regbase + CQSPI_REG_INDIRECTRDSTARTADDR); >>>> + writel(op->addr.val, plat->regbase + >>>> CQSPI_REG_INDIRECTRDSTARTADDR); >>>> >>>> - /* The remaining lenght is dummy bytes. */ >>>> - dummy_bytes = cmdlen - addr_bytes - 1; >>>> if (dummy_bytes) { >>>> if (dummy_bytes > CQSPI_DUMMY_BYTES_MAX) >>>> dummy_bytes = CQSPI_DUMMY_BYTES_MAX; >>>> >>>> - rd_reg |= (1 << CQSPI_REG_RD_INSTR_MODE_EN_LSB); >>>> -#if defined(CONFIG_SPL_SPI_XIP) && defined(CONFIG_SPL_BUILD) >>>> - writel(0x0, plat->regbase + CQSPI_REG_MODE_BIT); >>>> -#else >>>> - writel(0xFF, plat->regbase + CQSPI_REG_MODE_BIT); >>>> -#endif >>>> - >>>> /* Convert to clock cycles. */ >>>> dummy_clk = dummy_bytes * CQSPI_DUMMY_CLKS_PER_BYTE; >>>> - /* Need to minus the mode byte (8 clocks). */ >>>> - dummy_clk -= CQSPI_DUMMY_CLKS_PER_BYTE; >>>> >>>> if (dummy_clk) >>>> rd_reg |= (dummy_clk & >>>> CQSPI_REG_RD_INSTR_DUMMY_MASK) >>>> @@ -596,7 +550,7 @@ int cadence_qspi_apb_indirect_read_setup(struct >>>> cadence_spi_platdata *plat, >>>> /* set device size */ >>>> reg = readl(plat->regbase + CQSPI_REG_SIZE); >>>> reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK; >>>> - reg |= (addr_bytes - 1); >>>> + reg |= (op->addr.nbytes - 1); >>>> writel(reg, plat->regbase + CQSPI_REG_SIZE); >>>> return 0; >>>> } >>>> @@ -687,35 +641,23 @@ failrd: >>>> >>>> /* Opcode + Address (3/4 bytes) */ >>>> int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata >>>> *plat, >>>> - unsigned int cmdlen, unsigned int tx_width, const u8 *cmdbuf) >>>> + const struct spi_mem_op *op) >>>> { >>>> unsigned int reg; >>>> - unsigned int addr_bytes = cmdlen > 4 ? 4 : 3; >>>> >>>> - if (cmdlen < 4 || cmdbuf == NULL) { >>>> - printf("QSPI: Invalid input argument, len %d cmdbuf %p\n", >>>> - cmdlen, cmdbuf); >>>> - return -EINVAL; >>>> - } >>>> /* Setup the indirect trigger address */ >>>> writel(plat->trigger_address, >>>> plat->regbase + CQSPI_REG_INDIRECTTRIGGER); >>>> >>>> /* Configure the opcode */ >>>> - reg = cmdbuf[0] << CQSPI_REG_WR_INSTR_OPCODE_LSB; >>>> - >>>> - if (tx_width & SPI_TX_QUAD) >>>> - reg |= CQSPI_INST_TYPE_QUAD << >>>> CQSPI_REG_WR_INSTR_TYPE_DATA_LSB; >>>> - >>>> + reg = op->cmd.opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB; >>>> writel(reg, plat->regbase + CQSPI_REG_WR_INSTR); >>>> >>>> - /* Setup write address. */ >>>> - reg = cadence_qspi_apb_cmd2addr(&cmdbuf[1], addr_bytes); >>>> - writel(reg, plat->regbase + CQSPI_REG_INDIRECTWRSTARTADDR); >>>> + writel(op->addr.val, plat->regbase + >>>> CQSPI_REG_INDIRECTWRSTARTADDR); >>>> >>>> reg = readl(plat->regbase + CQSPI_REG_SIZE); >>>> reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK; >>>> - reg |= (addr_bytes - 1); >>>> + reg |= (op->addr.nbytes - 1); >>>> writel(reg, plat->regbase + CQSPI_REG_SIZE); >>>> return 0; >>>> } >>>> -- >>>> 2.23.0 >>>> >> >> -- >> Regards >> Vignesh -- Regards Vignesh _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot