From d2f763162aa86e97ae65390b8a85e34ebb0d71bb Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Wed, 11 Mar 2015 14:52:42 +0530 Subject: sf: Correct the macros as per new array fast read command Correct the macros as per insertion of array fast read command CMD_READ_ARRAY_FAST in spi_read_cmds_array in file sf_probe.c Signed-off-by: Siva Durga Prasad Paladugu Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/include/spi.h b/include/spi.h index c58e453..7829063 100644 --- a/include/spi.h +++ b/include/spi.h @@ -38,11 +38,12 @@ /* SPI RX operation modes */ #define SPI_OPM_RX_AS (1 << 0) -#define SPI_OPM_RX_DOUT (1 << 1) -#define SPI_OPM_RX_DIO (1 << 2) -#define SPI_OPM_RX_QOF (1 << 3) -#define SPI_OPM_RX_QIOF (1 << 4) -#define SPI_OPM_RX_EXTN (SPI_OPM_RX_AS | SPI_OPM_RX_DOUT | \ +#define SPI_OPM_RX_AF (1 << 1) +#define SPI_OPM_RX_DOUT (1 << 2) +#define SPI_OPM_RX_DIO (1 << 3) +#define SPI_OPM_RX_QOF (1 << 4) +#define SPI_OPM_RX_QIOF (1 << 5) +#define SPI_OPM_RX_EXTN (SPI_OPM_RX_AS | SPI_OPM_RX_AF | SPI_OPM_RX_DOUT | \ SPI_OPM_RX_DIO | SPI_OPM_RX_QOF | \ SPI_OPM_RX_QIOF) -- cgit v0.10.2 From 06bc1756c5b75ff8719ee969b3b99b4d32d9603e Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Wed, 11 Mar 2015 14:47:57 +0530 Subject: sf: Poll both the read status and flag status Poll both the Read status and Flag status registers for sucessful erase and program operations for the Micron devices with E_FSR flag set in params table. Signed-off-by: Siva Durga Prasad Paladugu Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 34bc54e..38592f5 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -154,21 +154,17 @@ static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr) } #endif -int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) +static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout, + u8 cmd, u8 poll_bit) { - struct spi_slave *spi = flash->spi; unsigned long timebase; unsigned long flags = SPI_XFER_BEGIN; int ret; u8 status; u8 check_status = 0x0; - u8 poll_bit = STATUS_WIP; - u8 cmd = flash->poll_cmd; - if (cmd == CMD_FLAG_STATUS) { - poll_bit = STATUS_PEC; + if (cmd == CMD_FLAG_STATUS) check_status = poll_bit; - } #ifdef CONFIG_SF_DUAL_FLASH if (spi->flags & SPI_XFER_U_PAGE) @@ -204,6 +200,28 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) return -1; } +int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) +{ + struct spi_slave *spi = flash->spi; + int ret; + u8 poll_bit = STATUS_WIP; + u8 cmd = CMD_READ_STATUS; + + ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit); + if (ret < 0) + return ret; + + if (flash->poll_cmd == CMD_FLAG_STATUS) { + poll_bit = STATUS_PEC; + cmd = CMD_FLAG_STATUS; + ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit); + if (ret < 0) + return ret; + } + + return 0; +} + int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, const void *buf, size_t buf_len) { -- cgit v0.10.2 From 8c48a68346038fdaa901e622760fe4c6a302220b Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Wed, 15 Apr 2015 13:13:28 +0200 Subject: zynq: spi: Remove unnecessary error condition Removed the unnecessary error check from spi_xfer as the bitlen zero is possible now to deassert the chip select for which no data is required to be transfered. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index 5da8759..e9129da 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -227,9 +227,6 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n", slave->bus, slave->cs, bitlen, len, flags); - if (bitlen == 0) - return -1; - if (bitlen % 8) { debug("spi_xfer: Non byte aligned SPI transfer\n"); return -1; -- cgit v0.10.2 From d15e74f16cc521da0e08060cda2c87307bd4363f Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 21 Apr 2015 10:37:45 +0200 Subject: spi flash: fix trivial problems Fix typos and too big #ifdef. Signed-off-by: Pavel Machek Reviewed-by: Marek Vasut Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/include/spi_flash.h b/include/spi_flash.h index 218283f..4791b94 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -62,11 +62,9 @@ struct spi_slave; * return 0 - Success, 1 - Failure */ struct spi_flash { -#ifdef CONFIG_DM_SPI_FLASH struct spi_slave *spi; +#ifdef CONFIG_DM_SPI_FLASH struct udevice *dev; -#else - struct spi_slave *spi; #endif const char *name; u8 dual_flash; @@ -91,13 +89,13 @@ struct spi_flash { #ifndef CONFIG_DM_SPI_FLASH /* * These are not strictly needed for driver model, but keep them here - * whilt the transition is in progress. + * while the transition is in progress. * * Normally each driver would provide its own operations, but for * SPI flash most chips use the same algorithms. One approach is * to create a 'common' SPI flash device which knows how to talk * to most devices, and then allow other drivers to be used instead - * if requird, perhaps with a way of scanning through the list to + * if required, perhaps with a way of scanning through the list to * find the driver that matches the device. */ int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); -- cgit v0.10.2 From ed62756dcf5544e277d87c461a84c6274f42b765 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 9 Jan 2015 14:39:22 +0100 Subject: cmd_sf: Fix problem with "sf update" and unaligned length On SoCFPGA, using "sf update" with an non-4byte aligned length leads to a hangup (and reboot via watchdog). This is because of the unaligned access in the cadence QSPI driver which is hard to prevent since the data is written into a 4-byte wide FIFO. This patch fixes this problem by changing the behavior of the last sector write (not sector aligned). The new code is even simpler and copies the source data into the temp buffer and now uses the temp buffer to write the complete sector. So only one SPI sector write is used now instead of 2 in the old version. Signed-off-by: Stefan Roese Cc: Gerlando Falauto Cc: Valentin Longchamp Cc: Holger Brunck Acked-by: Gerlando Falauto Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 6aabf39..342021d 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -164,6 +164,8 @@ static int do_spi_flash_probe(int argc, char * const argv[]) static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset, size_t len, const char *buf, char *cmp_buf, size_t *skipped) { + char *ptr = (char *)buf; + debug("offset=%#x, sector_size=%#x, len=%#zx\n", offset, flash->sector_size, len); /* Read the entire sector so to allow for rewriting */ @@ -179,16 +181,14 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset, /* Erase the entire sector */ if (spi_flash_erase(flash, offset, flash->sector_size)) return "erase"; - /* Write the initial part of the block from the source */ - if (spi_flash_write(flash, offset, len, buf)) - return "write"; - /* If it's a partial sector, rewrite the existing part */ + /* If it's a partial sector, copy the data into the temp-buffer */ if (len != flash->sector_size) { - /* Rewrite the original data to the end of the sector */ - if (spi_flash_write(flash, offset + len, - flash->sector_size - len, &cmp_buf[len])) - return "write"; + memcpy(cmp_buf, buf, len); + ptr = cmp_buf; } + /* Write one complete sector */ + if (spi_flash_write(flash, offset, flash->sector_size, ptr)) + return "write"; return NULL; } -- cgit v0.10.2 From 4fbad92e7382c74757a58491deb6d210d1d842db Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 20 Mar 2015 13:19:16 +0800 Subject: mtd: spi: check return value of spi_setup_slave Need to check value of spi_setup_slave and spi_setup_slave_fdt. If their return value 'bus' is NULL, there is no need to pass it to following spi_flash_probe_tail. If 'bus' is null, the original function flow is as following: spi_flash_probe |->spi_setup_slave |->spi_probe_bus_tail |->spi_flash_probe_slave |->spi_free_slave Alougth check the pointer in spi_free_slave is ok, checking the return value of spi_setup_slave and spi_setup_slave_fdt is better. Before this fix: " => sf probe 0:2 FSL_QSPI: Not a valid cs ! SF: Failed to set up slave data abort pc : [] lr : [] reloc pc : [<87814dcc>] lr : [<8782428c>] sp : fdf4fcf0 ip : e630396c fp : fe0d0888 r10: fffa2538 r9 : fdf4feb8 r8 : 02625a00 r7 : 00000002 r6 : fff94ec0 r5 : 00000000 r4 : 9355553c r3 : 1af0593c r2 : cb3fe030 r1 : fff94eb8 r0 : e59ff018 Flags: nZCv IRQs off FIQs off Mode SVC_32 Resetting CPU ... " After this fix: " => sf probe 0:2 FSL_QSPI: Not a valid cs ! Failed to initialize SPI flash at 0:2 " No data abort using this patch. Signed-off-by: Peng Fan Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index d19138d..2ee228d 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -434,6 +434,8 @@ struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, struct spi_slave *bus; bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); + if (!bus) + return NULL; return spi_flash_probe_tail(bus); } @@ -444,6 +446,8 @@ struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, struct spi_slave *bus; bus = spi_setup_slave_fdt(blob, slave_node, spi_node); + if (!bus) + return NULL; return spi_flash_probe_tail(bus); } #endif -- cgit v0.10.2 From 9694b724421b88acf7d553a55e4a43fa4e25e7be Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 19 Apr 2015 09:05:40 -0600 Subject: dm: spi: Correct SPI claim/release_bus() methods These methods should be passed a slave device, not a bus. This matches the old SPI interface. It is important to know which device is claiming the bus so passing a bus is not that useful. Reported-by: Haikun Wang Signed-off-by: Simon Glass Tested-by: Peng Fan Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c index a46d8c1..67f6b2d 100644 --- a/drivers/spi/exynos_spi.c +++ b/drivers/spi/exynos_spi.c @@ -296,8 +296,9 @@ static int exynos_spi_probe(struct udevice *bus) return 0; } -static int exynos_spi_claim_bus(struct udevice *bus) +static int exynos_spi_claim_bus(struct udevice *dev) { + struct udevice *bus = dev->parent; struct exynos_spi_priv *priv = dev_get_priv(bus); exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE); @@ -308,8 +309,9 @@ static int exynos_spi_claim_bus(struct udevice *bus) return 0; } -static int exynos_spi_release_bus(struct udevice *bus) +static int exynos_spi_release_bus(struct udevice *dev) { + struct udevice *bus = dev->parent; struct exynos_spi_priv *priv = dev_get_priv(bus); spi_flush_fifo(priv->regs); diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index 866c48f..83fe8e0 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -67,7 +67,7 @@ int spi_claim_bus(struct spi_slave *slave) if (ret) return ret; - return ops->claim_bus ? ops->claim_bus(bus) : 0; + return ops->claim_bus ? ops->claim_bus(dev) : 0; } void spi_release_bus(struct spi_slave *slave) @@ -77,7 +77,7 @@ void spi_release_bus(struct spi_slave *slave) struct dm_spi_ops *ops = spi_get_ops(bus); if (ops->release_bus) - ops->release_bus(bus); + ops->release_bus(dev); } int spi_xfer(struct spi_slave *slave, unsigned int bitlen, diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c index 53ff9ea..4bec663 100644 --- a/drivers/spi/tegra114_spi.c +++ b/drivers/spi/tegra114_spi.c @@ -153,8 +153,9 @@ static int tegra114_spi_probe(struct udevice *bus) return 0; } -static int tegra114_spi_claim_bus(struct udevice *bus) +static int tegra114_spi_claim_bus(struct udevice *dev) { + struct udevice *bus = dev->parent; struct tegra114_spi_priv *priv = dev_get_priv(bus); struct spi_regs *regs = priv->regs; diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c index 78c74cd..82c1b84 100644 --- a/drivers/spi/tegra20_sflash.c +++ b/drivers/spi/tegra20_sflash.c @@ -125,8 +125,9 @@ static int tegra20_sflash_probe(struct udevice *bus) return 0; } -static int tegra20_sflash_claim_bus(struct udevice *bus) +static int tegra20_sflash_claim_bus(struct udevice *dev) { + struct udevice *bus = dev->parent; struct tegra20_sflash_priv *priv = dev_get_priv(bus); struct spi_regs *regs = priv->regs; u32 reg; diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c index 597d6ad..f6fb89b 100644 --- a/drivers/spi/tegra20_slink.c +++ b/drivers/spi/tegra20_slink.c @@ -141,8 +141,9 @@ static int tegra30_spi_probe(struct udevice *bus) return 0; } -static int tegra30_spi_claim_bus(struct udevice *bus) +static int tegra30_spi_claim_bus(struct udevice *dev) { + struct udevice *bus = dev->parent; struct tegra30_spi_priv *priv = dev_get_priv(bus); struct spi_regs *regs = priv->regs; u32 reg; diff --git a/include/spi.h b/include/spi.h index 7829063..9495ca5 100644 --- a/include/spi.h +++ b/include/spi.h @@ -386,12 +386,12 @@ struct dm_spi_ops { * allowed to claim the same bus for several slaves without releasing * the bus in between. * - * @bus: The SPI slave + * @dev: The SPI slave * * Returns: 0 if the bus was claimed successfully, or a negative value * if it wasn't. */ - int (*claim_bus)(struct udevice *bus); + int (*claim_bus)(struct udevice *dev); /** * Release the SPI bus @@ -400,9 +400,9 @@ struct dm_spi_ops { * all transfers have finished. It may disable any SPI hardware as * appropriate. * - * @bus: The SPI slave + * @dev: The SPI slave */ - int (*release_bus)(struct udevice *bus); + int (*release_bus)(struct udevice *dev); /** * Set the word length for SPI transactions @@ -414,7 +414,7 @@ struct dm_spi_ops { * * Returns: 0 on success, -ve on failure. */ - int (*set_wordlen)(struct udevice *bus, unsigned int wordlen); + int (*set_wordlen)(struct udevice *dev, unsigned int wordlen); /** * SPI transfer -- cgit v0.10.2 From 122d805fd4bd478bb83536348291d34ae648364b Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Thu, 23 Apr 2015 19:52:11 +0530 Subject: Revert "spi: add config option to enable the WP pin function on st micron flashes" This reverts commit 562f8df18da62ae02c4ace1e530451fe82c3312d. Note: Even un-reverting this patch couldn't works as expected, based on the latest testing from Heiko Schocher. Signed-off-by: Jagannadha Sutradharudu Teki Cc: Heiko Schocher diff --git a/README b/README index fc1fd52..82224f7 100644 --- a/README +++ b/README @@ -3086,17 +3086,6 @@ CBFS (Coreboot Filesystem) support memories can be connected with a given cs line. Currently Xilinx Zynq qspi supports these type of connections. - CONFIG_SYS_SPI_ST_ENABLE_WP_PIN - enable the W#/Vpp signal to disable writing to the status - register on ST MICRON flashes like the N25Q128. - The status register write enable/disable bit, combined with - the W#/VPP signal provides hardware data protection for the - device as follows: When the enable/disable bit is set to 1, - and the W#/VPP signal is driven LOW, the status register - nonvolatile bits become read-only and the WRITE STATUS REGISTER - operation will not execute. The only way to exit this - hardware-protected mode is to drive W#/VPP HIGH. - - SystemACE Support: CONFIG_SYSTEMACE diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 785f7a9..bd834dc 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -97,10 +97,6 @@ enum { #define STATUS_QEB_MXIC (1 << 6) #define STATUS_PEC (1 << 7) -#ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN -#define STATUS_SRWD (1 << 7) /* SR write protect */ -#endif - /* Flash timeout values */ #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 2ee228d..de8d0b7 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -288,34 +288,6 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) } #endif /* CONFIG_OF_CONTROL */ -#ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN -/* enable the W#/Vpp signal to disable writing to the status register */ -static int spi_enable_wp_pin(struct spi_flash *flash) -{ - u8 status; - int ret; - - ret = spi_flash_cmd_read_status(flash, &status); - if (ret < 0) - return ret; - - ret = spi_flash_cmd_write_status(flash, STATUS_SRWD); - if (ret < 0) - return ret; - - ret = spi_flash_cmd_write_disable(flash); - if (ret < 0) - return ret; - - return 0; -} -#else -static int spi_enable_wp_pin(struct spi_flash *flash) -{ - return 0; -} -#endif - /** * spi_flash_probe_slave() - Probe for a SPI flash device on a bus * @@ -394,8 +366,6 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); } #endif - if (spi_enable_wp_pin(flash)) - puts("Enable WP pin failed\n"); /* Release spi bus */ spi_release_bus(spi); -- cgit v0.10.2 From 611c9ba2b8c27d6e3c63b663c88f1c8be9638c3a Mon Sep 17 00:00:00 2001 From: David Dueck Date: Wed, 1 Apr 2015 14:20:24 +0200 Subject: spi: omap3: Fix timeout handling The timeout value is never reset during the transfer. This means that when transferring more data we eventually trigger the timeout. This was reported on the mailing list: "Spansion SPI flash read timeout with AM335x" Signed-off-by: David Dueck CC: Tom Rini CC: Stefan Roese CC: Andy Pont Tested-by: David Dueck Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index 651e46e..85f9e85 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -20,7 +20,7 @@ #include #include "omap3_spi.h" -#define SPI_WAIT_TIMEOUT 3000000 +#define SPI_WAIT_TIMEOUT 10 static void spi_reset(struct omap3_spi_slave *ds) { @@ -227,7 +227,7 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp, { struct omap3_spi_slave *ds = to_omap3_spi(slave); int i; - int timeout = SPI_WAIT_TIMEOUT; + ulong start; int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); /* Enable the channel */ @@ -241,9 +241,10 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp, for (i = 0; i < len; i++) { /* wait till TX register is empty (TXS == 1) */ + start = get_timer(0); while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & OMAP3_MCSPI_CHSTAT_TXS)) { - if (--timeout <= 0) { + if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI TXS timed out, status=0x%08x\n", readl(&ds->regs->channel[ds->slave.cs].chstat)); return -1; @@ -280,7 +281,7 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp, { struct omap3_spi_slave *ds = to_omap3_spi(slave); int i; - int timeout = SPI_WAIT_TIMEOUT; + ulong start; int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); /* Enable the channel */ @@ -295,10 +296,11 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp, writel(0, &ds->regs->channel[ds->slave.cs].tx); for (i = 0; i < len; i++) { + start = get_timer(0); /* Wait till RX register contains data (RXS == 1) */ while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & OMAP3_MCSPI_CHSTAT_RXS)) { - if (--timeout <= 0) { + if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI RXS timed out, status=0x%08x\n", readl(&ds->regs->channel[ds->slave.cs].chstat)); return -1; @@ -332,7 +334,7 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, const void *txp, void *rxp, unsigned long flags) { struct omap3_spi_slave *ds = to_omap3_spi(slave); - int timeout = SPI_WAIT_TIMEOUT; + ulong start; int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); int irqstatus = readl(&ds->regs->irqstatus); int i=0; @@ -350,9 +352,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, for (i=0; i < len; i++){ /* Write: wait for TX empty (TXS == 1)*/ irqstatus |= (1<< (4*(ds->slave.bus))); + start = get_timer(0); while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & OMAP3_MCSPI_CHSTAT_TXS)) { - if (--timeout <= 0) { + if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI TXS timed out, status=0x%08x\n", readl(&ds->regs->channel[ds->slave.cs].chstat)); return -1; @@ -368,9 +371,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, writel(((u8 *)txp)[i], tx); /*Read: wait for RX containing data (RXS == 1)*/ + start = get_timer(0); while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & OMAP3_MCSPI_CHSTAT_RXS)) { - if (--timeout <= 0) { + if (get_timer(start) > SPI_WAIT_TIMEOUT) { printf("SPI RXS timed out, status=0x%08x\n", readl(&ds->regs->channel[ds->slave.cs].chstat)); return -1; -- cgit v0.10.2 From be7be78e10bfca6fc2d5e8fbc71da2db6a55c842 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Apr 2015 13:29:54 +0530 Subject: dm: sf: Save flash flags to struct spi_flash Add a new member 'flags' in struct spi_flash to store the flash flags during spi_flash_validate_params(). Signed-off-by: Bin Meng Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index de8d0b7..d8ab6a1 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -132,6 +132,9 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, flash->name = params->name; flash->memory_map = spi->memory_map; flash->dual_flash = flash->spi->option; +#ifdef CONFIG_DM_SPI_FLASH + flash->flags = params->flags; +#endif /* Assign spi_flash ops */ #ifndef CONFIG_DM_SPI_FLASH diff --git a/include/spi_flash.h b/include/spi_flash.h index 4791b94..f2814ef 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -65,6 +65,7 @@ struct spi_flash { struct spi_slave *spi; #ifdef CONFIG_DM_SPI_FLASH struct udevice *dev; + u16 flags; #endif const char *name; u8 dual_flash; -- cgit v0.10.2 From 074eed5146acc39a77f15ecdc8404b3ba74aa3ae Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 24 Apr 2015 19:51:10 +0800 Subject: dm: sf: Make SST flash write op work again With SPI flash moving to driver model, commit fbb0991 "dm: Convert spi_flash_probe() and 'sf probe' to use driver model" ignored the SST flash-specific write op (byte program & word program), which actually broke the SST flash from wroking. This commit makes SST flash work again under driver model, by adding SST flash-specific handling in the spi_flash_std_write(). Signed-off-by: Bin Meng Reviewed-by: Jagannadha Sutradharudu Teki diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index d8ab6a1..d8b9fca 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -446,6 +446,15 @@ int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, { struct spi_flash *flash = dev_get_uclass_priv(dev); +#if defined(CONFIG_SPI_FLASH_SST) + if (flash->flags & SST_WR) { + if (flash->spi->op_mode_tx & SPI_OPM_TX_BP) + return sst_write_bp(flash, offset, len, buf); + else + return sst_write_wp(flash, offset, len, buf); + } +#endif + return spi_flash_cmd_write_ops(flash, offset, len, buf); } -- cgit v0.10.2 From c650ca7b4c160193791dc7a52381c71c6a29e871 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Mon, 27 Apr 2015 21:04:15 +0530 Subject: sf: Fix to compute proper sector_size Upto now flash sector_size is assigned from params which isn't necessarily a sector size from vendor, so based on the SECT_* flags from flash_params the erase_size will compute and it will become the sector_size finally. Bug report (from Bin Meng): => sf probe SF: Detected SST25VF016B with page size 256 Bytes, erase size 4 KiB, total 2 MiB, mapped at ffe00000 => sf erase 0 +100 SF: 65536 bytes @ 0x0 Erased: OK Signed-off-by: Jagannadha Sutradharudu Teki Reported-by: Bin Meng Tested-by: Bin Meng diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index bd834dc..4158e13 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -119,7 +119,8 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id]) * @ext_jedec: Device ext_jedec ID - * @sector_size: Sector size of this device + * @sector_size: Isn't necessarily a sector size from vendor, + * the size listed here is what works with CMD_ERASE_64K * @nr_sectors: No.of sectors on this device * @e_rd_cmd: Enum list for read commands * @flags: Important param, for flash specific behaviour diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index d8b9fca..201471c 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -187,6 +187,9 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, flash->erase_size = flash->sector_size; } + /* Now erase size becomes valid sector size */ + flash->sector_size = flash->erase_size; + /* Look for the fastest read cmd */ cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); if (cmd) { -- cgit v0.10.2