From patchwork Tue Feb 5 05:59:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Raghavendra, Vignesh" X-Patchwork-Id: 1036452 X-Patchwork-Delegate: jagannadh.teki@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=quarantine dis=none) header.from=ti.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.b="VNj2xNAd"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43tvLZ1LQxz9sMx for ; Tue, 5 Feb 2019 17:09:58 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id D33D1C21E2F; Tue, 5 Feb 2019 06:07:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id E50BDC21F32; Tue, 5 Feb 2019 06:03:08 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D69E8C21F52; Tue, 5 Feb 2019 06:00:15 +0000 (UTC) Received: from lelv0143.ext.ti.com (lelv0143.ext.ti.com [198.47.23.248]) by lists.denx.de (Postfix) with ESMTPS id 721B5C21E63 for ; Tue, 5 Feb 2019 06:00:09 +0000 (UTC) Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id x155xwX8029730; Mon, 4 Feb 2019 23:59:58 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1549346398; bh=Qj3vOQp0rR3s88GEsSvgSSmV3zwS9pDAFLa8tjUZpTk=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=VNj2xNAdilr5t/wulDPvQ4NBt4wHocK1Et1HofcgDu7E3PjQNTHQvCVms91dupTwG wOhxhmLb+eDsa6CCl9IhbfmF+LqLhh5x3Gofdyg55OCkc8WE7S9TvfGkgzJYkt0v7g SzwLPQ3XdUWhfvrBBPV+PZ6iwn+oH9+adgP9Drpo= Received: from DFLE113.ent.ti.com (dfle113.ent.ti.com [10.64.6.34]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x155xw79013919 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 4 Feb 2019 23:59:58 -0600 Received: from DFLE114.ent.ti.com (10.64.6.35) by DFLE113.ent.ti.com (10.64.6.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1591.10; Mon, 4 Feb 2019 23:59:57 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DFLE114.ent.ti.com (10.64.6.35) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1591.10 via Frontend Transport; Mon, 4 Feb 2019 23:59:57 -0600 Received: from a0132425.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id x155wVWH006226; Mon, 4 Feb 2019 23:59:52 -0600 From: Vignesh R To: Jagan Teki Date: Tue, 5 Feb 2019 11:29:23 +0530 Message-ID: <20190205055929.24168-15-vigneshr@ti.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205055929.24168-1-vigneshr@ti.com> References: <20190205055929.24168-1-vigneshr@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Cc: Marek Vasut , Tom Rini , Stefan Roese , Nobuhiro Iwamatsu , Boris Brezillon , Michal Simek , u-boot@lists.denx.de, Rajat Srivastava , Miquel Raynal Subject: [U-Boot] [PATCH v4 14/20] mtd: spi: Switch to new SPI NOR framework X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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 Tested-by: Simon Goldschmidt Tested-by: Stefan Roese Tested-by: Horatiu Vultur Reviewed-by: Jagan Teki Tested-by: Jagan Teki #zynq-microzed --- 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 #include -/* 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 #include +#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 /* Because we dereference struct udevice here */ #include +#include #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