Message ID | 20190205055929.24168-15-vigneshr@ti.com |
---|---|
State | Accepted |
Delegated to: | Jagannadha Sutradharudu Teki |
Headers | show |
Series | SF: Migrate to Linux SPI NOR framework | expand |
On Tue, Feb 5, 2019 at 12:00 AM Vignesh R <vigneshr@ti.com> wrote: > > Switch spi_flash_* interfaces to call into new SPI NOR framework via MTD > layer. Fix up sf_dataflash to work in legacy way. And update sandbox to > use new interfaces/definitions > > Signed-off-by: Vignesh R <vigneshr@ti.com> > Tested-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com> > Tested-by: Stefan Roese <sr@denx.de> > Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com> > Reviewed-by: Jagan Teki <jagan@openedev.com> > Tested-by: Jagan Teki <jagan@amarulasolutions.com> #zynq-microzed This patch appears to break the da850_evm board which boots from SPI Flash and initializes the davinci driver with platdata since the device tree stuff does not quite work right in SPL. U-Boot SPL 2019.01-02923-gc4e8862308-dirty (Feb 10 2019 - 21:24:38 -0600) Trying to boot from SPI SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### Any suggestions on how to fix the SPI initialization without needing the device tree? I have tried to port the device tree stuff to SPL, but I haven't yet been successful so I have had to leave the platdata initialization in place. adam > --- > drivers/mtd/spi/Kconfig | 2 + > drivers/mtd/spi/Makefile | 4 +- > drivers/mtd/spi/sandbox.c | 36 +++--- > drivers/mtd/spi/sf_dataflash.c | 11 +- > drivers/mtd/spi/sf_internal.h | 225 ++++++--------------------------- > drivers/mtd/spi/sf_probe.c | 32 +++-- > drivers/mtd/spi/spi-nor-core.c | 59 +-------- > drivers/spi/stm32_qspi.c | 4 +- > include/spi_flash.h | 105 ++++----------- > 9 files changed, 113 insertions(+), 365 deletions(-) > > diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig > index 4ba95d58b371..e3b40fc157d6 100644 > --- a/drivers/mtd/spi/Kconfig > +++ b/drivers/mtd/spi/Kconfig > @@ -27,6 +27,8 @@ config SPI_FLASH_SANDBOX > > config SPI_FLASH > bool "Legacy SPI Flash Interface support" > + depends on SPI > + select SPI_MEM > help > Enable the legacy SPI flash support. This will include basic > standard support for things like probing, read / write, and > diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile > index b4c7e1c98bd5..70058d3df2b9 100644 > --- a/drivers/mtd/spi/Makefile > +++ b/drivers/mtd/spi/Makefile > @@ -9,7 +9,7 @@ ifdef CONFIG_SPL_BUILD > obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o > endif > > -obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o spi_flash_ids.o sf.o > -obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o > +obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi-nor-core.o > +obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o sf.o > obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o > obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o > diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c > index 7b9891cb981c..084c66e9840b 100644 > --- a/drivers/mtd/spi/sandbox.c > +++ b/drivers/mtd/spi/sandbox.c > @@ -92,7 +92,7 @@ struct sandbox_spi_flash { > /* The current flash status (see STAT_XXX defines above) */ > u16 status; > /* Data describing the flash we're emulating */ > - const struct spi_flash_info *data; > + const struct flash_info *data; > /* The file on disk to serv up data from */ > int fd; > }; > @@ -122,7 +122,7 @@ static int sandbox_sf_probe(struct udevice *dev) > /* spec = idcode:file */ > struct sandbox_spi_flash *sbsf = dev_get_priv(dev); > size_t len, idname_len; > - const struct spi_flash_info *data; > + const struct flash_info *data; > struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); > struct sandbox_state *state = state_get_current(); > struct dm_spi_slave_platdata *slave_plat; > @@ -155,7 +155,7 @@ static int sandbox_sf_probe(struct udevice *dev) > idname_len = strlen(spec); > debug("%s: device='%s'\n", __func__, spec); > > - for (data = spi_flash_ids; data->name; data++) { > + for (data = spi_nor_ids; data->name; data++) { > len = strlen(data->name); > if (idname_len != len) > continue; > @@ -243,43 +243,43 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, > > sbsf->cmd = rx[0]; > switch (sbsf->cmd) { > - case CMD_READ_ID: > + case SPINOR_OP_RDID: > sbsf->state = SF_ID; > sbsf->cmd = SF_ID; > break; > - case CMD_READ_ARRAY_FAST: > + case SPINOR_OP_READ_FAST: > sbsf->pad_addr_bytes = 1; > - case CMD_READ_ARRAY_SLOW: > - case CMD_PAGE_PROGRAM: > + case SPINOR_OP_READ: > + case SPINOR_OP_PP: > sbsf->state = SF_ADDR; > break; > - case CMD_WRITE_DISABLE: > + case SPINOR_OP_WRDI: > debug(" write disabled\n"); > sbsf->status &= ~STAT_WEL; > break; > - case CMD_READ_STATUS: > + case SPINOR_OP_RDSR: > sbsf->state = SF_READ_STATUS; > break; > - case CMD_READ_STATUS1: > + case SPINOR_OP_RDSR2: > sbsf->state = SF_READ_STATUS1; > break; > - case CMD_WRITE_ENABLE: > + case SPINOR_OP_WREN: > debug(" write enabled\n"); > sbsf->status |= STAT_WEL; > break; > - case CMD_WRITE_STATUS: > + case SPINOR_OP_WRSR: > sbsf->state = SF_WRITE_STATUS; > break; > default: { > int flags = sbsf->data->flags; > > /* we only support erase here */ > - if (sbsf->cmd == CMD_ERASE_CHIP) { > + if (sbsf->cmd == SPINOR_OP_CHIP_ERASE) { > sbsf->erase_size = sbsf->data->sector_size * > sbsf->data->n_sectors; > - } else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { > + } else if (sbsf->cmd == SPINOR_OP_BE_4K && (flags & SECT_4K)) { > sbsf->erase_size = 4 << 10; > - } else if (sbsf->cmd == CMD_ERASE_64K && !(flags & SECT_4K)) { > + } else if (sbsf->cmd == SPINOR_OP_SE && !(flags & SECT_4K)) { > sbsf->erase_size = 64 << 10; > } else { > debug(" cmd unknown: %#x\n", sbsf->cmd); > @@ -380,11 +380,11 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, > return -EIO; > } > switch (sbsf->cmd) { > - case CMD_READ_ARRAY_FAST: > - case CMD_READ_ARRAY_SLOW: > + case SPINOR_OP_READ_FAST: > + case SPINOR_OP_READ: > sbsf->state = SF_READ; > break; > - case CMD_PAGE_PROGRAM: > + case SPINOR_OP_PP: > sbsf->state = SF_WRITE; > break; > default: > diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c > index 4a60c1b2b43a..b6a2631747a9 100644 > --- a/drivers/mtd/spi/sf_dataflash.c > +++ b/drivers/mtd/spi/sf_dataflash.c > @@ -18,6 +18,7 @@ > > #include "sf_internal.h" > > +#define CMD_READ_ID 0x9f > /* reads can bypass the buffers */ > #define OP_READ_CONTINUOUS 0xE8 > #define OP_READ_PAGE 0xD2 > @@ -441,7 +442,7 @@ static int add_dataflash(struct udevice *dev, char *name, int nr_pages, > return 0; > } > > -struct flash_info { > +struct data_flash_info { > char *name; > > /* > @@ -460,7 +461,7 @@ struct flash_info { > #define IS_POW2PS 0x0001 /* uses 2^N byte pages */ > }; > > -static struct flash_info dataflash_data[] = { > +static struct data_flash_info dataflash_data[] = { > /* > * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, > * one with IS_POW2PS and the other without. The entry with the > @@ -501,12 +502,12 @@ static struct flash_info dataflash_data[] = { > { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, > }; > > -static struct flash_info *jedec_probe(struct spi_slave *spi) > +static struct data_flash_info *jedec_probe(struct spi_slave *spi) > { > int tmp; > uint8_t id[5]; > uint32_t jedec; > - struct flash_info *info; > + struct data_flash_info *info; > int status; > > /* > @@ -583,7 +584,7 @@ static int spi_dataflash_probe(struct udevice *dev) > { > struct spi_slave *spi = dev_get_parent_priv(dev); > struct spi_flash *spi_flash; > - struct flash_info *info; > + struct data_flash_info *info; > int status; > > spi_flash = dev_get_uclass_priv(dev); > diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h > index 46a504441751..fd00e0d1b23b 100644 > --- a/drivers/mtd/spi/sf_internal.h > +++ b/drivers/mtd/spi/sf_internal.h > @@ -12,142 +12,63 @@ > #include <linux/types.h> > #include <linux/compiler.h> > > -/* Dual SPI flash memories - see SPI_COMM_DUAL_... */ > -enum spi_dual_flash { > - SF_SINGLE_FLASH = 0, > - SF_DUAL_STACKED_FLASH = BIT(0), > - SF_DUAL_PARALLEL_FLASH = BIT(1), > -}; > - > -enum spi_nor_option_flags { > - SNOR_F_SST_WR = BIT(0), > - SNOR_F_USE_FSR = BIT(1), > - SNOR_F_USE_UPAGE = BIT(3), > -}; > - > -#define SPI_FLASH_3B_ADDR_LEN 3 > -#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) > -#define SPI_FLASH_16MB_BOUN 0x1000000 > - > -/* CFI Manufacture ID's */ > -#define SPI_FLASH_CFI_MFR_SPANSION 0x01 > -#define SPI_FLASH_CFI_MFR_STMICRO 0x20 > -#define SPI_FLASH_CFI_MFR_MICRON 0x2C > -#define SPI_FLASH_CFI_MFR_MACRONIX 0xc2 > -#define SPI_FLASH_CFI_MFR_SST 0xbf > -#define SPI_FLASH_CFI_MFR_WINBOND 0xef > -#define SPI_FLASH_CFI_MFR_ATMEL 0x1f > - > -/* Erase commands */ > -#define CMD_ERASE_4K 0x20 > -#define CMD_ERASE_CHIP 0xc7 > -#define CMD_ERASE_64K 0xd8 > - > -/* Write commands */ > -#define CMD_WRITE_STATUS 0x01 > -#define CMD_PAGE_PROGRAM 0x02 > -#define CMD_WRITE_DISABLE 0x04 > -#define CMD_WRITE_ENABLE 0x06 > -#define CMD_QUAD_PAGE_PROGRAM 0x32 > - > -/* Read commands */ > -#define CMD_READ_ARRAY_SLOW 0x03 > -#define CMD_READ_ARRAY_FAST 0x0b > -#define CMD_READ_DUAL_OUTPUT_FAST 0x3b > -#define CMD_READ_DUAL_IO_FAST 0xbb > -#define CMD_READ_QUAD_OUTPUT_FAST 0x6b > -#define CMD_READ_QUAD_IO_FAST 0xeb > -#define CMD_READ_ID 0x9f > -#define CMD_READ_STATUS 0x05 > -#define CMD_READ_STATUS1 0x35 > -#define CMD_READ_CONFIG 0x35 > -#define CMD_FLAG_STATUS 0x70 > - > -/* Bank addr access commands */ > -#ifdef CONFIG_SPI_FLASH_BAR > -# define CMD_BANKADDR_BRWR 0x17 > -# define CMD_BANKADDR_BRRD 0x16 > -# define CMD_EXTNADDR_WREAR 0xC5 > -# define CMD_EXTNADDR_RDEAR 0xC8 > -#endif > - > -/* Common status */ > -#define STATUS_WIP BIT(0) > -#define STATUS_QEB_WINSPAN BIT(1) > -#define STATUS_QEB_MXIC BIT(6) > -#define STATUS_PEC BIT(7) > -#define SR_BP0 BIT(2) /* Block protect 0 */ > -#define SR_BP1 BIT(3) /* Block protect 1 */ > -#define SR_BP2 BIT(4) /* Block protect 2 */ > - > -/* Flash timeout values */ > -#define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) > -#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) > -#define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) > - > -/* SST specific */ > -#ifdef CONFIG_SPI_FLASH_SST > -#define SST26_CMD_READ_BPR 0x72 > -#define SST26_CMD_WRITE_BPR 0x42 > - > -#define SST26_BPR_8K_NUM 4 > -#define SST26_MAX_BPR_REG_LEN (18 + 1) > -#define SST26_BOUND_REG_SIZE ((32 + SST26_BPR_8K_NUM * 8) * SZ_1K) > - > -enum lock_ctl { > - SST26_CTL_LOCK, > - SST26_CTL_UNLOCK, > - SST26_CTL_CHECK > -}; > - > -# define CMD_SST_BP 0x02 /* Byte Program */ > -# define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ > - > -int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, > - const void *buf); > -int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, > - const void *buf); > -#endif > - > -#define JEDEC_MFR(info) ((info)->id[0]) > -#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) > -#define JEDEC_EXT(info) (((info)->id[3]) << 8 | ((info)->id[4])) > -#define SPI_FLASH_MAX_ID_LEN 6 > +#define SPI_NOR_MAX_ID_LEN 6 > +#define SPI_NOR_MAX_ADDR_WIDTH 4 > > -struct spi_flash_info { > - /* Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) */ > - const char *name; > +struct flash_info { > + char *name; > > /* > * This array stores the ID bytes. > * The first three bytes are the JEDIC ID. > * JEDEC ID zero means "no ID" (mostly older chips). > */ > - u8 id[SPI_FLASH_MAX_ID_LEN]; > + u8 id[SPI_NOR_MAX_ID_LEN]; > u8 id_len; > > - /* > - * The size listed here is what works with SPINOR_OP_SE, which isn't > + /* The size listed here is what works with SPINOR_OP_SE, which isn't > * necessarily called a "sector" by the vendor. > */ > - u32 sector_size; > - u32 n_sectors; > + unsigned int sector_size; > + u16 n_sectors; > > u16 page_size; > + u16 addr_width; > > u16 flags; > -#define SECT_4K BIT(0) /* CMD_ERASE_4K works uniformly */ > -#define E_FSR BIT(1) /* use flag status register for */ > -#define SST_WR BIT(2) /* use SST byte/word programming */ > -#define WR_QPP BIT(3) /* use Quad Page Program */ > -#define RD_QUAD BIT(4) /* use Quad Read */ > -#define RD_DUAL BIT(5) /* use Dual Read */ > -#define RD_QUADIO BIT(6) /* use Quad IO Read */ > -#define RD_DUALIO BIT(7) /* use Dual IO Read */ > -#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) > +#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */ > +#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */ > +#define SST_WRITE BIT(2) /* use SST byte programming */ > +#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */ > +#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ > +#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ > +#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ > +#define USE_FSR BIT(7) /* use flag status register */ > +#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ > +#define SPI_NOR_HAS_TB BIT(9) /* > + * Flash SR has Top/Bottom (TB) protect > + * bit. Must be used with > + * SPI_NOR_HAS_LOCK. > + */ > +#define SPI_S3AN BIT(10) /* > + * Xilinx Spartan 3AN In-System Flash > + * (MFR cannot be used for probing > + * because it has the same value as > + * ATMEL flashes) > + */ > +#define SPI_NOR_4B_OPCODES BIT(11) /* > + * Use dedicated 4byte address op codes > + * to support memory size above 128Mib. > + */ > +#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ > +#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ > +#define USE_CLSR BIT(14) /* use CLSR command */ > }; > > -extern const struct spi_flash_info spi_flash_ids[]; > +extern const struct flash_info spi_nor_ids[]; > + > +#define JEDEC_MFR(info) ((info)->id[0]) > +#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) > > /* Send a single-byte command to the device and read the response */ > int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); > @@ -167,78 +88,12 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, > const void *data, size_t data_len); > > > -/* Flash erase(sectors) operation, support all possible erase commands */ > -int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); > - > /* Get software write-protect value (BP bits) */ > int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash); > > -/* Lock stmicro spi flash region */ > -int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); > - > -/* Unlock stmicro spi flash region */ > -int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len); > - > -/* Check if a stmicro spi flash region is completely locked */ > -int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len); > - > -/* Enable writing on the SPI flash */ > -static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) > -{ > - return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); > -} > - > -/* Disable writing on the SPI flash */ > -static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) > -{ > - return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); > -} > - > -/* > - * Used for spi_flash write operation > - * - SPI claim > - * - spi_flash_cmd_write_enable > - * - spi_flash_cmd_write > - * - spi_flash_wait_till_ready > - * - SPI release > - */ > -int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, > - size_t cmd_len, const void *buf, size_t buf_len); > - > -/* > - * Flash write operation, support all possible write commands. > - * Write the requested data out breaking it up into multiple write > - * commands as needed per the write size. > - */ > -int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, > - size_t len, const void *buf); > - > -/* > - * Same as spi_flash_cmd_read() except it also claims/releases the SPI > - * bus. Used as common part of the ->read() operation. > - */ > -int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, > - size_t cmd_len, void *data, size_t data_len); > - > -/* Flash read operation, support all possible read commands */ > -int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, > - size_t len, void *data); > > #ifdef CONFIG_SPI_FLASH_MTD > int spi_flash_mtd_register(struct spi_flash *flash); > void spi_flash_mtd_unregister(void); > #endif > - > -/** > - * spi_flash_scan - scan the SPI FLASH > - * @flash: the spi flash structure > - * > - * The drivers can use this fuction to scan the SPI FLASH. > - * In the scanning, it will try to get all the necessary information to > - * fill the spi_flash{}. > - * > - * Return: 0 for success, others for failure. > - */ > -int spi_flash_scan(struct spi_flash *flash); > - > #endif /* _SF_INTERNAL_H_ */ > diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c > index 7a379914d8f1..7f1378f4946d 100644 > --- a/drivers/mtd/spi/sf_probe.c > +++ b/drivers/mtd/spi/sf_probe.c > @@ -40,7 +40,7 @@ static int spi_flash_probe_slave(struct spi_flash *flash) > return ret; > } > > - ret = spi_flash_scan(flash); > + ret = spi_nor_scan(flash); > if (ret) > goto err_read_id; > > @@ -96,32 +96,38 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, > void *buf) > { > struct spi_flash *flash = dev_get_uclass_priv(dev); > + struct mtd_info *mtd = &flash->mtd; > + size_t retlen; > > - return log_ret(spi_flash_cmd_read_ops(flash, offset, len, buf)); > + return log_ret(mtd->_read(mtd, offset, len, &retlen, buf)); > } > > static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, > const void *buf) > { > struct spi_flash *flash = dev_get_uclass_priv(dev); > + struct mtd_info *mtd = &flash->mtd; > + size_t retlen; > > -#if defined(CONFIG_SPI_FLASH_SST) > - if (flash->flags & SNOR_F_SST_WR) { > - if (flash->spi->mode & SPI_TX_BYTE) > - 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); > + return mtd->_write(mtd, offset, len, &retlen, buf); > } > > static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) > { > struct spi_flash *flash = dev_get_uclass_priv(dev); > + struct mtd_info *mtd = &flash->mtd; > + struct erase_info instr; > + > + if (offset % mtd->erasesize || len % mtd->erasesize) { > + printf("SF: Erase offset/length not multiple of erase size\n"); > + return -EINVAL; > + } > + > + memset(&instr, 0, sizeof(instr)); > + instr.addr = offset; > + instr.len = len; > > - return spi_flash_cmd_erase_ops(flash, offset, len); > + return mtd->_erase(mtd, &instr); > } > > static int spi_flash_std_get_sw_write_prot(struct udevice *dev) > diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c > index 13c6236d623a..7590ff7716e8 100644 > --- a/drivers/mtd/spi/spi-nor-core.c > +++ b/drivers/mtd/spi/spi-nor-core.c > @@ -21,6 +21,8 @@ > #include <spi-mem.h> > #include <spi.h> > > +#include "sf_internal.h" > + > /* Define max times to check status register before we give up. */ > > /* > @@ -32,63 +34,6 @@ > > #define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) > > -#define SPI_NOR_MAX_ID_LEN 6 > -#define SPI_NOR_MAX_ADDR_WIDTH 4 > - > -struct flash_info { > - char *name; > - > - /* > - * This array stores the ID bytes. > - * The first three bytes are the JEDIC ID. > - * JEDEC ID zero means "no ID" (mostly older chips). > - */ > - u8 id[SPI_NOR_MAX_ID_LEN]; > - u8 id_len; > - > - /* The size listed here is what works with SPINOR_OP_SE, which isn't > - * necessarily called a "sector" by the vendor. > - */ > - unsigned int sector_size; > - u16 n_sectors; > - > - u16 page_size; > - u16 addr_width; > - > - u16 flags; > -#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */ > -#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */ > -#define SST_WRITE BIT(2) /* use SST byte programming */ > -#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */ > -#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ > -#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ > -#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ > -#define USE_FSR BIT(7) /* use flag status register */ > -#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ > -#define SPI_NOR_HAS_TB BIT(9) /* > - * Flash SR has Top/Bottom (TB) protect > - * bit. Must be used with > - * SPI_NOR_HAS_LOCK. > - */ > -#define SPI_S3AN BIT(10) /* > - * Xilinx Spartan 3AN In-System Flash > - * (MFR cannot be used for probing > - * because it has the same value as > - * ATMEL flashes) > - */ > -#define SPI_NOR_4B_OPCODES BIT(11) /* > - * Use dedicated 4byte address op codes > - * to support memory size above 128Mib. > - */ > -#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ > -#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ > -#define USE_CLSR BIT(14) /* use CLSR command */ > - > - int (*quad_enable)(struct spi_nor *nor); > -}; > - > -#define JEDEC_MFR(info) ((info)->id[0]) > - > static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op > *op, void *buf) > { > diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c > index 3b92254a5ce1..8b60d7c3b224 100644 > --- a/drivers/spi/stm32_qspi.c > +++ b/drivers/spi/stm32_qspi.c > @@ -271,9 +271,9 @@ static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv, > { > unsigned int ccr_reg; > > - priv->command = flash->read_cmd | CMD_HAS_ADR | CMD_HAS_DATA > + priv->command = flash->read_opcode | CMD_HAS_ADR | CMD_HAS_DATA > | CMD_HAS_DUMMY; > - priv->dummycycles = flash->dummy_byte * 8; > + priv->dummycycles = flash->read_dummy; > > ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP); > > diff --git a/include/spi_flash.h b/include/spi_flash.h > index e427e960d54f..7f691e8559cd 100644 > --- a/include/spi_flash.h > +++ b/include/spi_flash.h > @@ -11,6 +11,7 @@ > > #include <dm.h> /* Because we dereference struct udevice here */ > #include <linux/types.h> > +#include <linux/mtd/spi-nor.h> > > #ifndef CONFIG_SF_DEFAULT_SPEED > # define CONFIG_SF_DEFAULT_SPEED 1000000 > @@ -27,86 +28,6 @@ > > struct spi_slave; > > -/** > - * struct spi_flash - SPI flash structure > - * > - * @spi: SPI slave > - * @dev: SPI flash device > - * @name: Name of SPI flash > - * @dual_flash: Indicates dual flash memories - dual stacked, parallel > - * @shift: Flash shift useful in dual parallel > - * @flags: Indication of spi flash flags > - * @size: Total flash size > - * @page_size: Write (page) size > - * @sector_size: Sector size > - * @erase_size: Erase size > - * @bank_read_cmd: Bank read cmd > - * @bank_write_cmd: Bank write cmd > - * @bank_curr: Current flash bank > - * @erase_cmd: Erase cmd 4K, 32K, 64K > - * @read_cmd: Read cmd - Array Fast, Extn read and quad read. > - * @write_cmd: Write cmd - page and quad program. > - * @dummy_byte: Dummy cycles for read operation. > - * @memory_map: Address of read-only SPI flash access > - * @flash_lock: lock a region of the SPI Flash > - * @flash_unlock: unlock a region of the SPI Flash > - * @flash_is_locked: check if a region of the SPI Flash is completely locked > - * @read: Flash read ops: Read len bytes at offset into buf > - * Supported cmds: Fast Array Read > - * @write: Flash write ops: Write len bytes from buf into offset > - * Supported cmds: Page Program > - * @erase: Flash erase ops: Erase len bytes from offset > - * Supported cmds: Sector erase 4K, 32K, 64K > - * return 0 - Success, 1 - Failure > - */ > -struct spi_flash { > - struct spi_slave *spi; > -#ifdef CONFIG_DM_SPI_FLASH > - struct udevice *dev; > -#endif > - const char *name; > - u8 dual_flash; > - u8 shift; > - u16 flags; > - > - u32 size; > - u32 page_size; > - u32 sector_size; > - u32 erase_size; > -#ifdef CONFIG_SPI_FLASH_BAR > - u8 bank_read_cmd; > - u8 bank_write_cmd; > - u8 bank_curr; > -#endif > - u8 erase_cmd; > - u8 read_cmd; > - u8 write_cmd; > - u8 dummy_byte; > - > - void *memory_map; > - > - int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); > - int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); > - int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); > -#ifndef CONFIG_DM_SPI_FLASH > - /* > - * These are not strictly needed for driver model, but keep them here > - * 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 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); > - int (*write)(struct spi_flash *flash, u32 offset, size_t len, > - const void *buf); > - int (*erase)(struct spi_flash *flash, u32 offset, size_t len); > -#endif > -}; > - > struct dm_spi_flash_ops { > int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf); > int (*write)(struct udevice *dev, u32 offset, size_t len, > @@ -225,19 +146,37 @@ void spi_flash_free(struct spi_flash *flash); > static inline int spi_flash_read(struct spi_flash *flash, u32 offset, > size_t len, void *buf) > { > - return flash->read(flash, offset, len, buf); > + struct mtd_info *mtd = &flash->mtd; > + size_t retlen; > + > + return mtd->_read(mtd, offset, len, &retlen, buf); > } > > static inline int spi_flash_write(struct spi_flash *flash, u32 offset, > size_t len, const void *buf) > { > - return flash->write(flash, offset, len, buf); > + struct mtd_info *mtd = &flash->mtd; > + size_t retlen; > + > + return mtd->_write(mtd, offset, len, &retlen, buf); > } > > static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, > size_t len) > { > - return flash->erase(flash, offset, len); > + struct mtd_info *mtd = &flash->mtd; > + struct erase_info instr; > + > + if (offset % mtd->erasesize || len % mtd->erasesize) { > + printf("SF: Erase offset/length not multiple of erase size\n"); > + return -EINVAL; > + } > + > + memset(&instr, 0, sizeof(instr)); > + instr.addr = offset; > + instr.len = len; > + > + return mtd->_erase(mtd, &instr); > } > #endif > > -- > 2.20.1 >
On 11/02/19 9:01 AM, Adam Ford wrote: > On Tue, Feb 5, 2019 at 12:00 AM Vignesh R <vigneshr@ti.com> wrote: >> >> Switch spi_flash_* interfaces to call into new SPI NOR framework via MTD >> layer. Fix up sf_dataflash to work in legacy way. And update sandbox to >> use new interfaces/definitions >> >> Signed-off-by: Vignesh R <vigneshr@ti.com> >> Tested-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com> >> Tested-by: Stefan Roese <sr@denx.de> >> Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com> >> Reviewed-by: Jagan Teki <jagan@openedev.com> >> Tested-by: Jagan Teki <jagan@amarulasolutions.com> #zynq-microzed > > This patch appears to break the da850_evm board which boots from SPI > Flash and initializes the davinci driver with platdata since the > device tree stuff does not quite work right in SPL. Oops, I did test on K2G EVM that has davinci SPI controller with micron n25q flash but that was with DT. Not sure whats missing with platdata. > > U-Boot SPL 2019.01-02923-gc4e8862308-dirty (Feb 10 2019 - 21:24:38 -0600) > Trying to boot from SPI > SPI probe failed. > SPL: failed to boot from all boot devices > ### ERROR ### Please RESET the board ### Could you enable debug prints at spi-mem level in drivers/spi/spi-mem.c (especially debug prints at the end of spi_mem_exec_op()) and post the logs here? > > Any suggestions on how to fix the SPI initialization without needing > the device tree? I have tried to port the device tree stuff to SPL, > but I haven't yet been successful so I have had to leave the platdata > initialization in place. > I haven't changed any driver names so, platdata to driver bindings should still be the same. Could you verify if spi_nor_scan() is being called in drivers/mtd/spi/spi-nor-tiny.c for SPL? Sorry for the trouble. Regards Vignesh
On Sun, Feb 10, 2019 at 10:37 PM Vignesh R <vigneshr@ti.com> wrote: > > > > On 11/02/19 9:01 AM, Adam Ford wrote: > > On Tue, Feb 5, 2019 at 12:00 AM Vignesh R <vigneshr@ti.com> wrote: > >> > >> Switch spi_flash_* interfaces to call into new SPI NOR framework via MTD > >> layer. Fix up sf_dataflash to work in legacy way. And update sandbox to > >> use new interfaces/definitions > >> > >> Signed-off-by: Vignesh R <vigneshr@ti.com> > >> Tested-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com> > >> Tested-by: Stefan Roese <sr@denx.de> > >> Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com> > >> Reviewed-by: Jagan Teki <jagan@openedev.com> > >> Tested-by: Jagan Teki <jagan@amarulasolutions.com> #zynq-microzed > > > > This patch appears to break the da850_evm board which boots from SPI > > Flash and initializes the davinci driver with platdata since the > > device tree stuff does not quite work right in SPL. > > Oops, I did test on K2G EVM that has davinci SPI controller with micron > n25q flash but that was with DT. Not sure whats missing with platdata. > > > > > U-Boot SPL 2019.01-02923-gc4e8862308-dirty (Feb 10 2019 - 21:24:38 -0600) > > Trying to boot from SPI > > SPI probe failed. > > SPL: failed to boot from all boot devices > > ### ERROR ### Please RESET the board ### > > Could you enable debug prints at spi-mem level in drivers/spi/spi-mem.c > (especially debug prints at the end of spi_mem_exec_op()) and post the > logs here? > > > > > Any suggestions on how to fix the SPI initialization without needing > > the device tree? I have tried to port the device tree stuff to SPL, > > but I haven't yet been successful so I have had to leave the platdata > > initialization in place. > > > > I haven't changed any driver names so, platdata to driver bindings > should still be the same. Could you verify if spi_nor_scan() is being > called in drivers/mtd/spi/spi-nor-tiny.c for SPL? I globally turned on DEBUG and I have two logs for you: Not working: U-Boot SPL 2019.01-02923-gc4e8862308-dirty (Feb 12 2019 - 13:04:19 -0600) Trying to boot from SPI uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 'davinci_spi' - not found spi_get_bus_and_cs: Binding new device 'spi_flash', busnum=0, cs=0, driver=spi_flash_std spi_get_bus_and_cs: Error path, created=1, device 'spi_flash' SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### As a point of reference , I thought I'd show WORKING version (before this patch): U-Boot SPL 2019.01-02922-g2ee6705be0-dirty (Feb 12 2019 - 12:59:49 -0600) Trying to boot from SPI uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 'davinci_spi' - not found spi_get_bus_and_cs: Binding new device 'spi_flash', busnum=0, cs=0, driver=spi_flash_std uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 'spi_flash' - not found spi_flash_std_probe: slave=8001fd60, cs=0 davinci_spi_set_speed speed 30000000 davinci_spi_set_mode mode 3 davinci_spi_set_speed speed 30000000 davinci_spi_set_mode mode 3 spi_get_bus_and_cs: bus=8001fbf4, slave=8001fd60 SPL: payload image: U-Boot 2019.01-02922-g2ee6705be0 load addr: 0xc107ffc0 size: 405306 Jumping to U-Boot loaded - jumping to U-Boot... image entry point: 0xc1080000 ... During this process, I learned a few things. 1. I am not really using the device tree during SPL like i originally thought and the OF_PLATDATA 2. Getting SPL to support device tree with or without PLATDATA isn't as straightforward as I hoped 3. With the knowledge I learned from item 1, I tried to disabled OF_CONTROL during SPL, but this patch also fails to build since it assumes OF_CONTROL is always enabled. If there are any suggestions you might have, I am willing to try them. adam > > Sorry for the trouble. > > Regards > Vignesh > > > -- > Regards > Vignesh
On Tue, Feb 12, 2019 at 1:20 PM Adam Ford <aford173@gmail.com> wrote: > > On Sun, Feb 10, 2019 at 10:37 PM Vignesh R <vigneshr@ti.com> wrote: > > > > > > > > On 11/02/19 9:01 AM, Adam Ford wrote: > > > On Tue, Feb 5, 2019 at 12:00 AM Vignesh R <vigneshr@ti.com> wrote: > > >> > > >> Switch spi_flash_* interfaces to call into new SPI NOR framework via MTD > > >> layer. Fix up sf_dataflash to work in legacy way. And update sandbox to > > >> use new interfaces/definitions > > >> > > >> Signed-off-by: Vignesh R <vigneshr@ti.com> > > >> Tested-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com> > > >> Tested-by: Stefan Roese <sr@denx.de> > > >> Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com> > > >> Reviewed-by: Jagan Teki <jagan@openedev.com> > > >> Tested-by: Jagan Teki <jagan@amarulasolutions.com> #zynq-microzed > > > > > > This patch appears to break the da850_evm board which boots from SPI > > > Flash and initializes the davinci driver with platdata since the > > > device tree stuff does not quite work right in SPL. > > > > Oops, I did test on K2G EVM that has davinci SPI controller with micron > > n25q flash but that was with DT. Not sure whats missing with platdata. > > > > > > > > U-Boot SPL 2019.01-02923-gc4e8862308-dirty (Feb 10 2019 - 21:24:38 -0600) > > > Trying to boot from SPI > > > SPI probe failed. > > > SPL: failed to boot from all boot devices > > > ### ERROR ### Please RESET the board ### > > > > Could you enable debug prints at spi-mem level in drivers/spi/spi-mem.c > > (especially debug prints at the end of spi_mem_exec_op()) and post the > > logs here? > > > > > > > > Any suggestions on how to fix the SPI initialization without needing > > > the device tree? I have tried to port the device tree stuff to SPL, > > > but I haven't yet been successful so I have had to leave the platdata > > > initialization in place. > > > > > > > I haven't changed any driver names so, platdata to driver bindings > > should still be the same. Could you verify if spi_nor_scan() is being > > called in drivers/mtd/spi/spi-nor-tiny.c for SPL? > > I globally turned on DEBUG and I have two logs for you: > > Not working: > > U-Boot SPL 2019.01-02923-gc4e8862308-dirty (Feb 12 2019 - 13:04:19 -0600) > Trying to boot from SPI > uclass_find_device_by_seq: 0 -1 > uclass_find_device_by_seq: 0 0 > - -1 -1 'davinci_spi' > - not found > spi_get_bus_and_cs: Binding new device 'spi_flash', busnum=0, cs=0, > driver=spi_flash_std > spi_get_bus_and_cs: Error path, created=1, device 'spi_flash' > SPI probe failed. > SPL: failed to boot from all boot devices > ### ERROR ### Please RESET the board ### > > As a point of reference , I thought I'd show > WORKING version (before this patch): > > U-Boot SPL 2019.01-02922-g2ee6705be0-dirty (Feb 12 2019 - 12:59:49 -0600) > Trying to boot from SPI > uclass_find_device_by_seq: 0 -1 > uclass_find_device_by_seq: 0 0 > - -1 -1 'davinci_spi' > - not found > spi_get_bus_and_cs: Binding new device 'spi_flash', busnum=0, cs=0, > driver=spi_flash_std > uclass_find_device_by_seq: 0 -1 > uclass_find_device_by_seq: 0 0 > - -1 -1 'spi_flash' > - not found > spi_flash_std_probe: slave=8001fd60, cs=0 > davinci_spi_set_speed speed 30000000 > davinci_spi_set_mode mode 3 > davinci_spi_set_speed speed 30000000 > davinci_spi_set_mode mode 3 > spi_get_bus_and_cs: bus=8001fbf4, slave=8001fd60 > SPL: payload image: U-Boot 2019.01-02922-g2ee6705be0 load addr: > 0xc107ffc0 size: 405306 > Jumping to U-Boot > loaded - jumping to U-Boot... > image entry point: 0xc1080000 > ... > > During this process, I learned a few things. > 1. I am not really using the device tree during SPL like i originally > thought and the OF_PLATDATA > 2. Getting SPL to support device tree with or without PLATDATA isn't > as straightforward as I hoped > 3. With the knowledge I learned from item 1, I tried to disabled > OF_CONTROL during SPL, but this patch also fails to build since it > assumes OF_CONTROL is always enabled. > > If there are any suggestions you might have, I am willing to try them. > I beleive I have narrowed it down a bit to a chunk of code (int device_probe(struct udevice *dev)) located in device.c: /* Allocate private data if requested and not reentered */ if (drv->priv_auto_alloc_size && !dev->priv) { dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags); if (!dev->priv) { printf("Allocate private data if requested and not reentered\n"); ret = -ENOMEM; goto fail; } } I am not sure how the sizes are defined and/or allocated adam > adam > > > > > Sorry for the trouble. > > > > Regards > > Vignesh > > > > > > -- > > Regards > > Vignesh
On 13/02/19 1:54 AM, Adam Ford wrote: > On Tue, Feb 12, 2019 at 1:20 PM Adam Ford <aford173@gmail.com> wrote: >> >> On Sun, Feb 10, 2019 at 10:37 PM Vignesh R <vigneshr@ti.com> wrote: >>> >>> >>> >>> On 11/02/19 9:01 AM, Adam Ford wrote: >>>> On Tue, Feb 5, 2019 at 12:00 AM Vignesh R <vigneshr@ti.com> wrote: >>>>> >>>>> Switch spi_flash_* interfaces to call into new SPI NOR framework via MTD >>>>> layer. Fix up sf_dataflash to work in legacy way. And update sandbox to >>>>> use new interfaces/definitions >>>>> >>>>> Signed-off-by: Vignesh R <vigneshr@ti.com> >>>>> Tested-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com> >>>>> Tested-by: Stefan Roese <sr@denx.de> >>>>> Tested-by: Horatiu Vultur <horatiu.vultur@microchip.com> >>>>> Reviewed-by: Jagan Teki <jagan@openedev.com> >>>>> Tested-by: Jagan Teki <jagan@amarulasolutions.com> #zynq-microzed >>>> >>>> This patch appears to break the da850_evm board which boots from SPI >>>> Flash and initializes the davinci driver with platdata since the >>>> device tree stuff does not quite work right in SPL. >>> >>> Oops, I did test on K2G EVM that has davinci SPI controller with micron >>> n25q flash but that was with DT. Not sure whats missing with platdata. >>> >>>> >>>> U-Boot SPL 2019.01-02923-gc4e8862308-dirty (Feb 10 2019 - 21:24:38 -0600) >>>> Trying to boot from SPI >>>> SPI probe failed. >>>> SPL: failed to boot from all boot devices >>>> ### ERROR ### Please RESET the board ### >>> >>> Could you enable debug prints at spi-mem level in drivers/spi/spi-mem.c >>> (especially debug prints at the end of spi_mem_exec_op()) and post the >>> logs here? >>> >>>> >>>> Any suggestions on how to fix the SPI initialization without needing >>>> the device tree? I have tried to port the device tree stuff to SPL, >>>> but I haven't yet been successful so I have had to leave the platdata >>>> initialization in place. >>>> >>> >>> I haven't changed any driver names so, platdata to driver bindings >>> should still be the same. Could you verify if spi_nor_scan() is being >>> called in drivers/mtd/spi/spi-nor-tiny.c for SPL? >> >> I globally turned on DEBUG and I have two logs for you: >> >> Not working: >> >> U-Boot SPL 2019.01-02923-gc4e8862308-dirty (Feb 12 2019 - 13:04:19 -0600) >> Trying to boot from SPI >> uclass_find_device_by_seq: 0 -1 >> uclass_find_device_by_seq: 0 0 >> - -1 -1 'davinci_spi' >> - not found >> spi_get_bus_and_cs: Binding new device 'spi_flash', busnum=0, cs=0, >> driver=spi_flash_std >> spi_get_bus_and_cs: Error path, created=1, device 'spi_flash' >> SPI probe failed. >> SPL: failed to boot from all boot devices >> ### ERROR ### Please RESET the board ### >> >> As a point of reference , I thought I'd show >> WORKING version (before this patch): >> >> U-Boot SPL 2019.01-02922-g2ee6705be0-dirty (Feb 12 2019 - 12:59:49 -0600) >> Trying to boot from SPI >> uclass_find_device_by_seq: 0 -1 >> uclass_find_device_by_seq: 0 0 >> - -1 -1 'davinci_spi' >> - not found >> spi_get_bus_and_cs: Binding new device 'spi_flash', busnum=0, cs=0, >> driver=spi_flash_std >> uclass_find_device_by_seq: 0 -1 >> uclass_find_device_by_seq: 0 0 >> - -1 -1 'spi_flash' >> - not found >> spi_flash_std_probe: slave=8001fd60, cs=0 >> davinci_spi_set_speed speed 30000000 >> davinci_spi_set_mode mode 3 >> davinci_spi_set_speed speed 30000000 >> davinci_spi_set_mode mode 3 >> spi_get_bus_and_cs: bus=8001fbf4, slave=8001fd60 >> SPL: payload image: U-Boot 2019.01-02922-g2ee6705be0 load addr: >> 0xc107ffc0 size: 405306 >> Jumping to U-Boot >> loaded - jumping to U-Boot... >> image entry point: 0xc1080000 >> ... >> >> During this process, I learned a few things. >> 1. I am not really using the device tree during SPL like i originally >> thought and the OF_PLATDATA >> 2. Getting SPL to support device tree with or without PLATDATA isn't >> as straightforward as I hoped >> 3. With the knowledge I learned from item 1, I tried to disabled >> OF_CONTROL during SPL, but this patch also fails to build since it >> assumes OF_CONTROL is always enabled. >> >> If there are any suggestions you might have, I am willing to try them. >> > > I beleive I have narrowed it down a bit to a chunk of code (int > device_probe(struct udevice *dev)) located in device.c: > > /* Allocate private data if requested and not reentered */ > if (drv->priv_auto_alloc_size && !dev->priv) { > dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags); > if (!dev->priv) { > printf("Allocate private data if requested and not reentered\n"); > ret = -ENOMEM; > goto fail; > } > } > > I am not sure how the sizes are defined and/or allocated priv_auto_alloc_size is determined by: drivers/mtd/spi/sf_probe.c:180: .priv_auto_alloc_size = sizeof(struct spi_flash), Allocation is done at: ./drivers/core/device.c::alloc_priv() If you are seeing -ENOMEM, it looks calloc() maybe failing in above function. Could you increase available size of malloc in SPL to a higher value. I believe you are using da850evm_defconfig. If so, could you change CONFIG_SPL_SYS_MALLOC_F_LEN=0x800 or higher and see if that helps? Regards Vignesh
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 4ba95d58b371..e3b40fc157d6 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -27,6 +27,8 @@ config SPI_FLASH_SANDBOX config SPI_FLASH bool "Legacy SPI Flash Interface support" + depends on SPI + select SPI_MEM help Enable the legacy SPI flash support. This will include basic standard support for things like probing, read / write, and diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index b4c7e1c98bd5..70058d3df2b9 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -9,7 +9,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o endif -obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o spi_flash_ids.o sf.o -obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o +obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi-nor-core.o +obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o sf.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c index 7b9891cb981c..084c66e9840b 100644 --- a/drivers/mtd/spi/sandbox.c +++ b/drivers/mtd/spi/sandbox.c @@ -92,7 +92,7 @@ struct sandbox_spi_flash { /* The current flash status (see STAT_XXX defines above) */ u16 status; /* Data describing the flash we're emulating */ - const struct spi_flash_info *data; + const struct flash_info *data; /* The file on disk to serv up data from */ int fd; }; @@ -122,7 +122,7 @@ static int sandbox_sf_probe(struct udevice *dev) /* spec = idcode:file */ struct sandbox_spi_flash *sbsf = dev_get_priv(dev); size_t len, idname_len; - const struct spi_flash_info *data; + const struct flash_info *data; struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); struct sandbox_state *state = state_get_current(); struct dm_spi_slave_platdata *slave_plat; @@ -155,7 +155,7 @@ static int sandbox_sf_probe(struct udevice *dev) idname_len = strlen(spec); debug("%s: device='%s'\n", __func__, spec); - for (data = spi_flash_ids; data->name; data++) { + for (data = spi_nor_ids; data->name; data++) { len = strlen(data->name); if (idname_len != len) continue; @@ -243,43 +243,43 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, sbsf->cmd = rx[0]; switch (sbsf->cmd) { - case CMD_READ_ID: + case SPINOR_OP_RDID: sbsf->state = SF_ID; sbsf->cmd = SF_ID; break; - case CMD_READ_ARRAY_FAST: + case SPINOR_OP_READ_FAST: sbsf->pad_addr_bytes = 1; - case CMD_READ_ARRAY_SLOW: - case CMD_PAGE_PROGRAM: + case SPINOR_OP_READ: + case SPINOR_OP_PP: sbsf->state = SF_ADDR; break; - case CMD_WRITE_DISABLE: + case SPINOR_OP_WRDI: debug(" write disabled\n"); sbsf->status &= ~STAT_WEL; break; - case CMD_READ_STATUS: + case SPINOR_OP_RDSR: sbsf->state = SF_READ_STATUS; break; - case CMD_READ_STATUS1: + case SPINOR_OP_RDSR2: sbsf->state = SF_READ_STATUS1; break; - case CMD_WRITE_ENABLE: + case SPINOR_OP_WREN: debug(" write enabled\n"); sbsf->status |= STAT_WEL; break; - case CMD_WRITE_STATUS: + case SPINOR_OP_WRSR: sbsf->state = SF_WRITE_STATUS; break; default: { int flags = sbsf->data->flags; /* we only support erase here */ - if (sbsf->cmd == CMD_ERASE_CHIP) { + if (sbsf->cmd == SPINOR_OP_CHIP_ERASE) { sbsf->erase_size = sbsf->data->sector_size * sbsf->data->n_sectors; - } else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { + } else if (sbsf->cmd == SPINOR_OP_BE_4K && (flags & SECT_4K)) { sbsf->erase_size = 4 << 10; - } else if (sbsf->cmd == CMD_ERASE_64K && !(flags & SECT_4K)) { + } else if (sbsf->cmd == SPINOR_OP_SE && !(flags & SECT_4K)) { sbsf->erase_size = 64 << 10; } else { debug(" cmd unknown: %#x\n", sbsf->cmd); @@ -380,11 +380,11 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, return -EIO; } switch (sbsf->cmd) { - case CMD_READ_ARRAY_FAST: - case CMD_READ_ARRAY_SLOW: + case SPINOR_OP_READ_FAST: + case SPINOR_OP_READ: sbsf->state = SF_READ; break; - case CMD_PAGE_PROGRAM: + case SPINOR_OP_PP: sbsf->state = SF_WRITE; break; default: diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c index 4a60c1b2b43a..b6a2631747a9 100644 --- a/drivers/mtd/spi/sf_dataflash.c +++ b/drivers/mtd/spi/sf_dataflash.c @@ -18,6 +18,7 @@ #include "sf_internal.h" +#define CMD_READ_ID 0x9f /* reads can bypass the buffers */ #define OP_READ_CONTINUOUS 0xE8 #define OP_READ_PAGE 0xD2 @@ -441,7 +442,7 @@ static int add_dataflash(struct udevice *dev, char *name, int nr_pages, return 0; } -struct flash_info { +struct data_flash_info { char *name; /* @@ -460,7 +461,7 @@ struct flash_info { #define IS_POW2PS 0x0001 /* uses 2^N byte pages */ }; -static struct flash_info dataflash_data[] = { +static struct data_flash_info dataflash_data[] = { /* * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, * one with IS_POW2PS and the other without. The entry with the @@ -501,12 +502,12 @@ static struct flash_info dataflash_data[] = { { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, }; -static struct flash_info *jedec_probe(struct spi_slave *spi) +static struct data_flash_info *jedec_probe(struct spi_slave *spi) { int tmp; uint8_t id[5]; uint32_t jedec; - struct flash_info *info; + struct data_flash_info *info; int status; /* @@ -583,7 +584,7 @@ static int spi_dataflash_probe(struct udevice *dev) { struct spi_slave *spi = dev_get_parent_priv(dev); struct spi_flash *spi_flash; - struct flash_info *info; + struct data_flash_info *info; int status; spi_flash = dev_get_uclass_priv(dev); diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 46a504441751..fd00e0d1b23b 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -12,142 +12,63 @@ #include <linux/types.h> #include <linux/compiler.h> -/* Dual SPI flash memories - see SPI_COMM_DUAL_... */ -enum spi_dual_flash { - SF_SINGLE_FLASH = 0, - SF_DUAL_STACKED_FLASH = BIT(0), - SF_DUAL_PARALLEL_FLASH = BIT(1), -}; - -enum spi_nor_option_flags { - SNOR_F_SST_WR = BIT(0), - SNOR_F_USE_FSR = BIT(1), - SNOR_F_USE_UPAGE = BIT(3), -}; - -#define SPI_FLASH_3B_ADDR_LEN 3 -#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) -#define SPI_FLASH_16MB_BOUN 0x1000000 - -/* CFI Manufacture ID's */ -#define SPI_FLASH_CFI_MFR_SPANSION 0x01 -#define SPI_FLASH_CFI_MFR_STMICRO 0x20 -#define SPI_FLASH_CFI_MFR_MICRON 0x2C -#define SPI_FLASH_CFI_MFR_MACRONIX 0xc2 -#define SPI_FLASH_CFI_MFR_SST 0xbf -#define SPI_FLASH_CFI_MFR_WINBOND 0xef -#define SPI_FLASH_CFI_MFR_ATMEL 0x1f - -/* Erase commands */ -#define CMD_ERASE_4K 0x20 -#define CMD_ERASE_CHIP 0xc7 -#define CMD_ERASE_64K 0xd8 - -/* Write commands */ -#define CMD_WRITE_STATUS 0x01 -#define CMD_PAGE_PROGRAM 0x02 -#define CMD_WRITE_DISABLE 0x04 -#define CMD_WRITE_ENABLE 0x06 -#define CMD_QUAD_PAGE_PROGRAM 0x32 - -/* Read commands */ -#define CMD_READ_ARRAY_SLOW 0x03 -#define CMD_READ_ARRAY_FAST 0x0b -#define CMD_READ_DUAL_OUTPUT_FAST 0x3b -#define CMD_READ_DUAL_IO_FAST 0xbb -#define CMD_READ_QUAD_OUTPUT_FAST 0x6b -#define CMD_READ_QUAD_IO_FAST 0xeb -#define CMD_READ_ID 0x9f -#define CMD_READ_STATUS 0x05 -#define CMD_READ_STATUS1 0x35 -#define CMD_READ_CONFIG 0x35 -#define CMD_FLAG_STATUS 0x70 - -/* Bank addr access commands */ -#ifdef CONFIG_SPI_FLASH_BAR -# define CMD_BANKADDR_BRWR 0x17 -# define CMD_BANKADDR_BRRD 0x16 -# define CMD_EXTNADDR_WREAR 0xC5 -# define CMD_EXTNADDR_RDEAR 0xC8 -#endif - -/* Common status */ -#define STATUS_WIP BIT(0) -#define STATUS_QEB_WINSPAN BIT(1) -#define STATUS_QEB_MXIC BIT(6) -#define STATUS_PEC BIT(7) -#define SR_BP0 BIT(2) /* Block protect 0 */ -#define SR_BP1 BIT(3) /* Block protect 1 */ -#define SR_BP2 BIT(4) /* Block protect 2 */ - -/* Flash timeout values */ -#define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) -#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) -#define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) - -/* SST specific */ -#ifdef CONFIG_SPI_FLASH_SST -#define SST26_CMD_READ_BPR 0x72 -#define SST26_CMD_WRITE_BPR 0x42 - -#define SST26_BPR_8K_NUM 4 -#define SST26_MAX_BPR_REG_LEN (18 + 1) -#define SST26_BOUND_REG_SIZE ((32 + SST26_BPR_8K_NUM * 8) * SZ_1K) - -enum lock_ctl { - SST26_CTL_LOCK, - SST26_CTL_UNLOCK, - SST26_CTL_CHECK -}; - -# define CMD_SST_BP 0x02 /* Byte Program */ -# define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ - -int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf); -int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf); -#endif - -#define JEDEC_MFR(info) ((info)->id[0]) -#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) -#define JEDEC_EXT(info) (((info)->id[3]) << 8 | ((info)->id[4])) -#define SPI_FLASH_MAX_ID_LEN 6 +#define SPI_NOR_MAX_ID_LEN 6 +#define SPI_NOR_MAX_ADDR_WIDTH 4 -struct spi_flash_info { - /* Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) */ - const char *name; +struct flash_info { + char *name; /* * This array stores the ID bytes. * The first three bytes are the JEDIC ID. * JEDEC ID zero means "no ID" (mostly older chips). */ - u8 id[SPI_FLASH_MAX_ID_LEN]; + u8 id[SPI_NOR_MAX_ID_LEN]; u8 id_len; - /* - * The size listed here is what works with SPINOR_OP_SE, which isn't + /* The size listed here is what works with SPINOR_OP_SE, which isn't * necessarily called a "sector" by the vendor. */ - u32 sector_size; - u32 n_sectors; + unsigned int sector_size; + u16 n_sectors; u16 page_size; + u16 addr_width; u16 flags; -#define SECT_4K BIT(0) /* CMD_ERASE_4K works uniformly */ -#define E_FSR BIT(1) /* use flag status register for */ -#define SST_WR BIT(2) /* use SST byte/word programming */ -#define WR_QPP BIT(3) /* use Quad Page Program */ -#define RD_QUAD BIT(4) /* use Quad Read */ -#define RD_DUAL BIT(5) /* use Dual Read */ -#define RD_QUADIO BIT(6) /* use Quad IO Read */ -#define RD_DUALIO BIT(7) /* use Dual IO Read */ -#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) +#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */ +#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */ +#define SST_WRITE BIT(2) /* use SST byte programming */ +#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */ +#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ +#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ +#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ +#define USE_FSR BIT(7) /* use flag status register */ +#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ +#define SPI_NOR_HAS_TB BIT(9) /* + * Flash SR has Top/Bottom (TB) protect + * bit. Must be used with + * SPI_NOR_HAS_LOCK. + */ +#define SPI_S3AN BIT(10) /* + * Xilinx Spartan 3AN In-System Flash + * (MFR cannot be used for probing + * because it has the same value as + * ATMEL flashes) + */ +#define SPI_NOR_4B_OPCODES BIT(11) /* + * Use dedicated 4byte address op codes + * to support memory size above 128Mib. + */ +#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ +#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ +#define USE_CLSR BIT(14) /* use CLSR command */ }; -extern const struct spi_flash_info spi_flash_ids[]; +extern const struct flash_info spi_nor_ids[]; + +#define JEDEC_MFR(info) ((info)->id[0]) +#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) /* Send a single-byte command to the device and read the response */ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); @@ -167,78 +88,12 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, const void *data, size_t data_len); -/* Flash erase(sectors) operation, support all possible erase commands */ -int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); - /* Get software write-protect value (BP bits) */ int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash); -/* Lock stmicro spi flash region */ -int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); - -/* Unlock stmicro spi flash region */ -int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len); - -/* Check if a stmicro spi flash region is completely locked */ -int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len); - -/* Enable writing on the SPI flash */ -static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) -{ - return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); -} - -/* Disable writing on the SPI flash */ -static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) -{ - return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); -} - -/* - * Used for spi_flash write operation - * - SPI claim - * - spi_flash_cmd_write_enable - * - spi_flash_cmd_write - * - spi_flash_wait_till_ready - * - SPI release - */ -int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, - size_t cmd_len, const void *buf, size_t buf_len); - -/* - * Flash write operation, support all possible write commands. - * Write the requested data out breaking it up into multiple write - * commands as needed per the write size. - */ -int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, - size_t len, const void *buf); - -/* - * Same as spi_flash_cmd_read() except it also claims/releases the SPI - * bus. Used as common part of the ->read() operation. - */ -int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, - size_t cmd_len, void *data, size_t data_len); - -/* Flash read operation, support all possible read commands */ -int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, - size_t len, void *data); #ifdef CONFIG_SPI_FLASH_MTD int spi_flash_mtd_register(struct spi_flash *flash); void spi_flash_mtd_unregister(void); #endif - -/** - * spi_flash_scan - scan the SPI FLASH - * @flash: the spi flash structure - * - * The drivers can use this fuction to scan the SPI FLASH. - * In the scanning, it will try to get all the necessary information to - * fill the spi_flash{}. - * - * Return: 0 for success, others for failure. - */ -int spi_flash_scan(struct spi_flash *flash); - #endif /* _SF_INTERNAL_H_ */ diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 7a379914d8f1..7f1378f4946d 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -40,7 +40,7 @@ static int spi_flash_probe_slave(struct spi_flash *flash) return ret; } - ret = spi_flash_scan(flash); + ret = spi_nor_scan(flash); if (ret) goto err_read_id; @@ -96,32 +96,38 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, void *buf) { struct spi_flash *flash = dev_get_uclass_priv(dev); + struct mtd_info *mtd = &flash->mtd; + size_t retlen; - return log_ret(spi_flash_cmd_read_ops(flash, offset, len, buf)); + return log_ret(mtd->_read(mtd, offset, len, &retlen, buf)); } static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, const void *buf) { struct spi_flash *flash = dev_get_uclass_priv(dev); + struct mtd_info *mtd = &flash->mtd; + size_t retlen; -#if defined(CONFIG_SPI_FLASH_SST) - if (flash->flags & SNOR_F_SST_WR) { - if (flash->spi->mode & SPI_TX_BYTE) - 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); + return mtd->_write(mtd, offset, len, &retlen, buf); } static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) { struct spi_flash *flash = dev_get_uclass_priv(dev); + struct mtd_info *mtd = &flash->mtd; + struct erase_info instr; + + if (offset % mtd->erasesize || len % mtd->erasesize) { + printf("SF: Erase offset/length not multiple of erase size\n"); + return -EINVAL; + } + + memset(&instr, 0, sizeof(instr)); + instr.addr = offset; + instr.len = len; - return spi_flash_cmd_erase_ops(flash, offset, len); + return mtd->_erase(mtd, &instr); } static int spi_flash_std_get_sw_write_prot(struct udevice *dev) diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 13c6236d623a..7590ff7716e8 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -21,6 +21,8 @@ #include <spi-mem.h> #include <spi.h> +#include "sf_internal.h" + /* Define max times to check status register before we give up. */ /* @@ -32,63 +34,6 @@ #define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) -#define SPI_NOR_MAX_ID_LEN 6 -#define SPI_NOR_MAX_ADDR_WIDTH 4 - -struct flash_info { - char *name; - - /* - * This array stores the ID bytes. - * The first three bytes are the JEDIC ID. - * JEDEC ID zero means "no ID" (mostly older chips). - */ - u8 id[SPI_NOR_MAX_ID_LEN]; - u8 id_len; - - /* The size listed here is what works with SPINOR_OP_SE, which isn't - * necessarily called a "sector" by the vendor. - */ - unsigned int sector_size; - u16 n_sectors; - - u16 page_size; - u16 addr_width; - - u16 flags; -#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */ -#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */ -#define SST_WRITE BIT(2) /* use SST byte programming */ -#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */ -#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ -#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ -#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ -#define USE_FSR BIT(7) /* use flag status register */ -#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ -#define SPI_NOR_HAS_TB BIT(9) /* - * Flash SR has Top/Bottom (TB) protect - * bit. Must be used with - * SPI_NOR_HAS_LOCK. - */ -#define SPI_S3AN BIT(10) /* - * Xilinx Spartan 3AN In-System Flash - * (MFR cannot be used for probing - * because it has the same value as - * ATMEL flashes) - */ -#define SPI_NOR_4B_OPCODES BIT(11) /* - * Use dedicated 4byte address op codes - * to support memory size above 128Mib. - */ -#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ -#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ -#define USE_CLSR BIT(14) /* use CLSR command */ - - int (*quad_enable)(struct spi_nor *nor); -}; - -#define JEDEC_MFR(info) ((info)->id[0]) - static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op *op, void *buf) { diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c index 3b92254a5ce1..8b60d7c3b224 100644 --- a/drivers/spi/stm32_qspi.c +++ b/drivers/spi/stm32_qspi.c @@ -271,9 +271,9 @@ static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv, { unsigned int ccr_reg; - priv->command = flash->read_cmd | CMD_HAS_ADR | CMD_HAS_DATA + priv->command = flash->read_opcode | CMD_HAS_ADR | CMD_HAS_DATA | CMD_HAS_DUMMY; - priv->dummycycles = flash->dummy_byte * 8; + priv->dummycycles = flash->read_dummy; ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP); diff --git a/include/spi_flash.h b/include/spi_flash.h index e427e960d54f..7f691e8559cd 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -11,6 +11,7 @@ #include <dm.h> /* Because we dereference struct udevice here */ #include <linux/types.h> +#include <linux/mtd/spi-nor.h> #ifndef CONFIG_SF_DEFAULT_SPEED # define CONFIG_SF_DEFAULT_SPEED 1000000 @@ -27,86 +28,6 @@ struct spi_slave; -/** - * struct spi_flash - SPI flash structure - * - * @spi: SPI slave - * @dev: SPI flash device - * @name: Name of SPI flash - * @dual_flash: Indicates dual flash memories - dual stacked, parallel - * @shift: Flash shift useful in dual parallel - * @flags: Indication of spi flash flags - * @size: Total flash size - * @page_size: Write (page) size - * @sector_size: Sector size - * @erase_size: Erase size - * @bank_read_cmd: Bank read cmd - * @bank_write_cmd: Bank write cmd - * @bank_curr: Current flash bank - * @erase_cmd: Erase cmd 4K, 32K, 64K - * @read_cmd: Read cmd - Array Fast, Extn read and quad read. - * @write_cmd: Write cmd - page and quad program. - * @dummy_byte: Dummy cycles for read operation. - * @memory_map: Address of read-only SPI flash access - * @flash_lock: lock a region of the SPI Flash - * @flash_unlock: unlock a region of the SPI Flash - * @flash_is_locked: check if a region of the SPI Flash is completely locked - * @read: Flash read ops: Read len bytes at offset into buf - * Supported cmds: Fast Array Read - * @write: Flash write ops: Write len bytes from buf into offset - * Supported cmds: Page Program - * @erase: Flash erase ops: Erase len bytes from offset - * Supported cmds: Sector erase 4K, 32K, 64K - * return 0 - Success, 1 - Failure - */ -struct spi_flash { - struct spi_slave *spi; -#ifdef CONFIG_DM_SPI_FLASH - struct udevice *dev; -#endif - const char *name; - u8 dual_flash; - u8 shift; - u16 flags; - - u32 size; - u32 page_size; - u32 sector_size; - u32 erase_size; -#ifdef CONFIG_SPI_FLASH_BAR - u8 bank_read_cmd; - u8 bank_write_cmd; - u8 bank_curr; -#endif - u8 erase_cmd; - u8 read_cmd; - u8 write_cmd; - u8 dummy_byte; - - void *memory_map; - - int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); - int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); - int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); -#ifndef CONFIG_DM_SPI_FLASH - /* - * These are not strictly needed for driver model, but keep them here - * 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 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); - int (*write)(struct spi_flash *flash, u32 offset, size_t len, - const void *buf); - int (*erase)(struct spi_flash *flash, u32 offset, size_t len); -#endif -}; - struct dm_spi_flash_ops { int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf); int (*write)(struct udevice *dev, u32 offset, size_t len, @@ -225,19 +146,37 @@ void spi_flash_free(struct spi_flash *flash); static inline int spi_flash_read(struct spi_flash *flash, u32 offset, size_t len, void *buf) { - return flash->read(flash, offset, len, buf); + struct mtd_info *mtd = &flash->mtd; + size_t retlen; + + return mtd->_read(mtd, offset, len, &retlen, buf); } static inline int spi_flash_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { - return flash->write(flash, offset, len, buf); + struct mtd_info *mtd = &flash->mtd; + size_t retlen; + + return mtd->_write(mtd, offset, len, &retlen, buf); } static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, size_t len) { - return flash->erase(flash, offset, len); + struct mtd_info *mtd = &flash->mtd; + struct erase_info instr; + + if (offset % mtd->erasesize || len % mtd->erasesize) { + printf("SF: Erase offset/length not multiple of erase size\n"); + return -EINVAL; + } + + memset(&instr, 0, sizeof(instr)); + instr.addr = offset; + instr.len = len; + + return mtd->_erase(mtd, &instr); } #endif