From 5d40b3d384dc536ec26ce9b76b20b0b84749d2d1 Mon Sep 17 00:00:00 2001 From: Venkatesh Yadav Abbarapu Date: Thu, 26 Sep 2024 10:25:02 +0530 Subject: mtd: spi-nor: Add parallel and stacked memories support In parallel mode, the current implementation assumes that a maximum of two flashes are connected. The QSPI controller splits the data evenly between both the flashes so, both the flashes that are connected in parallel mode should be identical. During each operation SPI-NOR sets 0th bit for CS0 & 1st bit for CS1 in nor->flags. In stacked mode the current implementation assumes that a maximum of two flashes are connected and both the flashes are of same make but can differ in sizes. So, except the sizes all other flash parameters of both the flashes are identical Spi-nor will pass on the appropriate flash select flag to low level driver, and it will select pass all the data to that particular flash. Write operation in parallel mode are performed in page size * 2 chunks as each write operation results in writing both the flashes. For doubling the address space each operation is performed at addr/2 flash offset, where addr is the address specified by the user. Similarly for read and erase operations it will read from both flashes, so size and offset are divided by 2 and send to flash. Adding the config option SPI_ADVANCE for non SPL code. Signed-off-by: Ashok Reddy Soma Signed-off-by: Venkatesh Yadav Abbarapu --- include/linux/mtd/spi-nor.h | 17 +++++++++++++++++ include/spi.h | 11 +++++++++++ 2 files changed, 28 insertions(+) (limited to 'include') diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index d1dbf3eadbf..d5f4faf0a68 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -13,6 +13,9 @@ #include #include +/* In parallel configuration enable multiple CS */ +#define SPI_NOR_ENABLE_MULTI_CS (BIT(0) | BIT(1)) + /* * Manufacturer IDs * @@ -177,6 +180,12 @@ /* Status Register 2 bits. */ #define SR2_QUAD_EN_BIT7 BIT(7) +/* + * Maximum number of flashes that can be connected + * in stacked/parallel configuration + */ +#define SNOR_FLASH_CNT_MAX 2 + /* For Cypress flash. */ #define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */ #define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */ @@ -294,6 +303,13 @@ enum spi_nor_option_flags { SNOR_F_BROKEN_RESET = BIT(6), SNOR_F_SOFT_RESET = BIT(7), SNOR_F_IO_MODE_EN_VOLATILE = BIT(8), +#if defined(CONFIG_SPI_ADVANCE) + SNOR_F_HAS_STACKED = BIT(9), + SNOR_F_HAS_PARALLEL = BIT(10), +#else + SNOR_F_HAS_STACKED = 0, + SNOR_F_HAS_PARALLEL = 0, +#endif }; struct spi_nor; @@ -551,6 +567,7 @@ struct spi_nor { u8 bank_read_cmd; u8 bank_write_cmd; u8 bank_curr; + u8 upage_prev; #endif enum spi_nor_protocol read_proto; enum spi_nor_protocol write_proto; diff --git a/include/spi.h b/include/spi.h index 9e9851284c8..6e8e0cce7f2 100644 --- a/include/spi.h +++ b/include/spi.h @@ -38,6 +38,15 @@ #define SPI_DEFAULT_WORDLEN 8 +/* SPI transfer flags */ +#define SPI_XFER_STRIPE (1 << 6) +#define SPI_XFER_MASK (3 << 8) +#define SPI_XFER_LOWER (1 << 8) +#define SPI_XFER_UPPER (2 << 8) + +/* Max no. of CS supported per spi device */ +#define SPI_CS_CNT_MAX 2 + /** * struct dm_spi_bus - SPI bus info * @@ -155,6 +164,8 @@ struct spi_slave { #define SPI_XFER_BEGIN BIT(0) /* Assert CS before transfer */ #define SPI_XFER_END BIT(1) /* Deassert CS after transfer */ #define SPI_XFER_ONCE (SPI_XFER_BEGIN | SPI_XFER_END) +#define SPI_XFER_U_PAGE BIT(4) +#define SPI_XFER_STACKED BIT(5) }; /** -- cgit v1.3.1 From 34da258bb0465de4bf44dc8949a9536cc06bf725 Mon Sep 17 00:00:00 2001 From: Venkatesh Yadav Abbarapu Date: Thu, 26 Sep 2024 10:25:05 +0530 Subject: spi: spi-uclass: Read chipselect and restrict capabilities Read chipselect properties from DT which are populated using 'reg' property and save it in plat->cs[] array for later use. Also read multi chipselect capability which is used for parallel-memories and return errors if they are passed on using DT but driver is not capable of handling it. Signed-off-by: Ashok Reddy Soma Signed-off-by: Venkatesh Yadav Abbarapu --- drivers/mtd/spi/sandbox.c | 2 +- drivers/spi/altera_spi.c | 4 ++-- drivers/spi/atcspi200_spi.c | 2 +- drivers/spi/ath79_spi.c | 2 +- drivers/spi/atmel_spi.c | 6 +++--- drivers/spi/bcm63xx_hsspi.c | 42 +++++++++++++++++++++--------------------- drivers/spi/bcm63xx_spi.c | 6 +++--- drivers/spi/bcmbca_hsspi.c | 34 +++++++++++++++++----------------- drivers/spi/cf_spi.c | 6 +++--- drivers/spi/davinci_spi.c | 8 ++++---- drivers/spi/fsl_dspi.c | 18 +++++++++--------- drivers/spi/fsl_espi.c | 4 ++-- drivers/spi/fsl_qspi.c | 4 ++-- drivers/spi/gxp_spi.c | 2 +- drivers/spi/mpc8xx_spi.c | 4 ++-- drivers/spi/mpc8xxx_spi.c | 10 +++++----- drivers/spi/mscc_bb_spi.c | 4 ++-- drivers/spi/mxc_spi.c | 6 +++--- drivers/spi/npcm_fiu_spi.c | 14 +++++++------- drivers/spi/nxp_fspi.c | 2 +- drivers/spi/octeon_spi.c | 2 +- drivers/spi/omap3_spi.c | 4 ++-- drivers/spi/pic32_spi.c | 2 +- drivers/spi/rk_spi.c | 4 ++-- drivers/spi/rockchip_sfc.c | 2 +- drivers/spi/spi-aspeed-smc.c | 28 ++++++++++++++-------------- drivers/spi/spi-mxic.c | 6 +++--- drivers/spi/spi-qup.c | 4 ++-- drivers/spi/spi-sifive.c | 6 +++--- drivers/spi/spi-sn-f-ospi.c | 2 +- drivers/spi/spi-sunxi.c | 6 +++--- drivers/spi/spi-synquacer.c | 4 ++-- drivers/spi/spi-uclass.c | 30 +++++++++++++++++++++++++----- drivers/spi/stm32_qspi.c | 2 +- drivers/spi/stm32_spi.c | 4 ++-- drivers/spi/ti_qspi.c | 14 +++++++------- drivers/spi/xilinx_spi.c | 6 +++--- drivers/spi/zynq_qspi.c | 6 +++--- drivers/spi/zynq_spi.c | 6 +++--- include/spi.h | 8 +++++++- lib/acpi/acpi_device.c | 2 +- 41 files changed, 177 insertions(+), 151 deletions(-) (limited to 'include') diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c index 2d5a16bf6a2..e5ebc3479fb 100644 --- a/drivers/mtd/spi/sandbox.c +++ b/drivers/mtd/spi/sandbox.c @@ -138,7 +138,7 @@ static int sandbox_sf_probe(struct udevice *dev) return ret; } slave_plat = dev_get_parent_plat(dev); - cs = slave_plat->cs; + cs = slave_plat->cs[0]; debug("found at cs %d\n", cs); if (!pdata->filename) { diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c index 8e227d187b0..dafaf1130bb 100644 --- a/drivers/spi/altera_spi.c +++ b/drivers/spi/altera_spi.c @@ -95,7 +95,7 @@ static int altera_spi_xfer(struct udevice *dev, unsigned int bitlen, uint32_t reg, data, start; debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__, - dev_seq(bus), slave_plat->cs, bitlen, bytes, flags); + dev_seq(bus), slave_plat->cs[0], bitlen, bytes, flags); if (bitlen == 0) goto done; @@ -110,7 +110,7 @@ static int altera_spi_xfer(struct udevice *dev, unsigned int bitlen, readl(®s->rxdata); if (flags & SPI_XFER_BEGIN) - spi_cs_activate(dev, slave_plat->cs); + spi_cs_activate(dev, slave_plat->cs[0]); while (bytes--) { if (txp) diff --git a/drivers/spi/atcspi200_spi.c b/drivers/spi/atcspi200_spi.c index 2178534baf0..72b612c6560 100644 --- a/drivers/spi/atcspi200_spi.c +++ b/drivers/spi/atcspi200_spi.c @@ -319,7 +319,7 @@ static int atcspi200_spi_claim_bus(struct udevice *dev) struct udevice *bus = dev->parent; struct nds_spi_slave *ns = dev_get_priv(bus); - if (slave_plat->cs >= ns->num_cs) { + if (slave_plat->cs[0] >= ns->num_cs) { printf("Invalid SPI chipselect\n"); return -EINVAL; } diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c index fb2d77d7d4a..b0ed14f0cfc 100644 --- a/drivers/spi/ath79_spi.c +++ b/drivers/spi/ath79_spi.c @@ -73,7 +73,7 @@ static int ath79_spi_xfer(struct udevice *dev, unsigned int bitlen, if (restbits) bytes++; - out = AR71XX_SPI_IOC_CS_ALL & ~(AR71XX_SPI_IOC_CS(slave->cs)); + out = AR71XX_SPI_IOC_CS_ALL & ~(AR71XX_SPI_IOC_CS(slave->cs[0])); while (bytes > 0) { bytes--; curbyte = 0; diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 79f01001318..aaf3eddae42 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -125,7 +125,7 @@ static int atmel_spi_claim_bus(struct udevice *dev) struct atmel_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); struct at91_spi *reg_base = bus_plat->regs; - u32 cs = slave_plat->cs; + u32 cs = slave_plat->cs[0]; u32 freq = priv->freq; u32 scbr, csrx, mode; @@ -174,7 +174,7 @@ static void atmel_spi_cs_activate(struct udevice *dev) struct udevice *bus = dev_get_parent(dev); struct atmel_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - u32 cs = slave_plat->cs; + u32 cs = slave_plat->cs[0]; if (!dm_gpio_is_valid(&priv->cs_gpios[cs])) return; @@ -189,7 +189,7 @@ static void atmel_spi_cs_deactivate(struct udevice *dev) struct udevice *bus = dev_get_parent(dev); struct atmel_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - u32 cs = slave_plat->cs; + u32 cs = slave_plat->cs[0]; if (!dm_gpio_is_valid(&priv->cs_gpios[cs])) return; diff --git a/drivers/spi/bcm63xx_hsspi.c b/drivers/spi/bcm63xx_hsspi.c index 1aa43fd3a23..e9f0b343abb 100644 --- a/drivers/spi/bcm63xx_hsspi.c +++ b/drivers/spi/bcm63xx_hsspi.c @@ -174,7 +174,7 @@ static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv, set = DIV_ROUND_UP(2048, set); set &= SPI_PFL_CLK_FREQ_MASK; set |= SPI_PFL_CLK_RSTLOOP_MASK; - writel(set, priv->regs + SPI_PFL_CLK_REG(plat->cs)); + writel(set, priv->regs + SPI_PFL_CLK_REG(plat->cs[0])); /* profile signal */ set = 0; @@ -192,29 +192,29 @@ static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv, if (speed > SPI_MAX_SYNC_CLOCK) set |= SPI_PFL_SIG_ASYNCIN_MASK; - clrsetbits_32(priv->regs + SPI_PFL_SIG_REG(plat->cs), clr, set); + clrsetbits_32(priv->regs + SPI_PFL_SIG_REG(plat->cs[0]), clr, set); /* global control */ set = 0; clr = 0; if (priv->xfer_mode == HSSPI_XFER_MODE_PREPEND) { - if (priv->cs_pols & BIT(plat->cs)) - set |= BIT(plat->cs); + if (priv->cs_pols & BIT(plat->cs[0])) + set |= BIT(plat->cs[0]); else - clr |= BIT(plat->cs); + clr |= BIT(plat->cs[0]); } else { /* invert cs polarity */ - if (priv->cs_pols & BIT(plat->cs)) - clr |= BIT(plat->cs); + if (priv->cs_pols & BIT(plat->cs[0])) + clr |= BIT(plat->cs[0]); else - set |= BIT(plat->cs); + set |= BIT(plat->cs[0]); /* invert dummy cs polarity */ - if (priv->cs_pols & BIT(!plat->cs)) - clr |= BIT(!plat->cs); + if (priv->cs_pols & BIT(!plat->cs[0])) + clr |= BIT(!plat->cs[0]); else - set |= BIT(!plat->cs); + set |= BIT(!plat->cs[0]); } clrsetbits_32(priv->regs + SPI_CTL_REG, clr, set); @@ -290,7 +290,7 @@ static int bcm63xx_hsspi_xfer_dummy_cs(struct udevice *dev, unsigned int data_by if (plat->mode & SPI_3WIRE) val |= SPI_PFL_MODE_3WIRE_MASK; - writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs)); + writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs[0])); /* transfer loop */ while (data_bytes > 0) { @@ -310,9 +310,9 @@ static int bcm63xx_hsspi_xfer_dummy_cs(struct udevice *dev, unsigned int data_by /* issue the transfer */ val = SPI_CMD_OP_START; - val |= (plat->cs << SPI_CMD_PFL_SHIFT) & + val |= (plat->cs[0] << SPI_CMD_PFL_SHIFT) & SPI_CMD_PFL_MASK; - val |= (!plat->cs << SPI_CMD_SLAVE_SHIFT) & + val |= (!plat->cs[0] << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK; writel(val, priv->regs + SPI_CMD_REG); @@ -450,7 +450,7 @@ static int bcm63xx_hsspi_xfer_prepend(struct udevice *dev, unsigned int data_byt } } val |= (priv->prepend_cnt << SPI_PFL_MODE_PREPCNT_SHIFT); - writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs)); + writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs[0])); /* set fifo operation */ val = opcode | (data_bytes & HSSPI_FIFO_OP_BYTES_MASK); @@ -459,9 +459,9 @@ static int bcm63xx_hsspi_xfer_prepend(struct udevice *dev, unsigned int data_byt /* issue the transfer */ val = SPI_CMD_OP_START; - val |= (plat->cs << SPI_CMD_PFL_SHIFT) & + val |= (plat->cs[0] << SPI_CMD_PFL_SHIFT) & SPI_CMD_PFL_MASK; - val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & + val |= (plat->cs[0] << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK; writel(val, priv->regs + SPI_CMD_REG); @@ -537,16 +537,16 @@ static int bcm63xx_hsspi_child_pre_probe(struct udevice *dev) struct spi_slave *slave = dev_get_parent_priv(dev); /* check cs */ - if (plat->cs >= priv->num_cs) { - printf("no cs %u\n", plat->cs); + if (plat->cs[0] >= priv->num_cs) { + printf("no cs %u\n", plat->cs[0]); return -ENODEV; } /* cs polarity */ if (plat->mode & SPI_CS_HIGH) - priv->cs_pols |= BIT(plat->cs); + priv->cs_pols |= BIT(plat->cs[0]); else - priv->cs_pols &= ~BIT(plat->cs); + priv->cs_pols &= ~BIT(plat->cs[0]); /* * set the max read/write size to make sure each xfer are within the diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c index 595b41c8ab8..e02ec7e8bd7 100644 --- a/drivers/spi/bcm63xx_spi.c +++ b/drivers/spi/bcm63xx_spi.c @@ -275,7 +275,7 @@ static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen, /* issue the transfer */ cmd = SPI_CMD_OP_START; - cmd |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK; + cmd |= (plat->cs[0] << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK; cmd |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT); if (plat->mode & SPI_3WIRE) cmd |= SPI_CMD_3WIRE_MASK; @@ -353,8 +353,8 @@ static int bcm63xx_spi_child_pre_probe(struct udevice *dev) struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev); /* check cs */ - if (plat->cs >= priv->num_cs) { - printf("no cs %u\n", plat->cs); + if (plat->cs[0] >= priv->num_cs) { + printf("no cs %u\n", plat->cs[0]); return -ENODEV; } diff --git a/drivers/spi/bcmbca_hsspi.c b/drivers/spi/bcmbca_hsspi.c index eff9e1117d3..209ca713279 100644 --- a/drivers/spi/bcmbca_hsspi.c +++ b/drivers/spi/bcmbca_hsspi.c @@ -155,7 +155,7 @@ static void bcmbca_hsspi_setup_clock(struct bcmbca_hsspi_priv *priv, set = DIV_ROUND_UP(2048, set); set &= SPI_PFL_CLK_FREQ_MASK; set |= SPI_PFL_CLK_RSTLOOP_MASK; - writel(set, priv->regs + SPI_PFL_CLK_REG(plat->cs)); + writel(set, priv->regs + SPI_PFL_CLK_REG(plat->cs[0])); /* profile signal */ set = 0; @@ -173,16 +173,16 @@ static void bcmbca_hsspi_setup_clock(struct bcmbca_hsspi_priv *priv, if (priv->speed > SPI_MAX_SYNC_CLOCK) set |= SPI_PFL_SIG_ASYNCIN_MASK; - clrsetbits_32(priv->regs + SPI_PFL_SIG_REG(plat->cs), clr, set); + clrsetbits_32(priv->regs + SPI_PFL_SIG_REG(plat->cs[0]), clr, set); /* global control */ set = 0; clr = 0; - if (priv->cs_pols & BIT(plat->cs)) - set |= BIT(plat->cs); + if (priv->cs_pols & BIT(plat->cs[0])) + set |= BIT(plat->cs[0]); else - clr |= BIT(plat->cs); + clr |= BIT(plat->cs[0]); clrsetbits_32(priv->regs + SPI_CTL_REG, clr, set); } @@ -194,7 +194,7 @@ static void bcmbca_hsspi_activate_cs(struct bcmbca_hsspi_priv *priv, /* set the override bit */ val = readl(priv->spim_ctrl); - val |= BIT(plat->cs + SPIM_CTRL_CS_OVERRIDE_SEL_SHIFT); + val |= BIT(plat->cs[0] + SPIM_CTRL_CS_OVERRIDE_SEL_SHIFT); writel(val, priv->spim_ctrl); } @@ -205,7 +205,7 @@ static void bcmbca_hsspi_deactivate_cs(struct bcmbca_hsspi_priv *priv, /* clear the cs override bit */ val = readl(priv->spim_ctrl); - val &= ~BIT(plat->cs + SPIM_CTRL_CS_OVERRIDE_SEL_SHIFT); + val &= ~BIT(plat->cs[0] + SPIM_CTRL_CS_OVERRIDE_SEL_SHIFT); writel(val, priv->spim_ctrl); } @@ -250,7 +250,7 @@ static int bcmbca_hsspi_xfer(struct udevice *dev, unsigned int bitlen, if (plat->mode & SPI_3WIRE) val |= SPI_PFL_MODE_3WIRE_MASK; - writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs)); + writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs[0])); /* transfer loop */ while (data_bytes > 0) { @@ -276,9 +276,9 @@ static int bcmbca_hsspi_xfer(struct udevice *dev, unsigned int bitlen, /* issue the transfer */ val = SPI_CMD_OP_START; - val |= (plat->cs << SPI_CMD_PFL_SHIFT) & + val |= (plat->cs[0] << SPI_CMD_PFL_SHIFT) & SPI_CMD_PFL_MASK; - val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & + val |= (plat->cs[0] << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK; writel(val, priv->regs + SPI_CMD_REG); @@ -326,22 +326,22 @@ static int bcmbca_hsspi_child_pre_probe(struct udevice *dev) u32 val; /* check cs */ - if (plat->cs >= priv->num_cs) { - dev_err(dev, "no cs %u\n", plat->cs); + if (plat->cs[0] >= priv->num_cs) { + dev_err(dev, "no cs %u\n", plat->cs[0]); return -EINVAL; } /* cs polarity */ if (plat->mode & SPI_CS_HIGH) - priv->cs_pols |= BIT(plat->cs); + priv->cs_pols |= BIT(plat->cs[0]); else - priv->cs_pols &= ~BIT(plat->cs); + priv->cs_pols &= ~BIT(plat->cs[0]); /* set the polarity to spim cs register */ val = readl(priv->spim_ctrl); - val &= ~BIT(plat->cs + SPIM_CTRL_CS_OVERRIDE_VAL_SHIFT); - if (priv->cs_pols & BIT(plat->cs)) - val |= BIT(plat->cs + SPIM_CTRL_CS_OVERRIDE_VAL_SHIFT); + val &= ~BIT(plat->cs[0] + SPIM_CTRL_CS_OVERRIDE_VAL_SHIFT); + if (priv->cs_pols & BIT(plat->cs[0])) + val |= BIT(plat->cs[0] + SPIM_CTRL_CS_OVERRIDE_VAL_SHIFT); writel(val, priv->spim_ctrl); return 0; diff --git a/drivers/spi/cf_spi.c b/drivers/spi/cf_spi.c index 8234468b1d4..84077c01d83 100644 --- a/drivers/spi/cf_spi.c +++ b/drivers/spi/cf_spi.c @@ -123,7 +123,7 @@ static int coldfire_spi_claim_bus(struct udevice *dev) /* Clear FIFO and resume transfer */ clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF); - dspi_chip_select(slave_plat->cs); + dspi_chip_select(slave_plat->cs[0]); return 0; } @@ -139,7 +139,7 @@ static int coldfire_spi_release_bus(struct udevice *dev) /* Clear FIFO */ clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF); - dspi_chip_unselect(slave_plat->cs); + dspi_chip_unselect(slave_plat->cs[0]); return 0; } @@ -168,7 +168,7 @@ static int coldfire_spi_xfer(struct udevice *dev, unsigned int bitlen, if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN) ctrl |= DSPI_TFR_CONT; - ctrl = setup_ctrl(ctrl, slave_plat->cs); + ctrl = setup_ctrl(ctrl, slave_plat->cs[0]); if (len > 1) { int tmp_len = len - 1; diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 82049872d05..b264c52abbd 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -338,13 +338,13 @@ static int davinci_spi_claim_bus(struct udevice *dev) struct udevice *bus = dev->parent; struct davinci_spi_slave *ds = dev_get_priv(bus); - if (slave_plat->cs >= ds->num_cs) { + if (slave_plat->cs[0] >= ds->num_cs) { printf("Invalid SPI chipselect\n"); return -EINVAL; } ds->half_duplex = slave_plat->mode & SPI_PREAMBLE; - return __davinci_spi_claim_bus(ds, slave_plat->cs); + return __davinci_spi_claim_bus(ds, slave_plat->cs[0]); } static int davinci_spi_release_bus(struct udevice *dev) @@ -363,11 +363,11 @@ static int davinci_spi_xfer(struct udevice *dev, unsigned int bitlen, struct udevice *bus = dev->parent; struct davinci_spi_slave *ds = dev_get_priv(bus); - if (slave->cs >= ds->num_cs) { + if (slave->cs[0] >= ds->num_cs) { printf("Invalid SPI chipselect\n"); return -EINVAL; } - ds->cur_cs = slave->cs; + ds->cur_cs = slave->cs[0]; return __davinci_spi_xfer(ds, bitlen, dout, din, flags); } diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c index 1d4d90ce5aa..f2393c041f4 100644 --- a/drivers/spi/fsl_dspi.c +++ b/drivers/spi/fsl_dspi.c @@ -452,9 +452,9 @@ static int fsl_dspi_child_pre_probe(struct udevice *dev) unsigned char pcssck = 0, cssck = 0; unsigned char pasc = 0, asc = 0; - if (slave_plat->cs >= priv->num_chipselect) { + if (slave_plat->cs[0] >= priv->num_chipselect) { debug("DSPI invalid chipselect number %d(max %d)!\n", - slave_plat->cs, priv->num_chipselect - 1); + slave_plat->cs[0], priv->num_chipselect - 1); return -EINVAL; } @@ -469,12 +469,12 @@ static int fsl_dspi_child_pre_probe(struct udevice *dev) /* Set After SCK delay scale values */ ns_delay_scale(&pasc, &asc, sck_cs_delay, priv->bus_clk); - priv->ctar_val[slave_plat->cs] = DSPI_CTAR_DEFAULT_VALUE | + priv->ctar_val[slave_plat->cs[0]] = DSPI_CTAR_DEFAULT_VALUE | DSPI_CTAR_PCSSCK(pcssck) | DSPI_CTAR_PASC(pasc); debug("DSPI pre_probe slave device on CS %u, max_hz %u, mode 0x%x.\n", - slave_plat->cs, slave_plat->max_hz, slave_plat->mode); + slave_plat->cs[0], slave_plat->max_hz, slave_plat->mode); return 0; } @@ -527,13 +527,13 @@ static int fsl_dspi_claim_bus(struct udevice *dev) priv = dev_get_priv(bus); /* processor special preparation work */ - cpu_dspi_claim_bus(dev_seq(bus), slave_plat->cs); + cpu_dspi_claim_bus(dev_seq(bus), slave_plat->cs[0]); /* configure transfer mode */ - fsl_dspi_cfg_ctar_mode(priv, slave_plat->cs, priv->mode); + fsl_dspi_cfg_ctar_mode(priv, slave_plat->cs[0], priv->mode); /* configure active state of CSX */ - fsl_dspi_cfg_cs_active_state(priv, slave_plat->cs, + fsl_dspi_cfg_cs_active_state(priv, slave_plat->cs[0], priv->mode); fsl_dspi_clr_fifo(priv); @@ -559,7 +559,7 @@ static int fsl_dspi_release_bus(struct udevice *dev) dspi_halt(priv, 1); /* processor special release work */ - cpu_dspi_release_bus(dev_seq(bus), slave_plat->cs); + cpu_dspi_release_bus(dev_seq(bus), slave_plat->cs[0]); return 0; } @@ -615,7 +615,7 @@ static int fsl_dspi_xfer(struct udevice *dev, unsigned int bitlen, bus = dev->parent; priv = dev_get_priv(bus); - return dspi_xfer(priv, slave_plat->cs, bitlen, dout, din, flags); + return dspi_xfer(priv, slave_plat->cs[0], bitlen, dout, din, flags); } static int fsl_dspi_set_speed(struct udevice *bus, uint speed) diff --git a/drivers/spi/fsl_espi.c b/drivers/spi/fsl_espi.c index 2638ed25200..7ed35aa3e66 100644 --- a/drivers/spi/fsl_espi.c +++ b/drivers/spi/fsl_espi.c @@ -513,8 +513,8 @@ static int fsl_espi_child_pre_probe(struct udevice *dev) struct udevice *bus = dev->parent; struct fsl_spi_slave *fsl = dev_get_priv(bus); - debug("%s cs %u\n", __func__, slave_plat->cs); - fsl->cs = slave_plat->cs; + debug("%s cs %u\n", __func__, slave_plat->cs[0]); + fsl->cs = slave_plat->cs[0]; return 0; } diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 8a0a53cb372..c7f554826c3 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -510,10 +510,10 @@ static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_slave *slave) struct dm_spi_slave_plat *plat = dev_get_parent_plat(slave->dev); - if (q->selected == plat->cs) + if (q->selected == plat->cs[0]) return; - q->selected = plat->cs; + q->selected = plat->cs[0]; fsl_qspi_invalidate(q); } diff --git a/drivers/spi/gxp_spi.c b/drivers/spi/gxp_spi.c index 70d76ac66ad..3ee369c5a03 100644 --- a/drivers/spi/gxp_spi.c +++ b/drivers/spi/gxp_spi.c @@ -87,7 +87,7 @@ static int gxp_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *do value = readl(priv->base + OFFSET_SPIMCFG); value &= ~(1 << 24); /* set chipselect */ - value |= (slave_plat->cs << 24); + value |= (slave_plat->cs[0] << 24); /* addr reg and addr size */ if (len >= 4) { diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c index 7e72fb9e23d..51cc487271d 100644 --- a/drivers/spi/mpc8xx_spi.c +++ b/drivers/spi/mpc8xx_spi.c @@ -148,7 +148,7 @@ static void mpc8xx_spi_cs_activate(struct udevice *dev) struct mpc8xx_priv *priv = dev_get_priv(dev->parent); struct dm_spi_slave_plat *platdata = dev_get_parent_plat(dev); - dm_gpio_set_value(&priv->gpios[platdata->cs], 1); + dm_gpio_set_value(&priv->gpios[platdata->cs[0]], 1); } static void mpc8xx_spi_cs_deactivate(struct udevice *dev) @@ -156,7 +156,7 @@ static void mpc8xx_spi_cs_deactivate(struct udevice *dev) struct mpc8xx_priv *priv = dev_get_priv(dev->parent); struct dm_spi_slave_plat *platdata = dev_get_parent_plat(dev); - dm_gpio_set_value(&priv->gpios[platdata->cs], 0); + dm_gpio_set_value(&priv->gpios[platdata->cs[0]], 0); } static int mpc8xx_spi_xfer_one(struct udevice *dev, size_t count, diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c index cd624f4d6f0..b34e1c2129c 100644 --- a/drivers/spi/mpc8xxx_spi.c +++ b/drivers/spi/mpc8xxx_spi.c @@ -113,7 +113,7 @@ static void mpc8xxx_spi_cs_activate(struct udevice *dev) struct mpc8xxx_priv *priv = dev_get_priv(dev->parent); struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev); - dm_gpio_set_value(&priv->gpios[plat->cs], 1); + dm_gpio_set_value(&priv->gpios[plat->cs[0]], 1); } static void mpc8xxx_spi_cs_deactivate(struct udevice *dev) @@ -121,7 +121,7 @@ static void mpc8xxx_spi_cs_deactivate(struct udevice *dev) struct mpc8xxx_priv *priv = dev_get_priv(dev->parent); struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev); - dm_gpio_set_value(&priv->gpios[plat->cs], 0); + dm_gpio_set_value(&priv->gpios[plat->cs[0]], 0); } static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen, @@ -137,10 +137,10 @@ static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen, ulong type = dev_get_driver_data(bus); debug("%s: slave %s:%u dout %08X din %08X bitlen %u\n", __func__, - bus->name, plat->cs, (uint)dout, (uint)din, bitlen); - if (plat->cs >= priv->cs_count) { + bus->name, plat->cs[0], (uint)dout, (uint)din, bitlen); + if (plat->cs[0] >= priv->cs_count) { dev_err(dev, "chip select index %d too large (cs_count=%d)\n", - plat->cs, priv->cs_count); + plat->cs[0], priv->cs_count); return -EINVAL; } if (bitlen % 8) { diff --git a/drivers/spi/mscc_bb_spi.c b/drivers/spi/mscc_bb_spi.c index ad4daeba3cd..75ab4ab1dda 100644 --- a/drivers/spi/mscc_bb_spi.c +++ b/drivers/spi/mscc_bb_spi.c @@ -123,11 +123,11 @@ int mscc_bb_spi_xfer(struct udevice *dev, unsigned int bitlen, u8 *rxd = din; debug("spi_xfer: slave %s:%s cs%d mode %d, dout %p din %p bitlen %u\n", - dev->parent->name, dev->name, plat->cs, plat->mode, dout, + dev->parent->name, dev->name, plat->cs[0], plat->mode, dout, din, bitlen); if (flags & SPI_XFER_BEGIN) - mscc_bb_spi_cs_activate(priv, plat->mode, plat->cs); + mscc_bb_spi_cs_activate(priv, plat->mode, plat->cs[0]); count = bitlen / 8; for (i = 0; i < count; i++) { diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index e7c393ae188..9ab39a188b2 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -135,7 +135,7 @@ static void mxc_spi_cs_activate(struct mxc_spi_slave *mxcs) struct udevice *dev = mxcs->dev; struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - u32 cs = slave_plat->cs; + u32 cs = slave_plat->cs[0]; if (!dm_gpio_is_valid(&mxcs->cs_gpios[cs])) return; @@ -153,7 +153,7 @@ static void mxc_spi_cs_deactivate(struct mxc_spi_slave *mxcs) struct udevice *dev = mxcs->dev; struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - u32 cs = slave_plat->cs; + u32 cs = slave_plat->cs[0]; if (!dm_gpio_is_valid(&mxcs->cs_gpios[cs])) return; @@ -632,7 +632,7 @@ static int mxc_spi_claim_bus(struct udevice *dev) mxcs->dev = dev; - return mxc_spi_claim_bus_internal(mxcs, slave_plat->cs); + return mxc_spi_claim_bus_internal(mxcs, slave_plat->cs[0]); } static int mxc_spi_release_bus(struct udevice *dev) diff --git a/drivers/spi/npcm_fiu_spi.c b/drivers/spi/npcm_fiu_spi.c index 73c506442ae..7b8271c8bbc 100644 --- a/drivers/spi/npcm_fiu_spi.c +++ b/drivers/spi/npcm_fiu_spi.c @@ -203,7 +203,7 @@ static int npcm_fiu_spi_xfer(struct udevice *dev, unsigned int bitlen, int len; if (flags & SPI_XFER_BEGIN) - activate_cs(regs, slave_plat->cs); + activate_cs(regs, slave_plat->cs[0]); while (bytes) { len = (bytes > CHUNK_SIZE) ? CHUNK_SIZE : bytes; @@ -222,7 +222,7 @@ static int npcm_fiu_spi_xfer(struct udevice *dev, unsigned int bitlen, } if (flags & SPI_XFER_END) - deactivate_cs(regs, slave_plat->cs); + deactivate_cs(regs, slave_plat->cs[0]); return ret; } @@ -325,9 +325,9 @@ static int npcm_fiu_exec_op(struct spi_slave *slave, bytes = op->data.nbytes; addr = (u32)op->addr.val; if (!bytes) { - activate_cs(regs, slave_plat->cs); + activate_cs(regs, slave_plat->cs[0]); ret = npcm_fiu_uma_operation(priv, op, addr, NULL, NULL, 0, false); - deactivate_cs(regs, slave_plat->cs); + deactivate_cs(regs, slave_plat->cs[0]); return ret; } @@ -339,9 +339,9 @@ static int npcm_fiu_exec_op(struct spi_slave *slave, * Use HW-control CS for read to avoid clock and timing issues. */ if (op->data.dir == SPI_MEM_DATA_OUT) - activate_cs(regs, slave_plat->cs); + activate_cs(regs, slave_plat->cs[0]); else - writel(FIELD_PREP(UMA_CTS_DEV_NUM_MASK, slave_plat->cs) | UMA_CTS_SW_CS, + writel(FIELD_PREP(UMA_CTS_DEV_NUM_MASK, slave_plat->cs[0]) | UMA_CTS_SW_CS, ®s->uma_cts); while (bytes) { len = (bytes > CHUNK_SIZE) ? CHUNK_SIZE : bytes; @@ -361,7 +361,7 @@ static int npcm_fiu_exec_op(struct spi_slave *slave, rx += len; } if (op->data.dir == SPI_MEM_DATA_OUT) - deactivate_cs(regs, slave_plat->cs); + deactivate_cs(regs, slave_plat->cs[0]); return 0; } diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c index fefdaaa9e90..7489c896f9d 100644 --- a/drivers/spi/nxp_fspi.c +++ b/drivers/spi/nxp_fspi.c @@ -962,7 +962,7 @@ static int nxp_fspi_claim_bus(struct udevice *dev) bus = dev->parent; f = dev_get_priv(bus); - nxp_fspi_select_mem(f, slave_plat->cs); + nxp_fspi_select_mem(f, slave_plat->cs[0]); return 0; } diff --git a/drivers/spi/octeon_spi.c b/drivers/spi/octeon_spi.c index 4bc38beaa68..0e6e0f7dbe7 100644 --- a/drivers/spi/octeon_spi.c +++ b/drivers/spi/octeon_spi.c @@ -93,7 +93,7 @@ static u64 octeon_spi_set_mpicfg(struct udevice *dev) if (max_speed > OCTEON_SPI_MAX_CLOCK_HZ) max_speed = OCTEON_SPI_MAX_CLOCK_HZ; - debug("\n slave params %d %d %d\n", slave->cs, + debug("\n slave params %d %d %d\n", slave->cs[0], slave->max_hz, slave->mode); cpha = !!(slave->mode & SPI_CPHA); cpol = !!(slave->mode & SPI_CPOL); diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index 3d82fc74ff5..35bd8766097 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -393,7 +393,7 @@ static int omap3_spi_claim_bus(struct udevice *dev) struct omap3_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - priv->cs = slave_plat->cs; + priv->cs = slave_plat->cs[0]; if (!priv->freq) priv->freq = slave_plat->max_hz; @@ -422,7 +422,7 @@ static int omap3_spi_set_wordlen(struct udevice *dev, unsigned int wordlen) struct omap3_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - priv->cs = slave_plat->cs; + priv->cs = slave_plat->cs[0]; priv->wordlen = wordlen; _omap3_spi_set_wordlen(priv); diff --git a/drivers/spi/pic32_spi.c b/drivers/spi/pic32_spi.c index e11ae7fc7a4..c4b31dc2a61 100644 --- a/drivers/spi/pic32_spi.c +++ b/drivers/spi/pic32_spi.c @@ -247,7 +247,7 @@ static int pic32_spi_xfer(struct udevice *slave, unsigned int bitlen, slave_plat = dev_get_parent_plat(slave); debug("spi_xfer: bus:%i cs:%i flags:%lx\n", - dev_seq(bus), slave_plat->cs, flags); + dev_seq(bus), slave_plat->cs[0], flags); debug("msg tx %p, rx %p submitted of %d byte(s)\n", tx_buf, rx_buf, len); diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c index 4571dc9f9b6..2c3d70ba715 100644 --- a/drivers/spi/rk_spi.c +++ b/drivers/spi/rk_spi.c @@ -444,7 +444,7 @@ static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen, /* Assert CS before transfer */ if (flags & SPI_XFER_BEGIN) - spi_cs_activate(dev, slave_plat->cs); + spi_cs_activate(dev, slave_plat->cs[0]); /* * To ensure fast loading of firmware images (e.g. full U-Boot @@ -507,7 +507,7 @@ static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen, /* Deassert CS after transfer */ if (flags & SPI_XFER_END) - spi_cs_deactivate(dev, slave_plat->cs); + spi_cs_deactivate(dev, slave_plat->cs[0]); rkspi_enable_chip(regs, false); if (!out) diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c index 596c22aa010..71e9b707e8e 100644 --- a/drivers/spi/rockchip_sfc.c +++ b/drivers/spi/rockchip_sfc.c @@ -409,7 +409,7 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, /* set the Controller */ ctrl |= SFC_CTRL_PHASE_SEL_NEGETIVE; - cmd |= plat->cs << SFC_CMD_CS_SHIFT; + cmd |= plat->cs[0] << SFC_CMD_CS_SHIFT; dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", op->addr.nbytes, op->addr.buswidth, diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index 12320367e97..ca29cfd7c88 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -192,7 +192,7 @@ static u32 ast2400_get_clk_setting(struct udevice *dev, uint max_hz) if (found) { hclk_div = hclk_masks[i] << 8; - priv->flashes[slave_plat->cs].max_freq = hclk_clk / (i + 1); + priv->flashes[slave_plat->cs[0]].max_freq = hclk_clk / (i + 1); } dev_dbg(dev, "found: %s, hclk: %d, max_clk: %d\n", found ? "yes" : "no", @@ -200,7 +200,7 @@ static u32 ast2400_get_clk_setting(struct udevice *dev, uint max_hz) if (found) { dev_dbg(dev, "h_div: %d (mask %x), speed: %d\n", - i + 1, hclk_masks[i], priv->flashes[slave_plat->cs].max_freq); + i + 1, hclk_masks[i], priv->flashes[slave_plat->cs[0]].max_freq); } return hclk_div; @@ -311,7 +311,7 @@ static u32 ast2500_get_clk_setting(struct udevice *dev, uint max_hz) for (i = 0; i < ARRAY_SIZE(hclk_masks); i++) { if (hclk_clk / (i + 1) <= max_hz) { found = true; - priv->flashes[slave_plat->cs].max_freq = + priv->flashes[slave_plat->cs[0]].max_freq = hclk_clk / (i + 1); break; } @@ -325,7 +325,7 @@ static u32 ast2500_get_clk_setting(struct udevice *dev, uint max_hz) for (i = 0; i < ARRAY_SIZE(hclk_masks); i++) { if (hclk_clk / ((i + 1) * 4) <= max_hz) { found = true; - priv->flashes[slave_plat->cs].max_freq = + priv->flashes[slave_plat->cs[0]].max_freq = hclk_clk / ((i + 1) * 4); break; } @@ -340,7 +340,7 @@ end: if (found) { dev_dbg(dev, "h_div: %d (mask %x), speed: %d\n", - i + 1, hclk_masks[i], priv->flashes[slave_plat->cs].max_freq); + i + 1, hclk_masks[i], priv->flashes[slave_plat->cs[0]].max_freq); } return hclk_div; @@ -456,7 +456,7 @@ static u32 ast2600_get_clk_setting(struct udevice *dev, uint max_hz) if (found) { hclk_div = ((j << 24) | hclk_masks[i] << 8); - priv->flashes[slave_plat->cs].max_freq = + priv->flashes[slave_plat->cs[0]].max_freq = hclk_clk / (i + 1 + j * 16); break; } @@ -467,7 +467,7 @@ static u32 ast2600_get_clk_setting(struct udevice *dev, uint max_hz) if (found) { dev_dbg(dev, "base_clk: %d, h_div: %d (mask %x), speed: %d\n", - j, i + 1, hclk_masks[i], priv->flashes[slave_plat->cs].max_freq); + j, i + 1, hclk_masks[i], priv->flashes[slave_plat->cs[0]].max_freq); } return hclk_div; @@ -588,7 +588,7 @@ static int aspeed_spi_exec_op_user_mode(struct spi_slave *slave, struct udevice *bus = dev->parent; struct aspeed_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(slave->dev); - u32 cs = slave_plat->cs; + u32 cs = slave_plat->cs[0]; u32 ce_ctrl_reg = (u32)&priv->regs->ce_ctrl[cs]; u32 ce_ctrl_val; struct aspeed_spi_flash *flash = &priv->flashes[cs]; @@ -668,7 +668,7 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) const struct aspeed_spi_info *info = priv->info; struct spi_mem_op op_tmpl = desc->info.op_tmpl; u32 i; - u32 cs = slave_plat->cs; + u32 cs = slave_plat->cs[0]; u32 cmd_io_conf; u32 ce_ctrl_reg; @@ -725,7 +725,7 @@ static ssize_t aspeed_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, struct udevice *dev = desc->slave->dev; struct aspeed_spi_priv *priv = dev_get_priv(dev->parent); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - u32 cs = slave_plat->cs; + u32 cs = slave_plat->cs[0]; int ret; dev_dbg(dev, "read op:0x%x, addr:0x%llx, len:0x%x\n", @@ -750,7 +750,7 @@ static struct aspeed_spi_flash *aspeed_spi_get_flash(struct udevice *dev) struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); struct aspeed_spi_plat *plat = dev_get_plat(bus); struct aspeed_spi_priv *priv = dev_get_priv(bus); - u32 cs = slave_plat->cs; + u32 cs = slave_plat->cs[0]; if (cs >= plat->max_cs) { dev_err(dev, "invalid CS %u\n", cs); @@ -1068,10 +1068,10 @@ static int aspeed_spi_claim_bus(struct udevice *dev) struct udevice *bus = dev->parent; struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); struct aspeed_spi_priv *priv = dev_get_priv(dev->parent); - struct aspeed_spi_flash *flash = &priv->flashes[slave_plat->cs]; + struct aspeed_spi_flash *flash = &priv->flashes[slave_plat->cs[0]]; u32 clk_setting; - dev_dbg(bus, "%s: claim bus CS%u\n", bus->name, slave_plat->cs); + dev_dbg(bus, "%s: claim bus CS%u\n", bus->name, slave_plat->cs[0]); if (flash->max_freq == 0) { clk_setting = priv->info->get_clk_setting(dev, slave_plat->max_hz); @@ -1089,7 +1089,7 @@ static int aspeed_spi_release_bus(struct udevice *dev) struct udevice *bus = dev->parent; struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - dev_dbg(bus, "%s: release bus CS%u\n", bus->name, slave_plat->cs); + dev_dbg(bus, "%s: release bus CS%u\n", bus->name, slave_plat->cs[0]); if (!aspeed_spi_get_flash(dev)) return -ENODEV; diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c index b98bcd9b6ba..3835865ea7d 100644 --- a/drivers/spi/spi-mxic.c +++ b/drivers/spi/spi-mxic.c @@ -366,8 +366,8 @@ static int mxic_spi_mem_exec_op(struct spi_slave *slave, nio = 2; writel(HC_CFG_NIO(nio) | - HC_CFG_TYPE(slave_plat->cs, HC_CFG_TYPE_SPI_NOR) | - HC_CFG_SLV_ACT(slave_plat->cs) | HC_CFG_IDLE_SIO_LVL(1) | + HC_CFG_TYPE(slave_plat->cs[0], HC_CFG_TYPE_SPI_NOR) | + HC_CFG_SLV_ACT(slave_plat->cs[0]) | HC_CFG_IDLE_SIO_LVL(1) | HC_CFG_MAN_CS_EN, priv->regs + HC_CFG); writel(HC_EN_BIT, priv->regs + HC_EN); @@ -396,7 +396,7 @@ static int mxic_spi_mem_exec_op(struct spi_slave *slave, ss_ctrl |= OP_READ; } - writel(ss_ctrl, priv->regs + SS_CTRL(slave_plat->cs)); + writel(ss_ctrl, priv->regs + SS_CTRL(slave_plat->cs[0])); writel(readl(priv->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT, priv->regs + HC_CFG); diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 836c550b0bb..dc001e6e4cc 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -718,7 +718,7 @@ static int qup_spi_xfer(struct udevice *dev, unsigned int bitlen, if (ret != 0) return ret; - ret = qup_spi_set_cs(bus, slave_plat->cs, false); + ret = qup_spi_set_cs(bus, slave_plat->cs[0], false); if (ret != 0) return ret; } @@ -736,7 +736,7 @@ static int qup_spi_xfer(struct udevice *dev, unsigned int bitlen, } if (flags & SPI_XFER_END) { - ret = qup_spi_set_cs(bus, slave_plat->cs, true); + ret = qup_spi_set_cs(bus, slave_plat->cs[0], true); if (ret != 0) return ret; } diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 0c8666c05f9..15407d482c9 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -108,13 +108,13 @@ static void sifive_spi_prep_device(struct sifive_spi *spi, { /* Update the chip select polarity */ if (slave_plat->mode & SPI_CS_HIGH) - spi->cs_inactive &= ~BIT(slave_plat->cs); + spi->cs_inactive &= ~BIT(slave_plat->cs[0]); else - spi->cs_inactive |= BIT(slave_plat->cs); + spi->cs_inactive |= BIT(slave_plat->cs[0]); writel(spi->cs_inactive, spi->regs + SIFIVE_SPI_REG_CSDEF); /* Select the correct device */ - writel(slave_plat->cs, spi->regs + SIFIVE_SPI_REG_CSID); + writel(slave_plat->cs[0], spi->regs + SIFIVE_SPI_REG_CSID); } static int sifive_spi_set_cs(struct sifive_spi *spi, diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c index fc82791006e..364ba4b3a97 100644 --- a/drivers/spi/spi-sn-f-ospi.c +++ b/drivers/spi/spi-sn-f-ospi.c @@ -497,7 +497,7 @@ static int f_ospi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) int err = 0; slave_plat = dev_get_parent_plat(slave->dev); - ospi->chip_select = slave_plat->cs; + ospi->chip_select = slave_plat->cs[0]; switch (op->data.dir) { case SPI_MEM_DATA_IN: diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index 88550b8ea84..e00532a371b 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -360,7 +360,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, } if (flags & SPI_XFER_BEGIN) - sun4i_spi_set_cs(bus, slave_plat->cs, true); + sun4i_spi_set_cs(bus, slave_plat->cs[0], true); /* Reset FIFOs */ setbits_le32(SPI_REG(priv, SPI_FCR), SPI_BIT(priv, SPI_FCR_RF_RST) | @@ -391,7 +391,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, false, SUN4I_SPI_TIMEOUT_MS, false); if (ret < 0) { printf("ERROR: sun4i_spi: Timeout transferring data\n"); - sun4i_spi_set_cs(bus, slave_plat->cs, false); + sun4i_spi_set_cs(bus, slave_plat->cs[0], false); return ret; } @@ -402,7 +402,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, } if (flags & SPI_XFER_END) - sun4i_spi_set_cs(bus, slave_plat->cs, false); + sun4i_spi_set_cs(bus, slave_plat->cs[0], false); return 0; } diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c index eb522fd7b3d..a3c0ad17121 100644 --- a/drivers/spi/spi-synquacer.c +++ b/drivers/spi/spi-synquacer.c @@ -193,12 +193,12 @@ static void synquacer_spi_config(struct udevice *dev, void *rx, const void *tx) /* if nothing to do */ if (slave_plat->mode == priv->mode && rwflag == priv->rwflag && - slave_plat->cs == priv->cs && + slave_plat->cs[0] == priv->cs && slave_plat->max_hz == priv->speed) return; priv->rwflag = rwflag; - priv->cs = slave_plat->cs; + priv->cs = slave_plat->cs[0]; priv->mode = slave_plat->mode; priv->speed = slave_plat->max_hz; diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index 6e281725239..b454c4163cd 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -224,7 +224,7 @@ int spi_chip_select(struct udevice *dev) { struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev); - return plat ? plat->cs : -ENOENT; + return plat ? plat->cs[0] : -ENOENT; } int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp) @@ -261,8 +261,8 @@ int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp) struct dm_spi_slave_plat *plat; plat = dev_get_parent_plat(dev); - dev_dbg(bus, "%s: plat=%p, cs=%d\n", __func__, plat, plat->cs); - if (plat->cs == cs) { + dev_dbg(bus, "%s: plat=%p, cs=%d\n", __func__, plat, plat->cs[0]); + if (plat->cs[0] == cs) { *devp = dev; return 0; } @@ -415,7 +415,7 @@ int _spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, return ret; } plat = dev_get_parent_plat(dev); - plat->cs = cs; + plat->cs[0] = cs; if (speed) { plat->max_hz = speed; } else { @@ -446,6 +446,12 @@ int _spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, slave = dev_get_parent_priv(dev); bus_data = dev_get_uclass_priv(bus); +#if CONFIG_IS_ENABLED(SPI_ADVANCE) + if ((dev_read_bool(dev, "parallel-memories")) && !slave->multi_cs_cap) { + dev_err(dev, "controller doesn't support multi CS\n"); + return -EINVAL; + } +#endif /* * In case the operation speed is not yet established by * dm_spi_claim_bus() ensure the bus is configured properly. @@ -509,7 +515,21 @@ int spi_slave_of_to_plat(struct udevice *dev, struct dm_spi_slave_plat *plat) int mode = 0; int value; - plat->cs = dev_read_u32_default(dev, "reg", -1); +#if CONFIG_IS_ENABLED(SPI_ADVANCE) + int ret; + + ret = dev_read_u32_array(dev, "reg", plat->cs, SPI_CS_CNT_MAX); + + if (ret == -EOVERFLOW || ret == -FDT_ERR_BADLAYOUT) { + dev_read_u32(dev, "reg", &plat->cs[0]); + } else { + dev_err(dev, "has no valid 'reg' property (%d)\n", ret); + return ret; + } +#else + plat->cs[0] = dev_read_u32_default(dev, "reg", -1); +#endif + plat->max_hz = dev_read_u32_default(dev, "spi-max-frequency", SPI_DEFAULT_SPEED_HZ); if (dev_read_bool(dev, "spi-cpol")) diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c index 2812a4da411..3216ec8010e 100644 --- a/drivers/spi/stm32_qspi.c +++ b/drivers/spi/stm32_qspi.c @@ -394,7 +394,7 @@ static int stm32_qspi_claim_bus(struct udevice *dev) { struct stm32_qspi_priv *priv = dev_get_priv(dev->parent); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - int slave_cs = slave_plat->cs; + int slave_cs = slave_plat->cs[0]; if (slave_cs >= STM32_QSPI_MAX_CHIP) return -ENODEV; diff --git a/drivers/spi/stm32_spi.c b/drivers/spi/stm32_spi.c index 97b83b17167..a1f31cf653c 100644 --- a/drivers/spi/stm32_spi.c +++ b/drivers/spi/stm32_spi.c @@ -434,7 +434,7 @@ static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen, slave_plat = dev_get_parent_plat(slave); if (flags & SPI_XFER_BEGIN) - stm32_spi_set_cs(bus, slave_plat->cs, false); + stm32_spi_set_cs(bus, slave_plat->cs[0], false); /* Be sure to have data in fifo before starting data transfer */ if (priv->tx_buf) @@ -485,7 +485,7 @@ static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen, stm32_spi_stopxfer(bus); if (flags & SPI_XFER_END) - stm32_spi_set_cs(bus, slave_plat->cs, true); + stm32_spi_set_cs(bus, slave_plat->cs[0], true); return xfer_status; } diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c index a16412ec6fb..1f2494e592c 100644 --- a/drivers/spi/ti_qspi.c +++ b/drivers/spi/ti_qspi.c @@ -163,7 +163,7 @@ static int ti_qspi_xfer(struct udevice *dev, unsigned int bitlen, uchar *rxp = din; uint status; int timeout; - unsigned int cs = slave->cs; + unsigned int cs = slave->cs[0]; bus = dev->parent; priv = dev_get_priv(bus); @@ -344,7 +344,7 @@ static int ti_qspi_exec_mem_op(struct spi_slave *slave, if (from + op->data.nbytes > priv->mmap_size) return -ENOTSUPP; - ti_qspi_setup_mmap_read(priv, slave_plat->cs, op->cmd.opcode, + ti_qspi_setup_mmap_read(priv, slave_plat->cs[0], op->cmd.opcode, op->data.buswidth, op->addr.nbytes, op->dummy.nbytes); @@ -363,7 +363,7 @@ static int ti_qspi_claim_bus(struct udevice *dev) bus = dev->parent; priv = dev_get_priv(bus); - if (slave_plat->cs > priv->num_cs) { + if (slave_plat->cs[0] > priv->num_cs) { debug("invalid qspi chip select\n"); return -EINVAL; } @@ -371,13 +371,13 @@ static int ti_qspi_claim_bus(struct udevice *dev) writel(MM_SWITCH, &priv->base->memswitch); if (priv->ctrl_mod_mmap) ti_qspi_ctrl_mode_mmap(priv->ctrl_mod_mmap, - slave_plat->cs, true); + slave_plat->cs[0], true); writel(priv->dc, &priv->base->dc); writel(0, &priv->base->cmd); writel(0, &priv->base->data); - priv->dc <<= slave_plat->cs * 8; + priv->dc <<= slave_plat->cs[0] * 8; writel(priv->dc, &priv->base->dc); return 0; @@ -395,12 +395,12 @@ static int ti_qspi_release_bus(struct udevice *dev) writel(~MM_SWITCH, &priv->base->memswitch); if (priv->ctrl_mod_mmap) ti_qspi_ctrl_mode_mmap(priv->ctrl_mod_mmap, - slave_plat->cs, false); + slave_plat->cs[0], false); writel(0, &priv->base->dc); writel(0, &priv->base->cmd); writel(0, &priv->base->data); - writel(0, TI_QSPI_SETUP_REG(priv, slave_plat->cs)); + writel(0, TI_QSPI_SETUP_REG(priv, slave_plat->cs[0])); return 0; } diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 0e7fa3a4525..b2af17ebae9 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -291,7 +291,7 @@ static void xilinx_spi_startup_block(struct udevice *dev) * Perform a dummy read as a work around for * the startup block issue. */ - spi_cs_activate(dev, slave_plat->cs); + spi_cs_activate(dev, slave_plat->cs[0]); txp = 0x9f; start_transfer(dev, (void *)&txp, NULL, 1); @@ -306,7 +306,7 @@ static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen, struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); int ret; - spi_cs_activate(dev, slave_plat->cs); + spi_cs_activate(dev, slave_plat->cs[0]); ret = start_transfer(dev, dout, din, bitlen / 8); spi_cs_deactivate(dev); return ret; @@ -331,7 +331,7 @@ static int xilinx_spi_mem_exec_op(struct spi_slave *spi, startup++; } - spi_cs_activate(spi->dev, slave_plat->cs); + spi_cs_activate(spi->dev, slave_plat->cs[0]); if (op->cmd.opcode) { ret = start_transfer(spi->dev, (void *)&op->cmd.opcode, diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c index b71b9a6fd6c..e8bc196ce9e 100644 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@ -585,13 +585,13 @@ static int zynq_qspi_xfer(struct udevice *dev, unsigned int bitlen, struct zynq_qspi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - priv->cs = slave_plat->cs; + priv->cs = slave_plat->cs[0]; priv->tx_buf = dout; priv->rx_buf = din; priv->len = bitlen / 8; - debug("zynq_qspi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n", - dev_seq(bus), slave_plat->cs, bitlen, priv->len, flags); + debug("zynq_qspi_xfer: bus:%i cs[0]:%i bitlen:%i len:%i flags:%lx\n", + dev_seq(bus), slave_plat->cs[0], bitlen, priv->len, flags); /* * Festering sore. diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index d15d91a1d24..37fa12b96b5 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -240,15 +240,15 @@ static int zynq_spi_xfer(struct udevice *dev, unsigned int bitlen, u8 *rx_buf = din, buf; u32 ts, status; - debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n", - dev_seq(bus), slave_plat->cs, bitlen, len, flags); + debug("spi_xfer: bus:%i cs[0]:%i bitlen:%i len:%i flags:%lx\n", + dev_seq(bus), slave_plat->cs[0], bitlen, len, flags); if (bitlen % 8) { debug("spi_xfer: Non byte aligned SPI transfer\n"); return -1; } - priv->cs = slave_plat->cs; + priv->cs = slave_plat->cs[0]; if (flags & SPI_XFER_BEGIN) spi_cs_activate(dev); diff --git a/include/spi.h b/include/spi.h index 6e8e0cce7f2..b7148864e78 100644 --- a/include/spi.h +++ b/include/spi.h @@ -80,7 +80,7 @@ struct dm_spi_bus { * @mode: SPI mode to use for this device (see SPI mode flags) */ struct dm_spi_slave_plat { - unsigned int cs; + unsigned int cs[SPI_CS_CNT_MAX]; uint max_hz; uint mode; }; @@ -166,6 +166,12 @@ struct spi_slave { #define SPI_XFER_ONCE (SPI_XFER_BEGIN | SPI_XFER_END) #define SPI_XFER_U_PAGE BIT(4) #define SPI_XFER_STACKED BIT(5) + /* + * Flag indicating that the spi-controller has multi chip select + * capability and can assert/de-assert more than one chip select + * at once. + */ + bool multi_cs_cap; }; /** diff --git a/lib/acpi/acpi_device.c b/lib/acpi/acpi_device.c index ed94194346d..0f3044bca79 100644 --- a/lib/acpi/acpi_device.c +++ b/lib/acpi/acpi_device.c @@ -728,7 +728,7 @@ static int acpi_device_set_spi(const struct udevice *dev, struct acpi_spi *spi, plat = dev_get_parent_plat(slave->dev); memset(spi, '\0', sizeof(*spi)); - spi->device_select = plat->cs; + spi->device_select = plat->cs[0]; spi->device_select_polarity = SPI_POLARITY_LOW; spi->wire_mode = SPI_4_WIRE_MODE; spi->speed = plat->max_hz; -- cgit v1.3.1 From 217b0a28b6db3d664300f82df8e4cf342de3b8a0 Mon Sep 17 00:00:00 2001 From: Venkatesh Yadav Abbarapu Date: Thu, 26 Sep 2024 10:25:06 +0530 Subject: spi: zynqmp_gqspi: Add parallel memories support in GQSPI driver Add support for parallel memories in zynqmp_gqspi.c driver. In case of parallel memories STRIPE bit is set and sent to the qspi ip, which will send data bits to both the flashes in parallel. However for few commands we should not use stripe, instead send same data to both the flashes. Those commands are exclueded by using zynqmp_qspi_update_stripe(). Also update copyright info for this file. Signed-off-by: Ashok Reddy Soma Signed-off-by: Venkatesh Yadav Abbarapu --- drivers/spi/zynqmp_gqspi.c | 141 ++++++++++++++++++++++++++++++++++++++++----- include/spi.h | 4 ++ 2 files changed, 129 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c index ae795e50b0a..1d19b2606c5 100644 --- a/drivers/spi/zynqmp_gqspi.c +++ b/drivers/spi/zynqmp_gqspi.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * (C) Copyright 2018 Xilinx - * + * (C) Copyright 2013 - 2022, Xilinx, Inc. + * (C) Copyright 2023, Advanced Micro Devices, Inc. * Xilinx ZynqMP Generic Quad-SPI(QSPI) controller driver(master mode only) */ @@ -24,6 +24,8 @@ #include #include #include +#include +#include "../mtd/spi/sf_internal.h" #include #define GQSPI_GFIFO_STRT_MODE_MASK BIT(29) @@ -87,6 +89,9 @@ #define SPI_XFER_ON_LOWER 1 #define SPI_XFER_ON_UPPER 2 +#define GQSPI_SELECT_LOWER_CS BIT(0) +#define GQSPI_SELECT_UPPER_CS BIT(1) + #define GQSPI_DMA_ALIGN 0x4 #define GQSPI_MAX_BAUD_RATE_VAL 7 #define GQSPI_DFLT_BAUD_RATE_VAL 2 @@ -183,13 +188,14 @@ struct zynqmp_qspi_priv { int bytes_to_transfer; int bytes_to_receive; const struct spi_mem_op *op; + unsigned int is_parallel; + unsigned int u_page; + unsigned int bus; + unsigned int stripe; + unsigned int flags; + u32 max_hz; }; -__weak int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value) -{ - return 0; -} - static int zynqmp_qspi_of_to_plat(struct udevice *bus) { struct zynqmp_qspi_plat *plat = dev_get_plat(bus); @@ -234,8 +240,30 @@ static u32 zynqmp_qspi_bus_select(struct zynqmp_qspi_priv *priv) { u32 gqspi_fifo_reg = 0; - gqspi_fifo_reg = GQSPI_GFIFO_LOW_BUS | - GQSPI_GFIFO_CS_LOWER; + if (priv->is_parallel) { + if (priv->bus == SPI_XFER_ON_BOTH) + gqspi_fifo_reg = GQSPI_GFIFO_LOW_BUS | + GQSPI_GFIFO_UP_BUS | + GQSPI_GFIFO_CS_UPPER | + GQSPI_GFIFO_CS_LOWER; + else if (priv->bus == SPI_XFER_ON_LOWER) + gqspi_fifo_reg = GQSPI_GFIFO_LOW_BUS | + GQSPI_GFIFO_CS_UPPER | + GQSPI_GFIFO_CS_LOWER; + else if (priv->bus == SPI_XFER_ON_UPPER) + gqspi_fifo_reg = GQSPI_GFIFO_UP_BUS | + GQSPI_GFIFO_CS_LOWER | + GQSPI_GFIFO_CS_UPPER; + else + debug("Wrong Bus selection:0x%x\n", priv->bus); + } else { + if (priv->u_page) + gqspi_fifo_reg = GQSPI_GFIFO_LOW_BUS | + GQSPI_GFIFO_CS_UPPER; + else + gqspi_fifo_reg = GQSPI_GFIFO_LOW_BUS | + GQSPI_GFIFO_CS_LOWER; + } return gqspi_fifo_reg; } @@ -295,8 +323,15 @@ static void zynqmp_qspi_chipselect(struct zynqmp_qspi_priv *priv, int is_on) gqspi_fifo_reg |= GQSPI_SPI_MODE_SPI | GQSPI_IMD_DATA_CS_ASSERT; } else { - gqspi_fifo_reg = GQSPI_GFIFO_LOW_BUS; - gqspi_fifo_reg |= GQSPI_IMD_DATA_CS_DEASSERT; + if (priv->is_parallel) { + 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; + } } zynqmp_qspi_fill_gen_fifo(priv, gqspi_fifo_reg); @@ -367,12 +402,13 @@ static int zynqmp_qspi_set_speed(struct udevice *bus, uint speed) log_debug("%s, Speed: %d, Max: %d\n", __func__, speed, plat->frequency); - if (speed > plat->frequency) - speed = plat->frequency; + /* + * If speed == 0 or speed > max freq, then set speed to highest + */ + if (!speed || speed > priv->max_hz) + speed = priv->max_hz; if (plat->speed_hz != speed) { - /* Set the clock frequency */ - /* If speed == 0, default to lowest speed */ while ((baud_rate_val < 8) && ((plat->frequency / (2 << baud_rate_val)) > speed)) @@ -394,6 +430,18 @@ static int zynqmp_qspi_set_speed(struct udevice *bus, uint speed) return 0; } +static int zynqmp_qspi_child_pre_probe(struct udevice *bus) +{ + struct spi_slave *slave = dev_get_parent_priv(bus); + struct zynqmp_qspi_priv *priv = dev_get_priv(bus->parent); + + slave->multi_cs_cap = true; + slave->bytemode = SPI_4BYTE_MODE; + priv->max_hz = slave->max_hz; + + return 0; +} + static int zynqmp_qspi_probe(struct udevice *bus) { struct zynqmp_qspi_plat *plat = dev_get_plat(bus); @@ -458,12 +506,17 @@ static int zynqmp_qspi_set_mode(struct udevice *bus, uint mode) static int zynqmp_qspi_fill_tx_fifo(struct zynqmp_qspi_priv *priv, u32 size) { - u32 data; + u32 data, ier; int ret = 0; struct zynqmp_qspi_regs *regs = priv->regs; u32 *buf = (u32 *)priv->tx_buf; u32 len = size; + /* Enable interrupts */ + ier = readl(®s->ier); + ier |= GQSPI_IXR_ALL_MASK | GQSPI_IXR_TXFIFOEMPTY_MASK; + writel(ier, ®s->ier); + while (size) { ret = wait_for_bit_le32(®s->isr, GQSPI_IXR_TXNFULL_MASK, 1, GQSPI_TIMEOUT, 1); @@ -586,6 +639,9 @@ static int zynqmp_qspi_genfifo_fill_tx(struct zynqmp_qspi_priv *priv) gen_fifo_cmd |= zynqmp_qspi_genfifo_mode(priv->op->data.buswidth); gen_fifo_cmd |= GQSPI_GFIFO_TX | GQSPI_GFIFO_DATA_XFR_MASK; + if (priv->stripe) + gen_fifo_cmd |= GQSPI_GFIFO_STRIPE_MASK; + while (priv->len) { len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd); zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd); @@ -720,6 +776,9 @@ static int zynqmp_qspi_genfifo_fill_rx(struct zynqmp_qspi_priv *priv) gen_fifo_cmd |= zynqmp_qspi_genfifo_mode(priv->op->data.buswidth); gen_fifo_cmd |= GQSPI_GFIFO_RX | GQSPI_GFIFO_DATA_XFR_MASK; + 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. @@ -760,6 +819,33 @@ static int zynqmp_qspi_release_bus(struct udevice *dev) return 0; } +static bool zynqmp_qspi_update_stripe(const struct spi_mem_op *op) +{ + /* + * This is a list of opcodes for which we must not use striped access + * even in dual parallel mode, but instead broadcast the same data to + * both chips. This is primarily erase commands and writing some + * registers. + */ + switch (op->cmd.opcode) { + case SPINOR_OP_BE_4K: + case SPINOR_OP_BE_32K: + case SPINOR_OP_CHIP_ERASE: + case SPINOR_OP_SE: + case SPINOR_OP_BE_32K_4B: + case SPINOR_OP_SE_4B: + case SPINOR_OP_BE_4K_4B: + case SPINOR_OP_WRSR: + case SPINOR_OP_WREAR: + case SPINOR_OP_BRWR: + return false; + case SPINOR_OP_WRSR2: + return op->addr.nbytes != 0; + default: + return true; + } +} + static int zynqmp_qspi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) { @@ -771,6 +857,25 @@ static int zynqmp_qspi_exec_op(struct spi_slave *slave, priv->rx_buf = op->data.buf.in; priv->len = op->data.nbytes; + if (slave->flags & SPI_XFER_U_PAGE) + priv->u_page = 1; + else + priv->u_page = 0; + + if ((slave->flags & GQSPI_SELECT_LOWER_CS) && + (slave->flags & GQSPI_SELECT_UPPER_CS)) + priv->is_parallel = true; + + priv->stripe = 0; + priv->bus = 0; + + if (priv->is_parallel) { + if (slave->flags & SPI_XFER_MASK) + priv->bus = (slave->flags & SPI_XFER_MASK) >> 8; + if (zynqmp_qspi_update_stripe(op)) + priv->stripe = 1; + } + zynqmp_qspi_chipselect(priv, 1); /* Send opcode, addr, dummy */ @@ -784,6 +889,9 @@ static int zynqmp_qspi_exec_op(struct spi_slave *slave, zynqmp_qspi_chipselect(priv, 0); + priv->is_parallel = false; + slave->flags &= ~SPI_XFER_MASK; + return ret; } @@ -814,4 +922,5 @@ U_BOOT_DRIVER(zynqmp_qspi) = { .plat_auto = sizeof(struct zynqmp_qspi_plat), .priv_auto = sizeof(struct zynqmp_qspi_priv), .probe = zynqmp_qspi_probe, + .child_pre_probe = zynqmp_qspi_child_pre_probe, }; diff --git a/include/spi.h b/include/spi.h index b7148864e78..3a92d02f215 100644 --- a/include/spi.h +++ b/include/spi.h @@ -38,6 +38,9 @@ #define SPI_DEFAULT_WORDLEN 8 +#define SPI_3BYTE_MODE 0x0 +#define SPI_4BYTE_MODE 0x1 + /* SPI transfer flags */ #define SPI_XFER_STRIPE (1 << 6) #define SPI_XFER_MASK (3 << 8) @@ -172,6 +175,7 @@ struct spi_slave { * at once. */ bool multi_cs_cap; + u32 bytemode; }; /** -- cgit v1.3.1