[U-Boot] [PATCH 1/2] spi: cadence_qspi: Move to spi-mem framework
Vignesh Raghavendra
vigneshr at ti.com
Thu Nov 7 06:09:55 UTC 2019
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 <vigneshr at 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 <vigneshr at 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 <vigneshr at 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
More information about the U-Boot
mailing list