All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jagan Teki <jteki@openedev.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 01/10] sf: Add spi_flash_ids local to core
Date: Thu, 31 Dec 2015 14:51:56 +0530	[thread overview]
Message-ID: <1451553724-1098-2-git-send-email-jteki@openedev.com> (raw)
In-Reply-To: <1451553724-1098-1-git-send-email-jteki@openedev.com>

This patch add's spi_flash_ids handling into core, instead
of maintaining it into separate file like sf_params.c

Code taken from the Linux spi-nor core and added missing
part id's and also added extra flash_info member as e_rd_cmd
for computing fastest read command.

Cc: Simon Glass <sjg@chromium.org>
Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Michal Simek <michal.simek@xilinx.com>
Cc: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
Tested-by: Mugunthan V N <mugunthanvnm@ti.com>
Tested-by: Jagan Teki <jteki@openedev.com>
Signed-off-by: Jagan Teki <jteki@openedev.com>
---
 drivers/mtd/spi/spi_flash.c | 431 +++++++++++++++++++++++++++++++++++++-------
 include/linux/err.h         |   5 +
 2 files changed, 370 insertions(+), 66 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index e92f729..2c309e7 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -21,6 +21,45 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define SPI_NOR_MAX_ID_LEN	6
+
+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	sector_size;
+	u16		n_sectors;
+
+	u16		page_size;
+	u16		addr_width;
+
+	/* Enum list for read commands */
+	enum spi_read_cmds e_rd_cmd;
+
+	u16		flags;
+#define	SECT_4K			0x01	/* SPINOR_OP_BE_4K works uniformly */
+#define	SPI_NOR_NO_ERASE	0x02	/* No erase command needed */
+#define	SST_WRITE		0x04	/* use SST byte programming */
+#define	SPI_NOR_NO_FR		0x08	/* Can't do fastread */
+#define	SECT_4K_PMC		0x10	/* SPINOR_OP_BE_4K_PMC works uniformly */
+#define	SPI_NOR_DUAL_READ	0x20    /* Flash supports Dual Read */
+#define	SPI_NOR_QUAD_READ	0x40    /* Flash supports Quad Read */
+#define	USE_FSR			0x80	/* use flag status register */
+};
+#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]))
+
 static void spi_flash_addr(u32 addr, u8 *cmd)
 {
 	/* cmd[0] is actual command */
@@ -164,7 +203,8 @@ bar_end:
 	return flash->bank_curr;
 }
 
-static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0)
+static int spi_flash_read_bar(struct spi_flash *flash,
+				const struct flash_info *info)
 {
 	u8 curr_bank = 0;
 	int ret;
@@ -172,7 +212,7 @@ static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0)
 	if (flash->size <= SPI_FLASH_16MB_BOUN)
 		goto bar_end;
 
-	switch (idcode0) {
+	switch (JEDEC_MFR(info)) {
 	case SPI_FLASH_CFI_MFR_SPANSION:
 		flash->bank_read_cmd = CMD_BANKADDR_BRRD;
 		flash->bank_write_cmd = CMD_BANKADDR_BRWR;
@@ -829,6 +869,296 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len)
 }
 #endif
 
+/* Used when the "_ext_id" is two bytes at most */
+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _e_rd_cmd, _flags)	\
+		.id = {							\
+			((_jedec_id) >> 16) & 0xff,			\
+			((_jedec_id) >> 8) & 0xff,			\
+			(_jedec_id) & 0xff,				\
+			((_ext_id) >> 8) & 0xff,			\
+			(_ext_id) & 0xff,				\
+			},						\
+		.id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),	\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = 256,					\
+		.e_rd_cmd = _e_rd_cmd,					\
+		.flags = (_flags),
+
+#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _e_rd_cmd, _flags)	\
+		.id = {							\
+			((_jedec_id) >> 16) & 0xff,			\
+			((_jedec_id) >> 8) & 0xff,			\
+			(_jedec_id) & 0xff,				\
+			((_ext_id) >> 16) & 0xff,			\
+			((_ext_id) >> 8) & 0xff,			\
+			(_ext_id) & 0xff,				\
+			},						\
+		.id_len = 6,						\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = 256,					\
+		.e_rd_cmd = _e_rd_cmd,					\
+		.flags = (_flags),
+
+#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _e_rd_cmd, _flags)	\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = (_page_size),				\
+		.addr_width = (_addr_width),				\
+		.e_rd_cmd = _e_rd_cmd,					\
+		.flags = (_flags),
+
+/* NOTE: double check command sets and memory organization when you add
+ * more nor chips.  This current list focusses on newer chips, which
+ * have been converging on command sets which including JEDEC ID.
+ *
+ * All newly added entries should describe *hardware* and should use SECT_4K
+ * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage
+ * scenarios excluding small sectors there is config option that can be
+ * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS.
+ * For historical (and compatibility) reasons (before we got above config) some
+ * old entries may be missing 4K flag.
+ */
+static const struct flash_info spi_flash_ids[] = {
+#ifdef CONFIG_SPI_FLASH_ATMEL		/* ATMEL */
+	/* Atmel -- some are (confusingly) marketed as "DataFlash" */
+	{ "at25fs010",  INFO(0x1f6601, 0, 32 * 1024,   4, RD_NORM, SECT_4K) },
+	{ "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, RD_NORM, SECT_4K) },
+
+	{ "at25df041a", INFO(0x1f4401, 0, 64 * 1024,   8, RD_NORM, SECT_4K) },
+	{ "at25df321a", INFO(0x1f4701, 0, 64 * 1024,  64, RD_NORM, SECT_4K) },
+	{ "at25df641",  INFO(0x1f4800, 0, 64 * 1024, 128, RD_NORM, SECT_4K) },
+
+	{ "at26f004",   INFO(0x1f0400, 0, 64 * 1024,  8, RD_NORM, SECT_4K) },
+	{ "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, RD_NORM, SECT_4K) },
+	{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, RD_NORM, SECT_4K) },
+	{ "at26df321",  INFO(0x1f4700, 0, 64 * 1024, 64, RD_NORM, SECT_4K) },
+
+	{ "at45db011d",	INFO(0x1f2200, 0, 64 * 1024,   4, RD_NORM, SECT_4K) },
+	{ "at45db021d",	INFO(0x1f2300, 0, 64 * 1024,   8, RD_NORM, SECT_4K) },
+	{ "at45db041d",	INFO(0x1f2400, 0, 64 * 1024,   8, RD_NORM, SECT_4K) },
+	{ "at45db081d",	INFO(0x1f2500, 0, 64 * 1024,  16, RD_NORM, SECT_4K) },
+	{ "at45db161d",	INFO(0x1f2600, 0, 64 * 1024,  32, RD_NORM, SECT_4K) },
+	{ "at45db321d",	INFO(0x1f2700, 0, 64 * 1024,  64, RD_NORM, SECT_4K) },
+	{ "at45db641d",	INFO(0x1f2800, 0, 64 * 1024, 128, RD_NORM, SECT_4K) },
+#endif
+#ifdef CONFIG_SPI_FLASH_EON		/* EON */
+	/* EON -- en25xxx */
+	{ "en25f32",    INFO(0x1c3116, 0, 64 * 1024,   64, RD_NORM, SECT_4K) },
+	{ "en25p32",    INFO(0x1c2016, 0, 64 * 1024,   64, RD_NORM, 0) },
+	{ "en25q32b",   INFO(0x1c3016, 0, 64 * 1024,   64, RD_NORM, 0) },
+	{ "en25p64",    INFO(0x1c2017, 0, 64 * 1024,  128, RD_NORM, 0) },
+	{ "en25q64",    INFO(0x1c3017, 0, 64 * 1024,  128, RD_NORM, SECT_4K) },
+	{ "en25q128b",	INFO(0x1c3018, 0, 64 * 1024,  256, RD_NORM, 0) },
+	{ "en25qh128",  INFO(0x1c7018, 0, 64 * 1024,  256, RD_NORM, 0) },
+	{ "en25qh256",  INFO(0x1c7019, 0, 64 * 1024,  512, RD_NORM, 0) },
+	{ "en25s64",	INFO(0x1c3817, 0, 64 * 1024,  128, RD_NORM, SECT_4K) },
+#endif
+	/* ESMT */
+	{ "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, RD_NORM, SECT_4K) },
+
+	/* Everspin */
+	{ "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, RD_NORM, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "mr25h10",  CAT25_INFO(128 * 1024, 1, 256, 3, RD_NORM, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+
+	/* Fujitsu */
+	{ "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, RD_NORM, SPI_NOR_NO_ERASE) },
+
+#ifdef CONFIG_SPI_FLASH_GIGADEVICE	/* GIGADEVICE */
+	/* GigaDevice */
+	{ "gd25q32", INFO(0xc84016, 0, 64 * 1024,  64, RD_NORM, SECT_4K) },
+	{ "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, RD_NORM, SECT_4K) },
+	{ "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, RD_NORM, SECT_4K) },
+	{ "gd25lq32", INFO(0xc86016, 0,	64 * 1024,  64, RD_NORM, SECT_4K) },
+#endif
+	/* Intel/Numonyx -- xxxs33b */
+	{ "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, RD_NORM, 0) },
+	{ "320s33b",  INFO(0x898912, 0, 64 * 1024,  64, RD_NORM, 0) },
+	{ "640s33b",  INFO(0x898913, 0, 64 * 1024, 128, RD_NORM, 0) },
+
+#ifdef CONFIG_SPI_FLASH_ISSI		/* ISSI */
+	/* ISSI */
+	{ "is25cd512", INFO(0x7f9d20, 0, 32 * 1024,   2, RD_NORM, SECT_4K) },
+	{ "is25lp032", INFO(0x9d6016, 0, 64 * 1024,  64, RD_NORM, 0) },
+	{ "is25lp064", INFO(0x9d6017, 0, 64 * 1024, 128, RD_NORM, 0) },
+	{ "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, RD_NORM, 0) },
+#endif
+#ifdef CONFIG_SPI_FLASH_MACRONIX	/* MACRONIX */
+	/* Macronix */
+	{ "mx25l512e",   INFO(0xc22010, 0, 64 * 1024,   1, RD_NORM, SECT_4K) },
+	{ "mx25l2005a",  INFO(0xc22012, 0, 64 * 1024,   4, RD_NORM, SECT_4K) },
+	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, RD_NORM, SECT_4K) },
+	{ "mx25l8005",   INFO(0xc22014, 0, 64 * 1024,  16, RD_NORM, 0) },
+	{ "mx25l1606e",  INFO(0xc22015, 0, 64 * 1024,  32, RD_NORM, SECT_4K) },
+	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, RD_NORM, 0) },
+	{ "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, RD_NORM, SECT_4K) },
+	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, RD_NORM, 0) },
+	{ "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, RD_NORM, SECT_4K) },
+	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, RD_FULL, WR_QPP) },
+	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, RD_FULL, WR_QPP) },
+	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, RD_FULL, WR_QPP) },
+	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, RD_FULL, WR_QPP) },
+	{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, RD_FULL, WR_QPP | SPI_NOR_QUAD_READ) },
+	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, RD_FULL, WR_QPP | SPI_NOR_QUAD_READ) },
+#endif
+#ifdef CONFIG_SPI_FLASH_STMICRO		/* STMICRO */
+	/* Micron */
+	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64, RD_FULL, WR_QPP | SPI_NOR_QUAD_READ) },
+	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, RD_FULL, WR_QPP | SECT_4K | SPI_NOR_QUAD_READ) },
+	{ "n25q064a",    INFO(0x20bb17, 0, 64 * 1024,  128, RD_FULL, WR_QPP | SECT_4K | SPI_NOR_QUAD_READ) },
+	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, RD_FULL, WR_QPP | SPI_NOR_QUAD_READ) },
+	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, RD_FULL, WR_QPP | SPI_NOR_QUAD_READ) },
+	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, RD_FULL, WR_QPP | SECT_4K | SPI_NOR_QUAD_READ) },
+	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, RD_FULL, WR_QPP | SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, RD_FULL, WR_QPP | SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, RD_FULL, WR_QPP | SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+#endif
+	/* PMC */
+	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2, RD_NORM, SECT_4K_PMC) },
+	{ "pm25lv010",   INFO(0,        0, 32 * 1024,    4, RD_NORM, SECT_4K_PMC) },
+	{ "pm25lq032",   INFO(0x7f9d46, 0, 64 * 1024,   64, RD_NORM, SECT_4K) },
+
+#ifdef CONFIG_SPI_FLASH_SPANSION	/* SPANSION */
+	/* Spansion -- single (large) sector size only, at least
+	 * for the chips listed here (without boot sectors).
+	 */
+	{ "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, RD_FULL, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, RD_FULL, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, RD_FULL, WR_QPP) },
+	{ "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, RD_FULL, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, RD_FULL, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25fl512s1", INFO(0x010220, 0x4d01,  64 * 1024, 1024, RD_FULL, WR_QPP) },
+	{ "s25fl512s2", INFO(0x010220, 0x4f00, 256 * 1024, 256, RD_FULL, WR_QPP) },
+	{ "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, RD_FULL, WR_QPP) },
+	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, RD_FULL, WR_QPP) },
+	{ "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, RD_FULL, WR_QPP) },
+	{ "s25fl128s",	INFO6(0x012018, 0x4d0180, 64 * 1024, 256, RD_FULL, WR_QPP | SPI_NOR_QUAD_READ) },
+	{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, RD_FULL, WR_QPP | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, RD_FULL, WR_QPP | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8, RD_NORM, 0) },
+	{ "s25sl008a",  INFO(0x010213,      0,  64 * 1024,  16, RD_NORM, 0) },
+	{ "s25sl016a",  INFO(0x010214,      0,  64 * 1024,  32, RD_NORM, 0) },
+	{ "s25sl032a",  INFO(0x010215,      0,  64 * 1024,  64, RD_NORM, 0) },
+	{ "s25sl064a",  INFO(0x010216,      0,  64 * 1024, 128, RD_NORM, 0) },
+	{ "s25fl008k",  INFO(0xef4014,      0,  64 * 1024,  16, RD_NORM, SECT_4K) },
+	{ "s25fl016k",  INFO(0xef4015,      0,  64 * 1024,  32, RD_NORM, SECT_4K) },
+	{ "s25fl064k",  INFO(0xef4017,      0,  64 * 1024, 128, RD_NORM, SECT_4K) },
+	{ "s25fl132k",  INFO(0x014016,      0,  64 * 1024,  64, RD_NORM, SECT_4K) },
+	{ "s25fl164k",  INFO(0x014017,      0,  64 * 1024, 128, RD_NORM, SECT_4K) },
+	{ "s25fl204k",  INFO(0x014013,      0,  64 * 1024,   8, RD_NORM, SECT_4K) },
+#endif
+#ifdef CONFIG_SPI_FLASH_SST		/* SST */
+	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
+	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8, RD_NORM, SECT_4K | SST_WRITE) },
+	{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WRITE) },
+	{ "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, RD_NORM, SECT_4K | SST_WRITE) },
+	{ "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, RD_NORM, SECT_4K | SST_WRITE) },
+	{ "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, RD_NORM, SECT_4K) },
+	{ "sst25wf512",  INFO(0xbf2501, 0, 64 * 1024,  1, RD_NORM, SECT_4K | SST_WRITE) },
+	{ "sst25wf010",  INFO(0xbf2502, 0, 64 * 1024,  2, RD_NORM, SECT_4K | SST_WRITE) },
+	{ "sst25wf020",  INFO(0xbf2503, 0, 64 * 1024,  4, RD_NORM, SECT_4K | SST_WRITE) },
+	{ "sst25wf040",	 INFO(0xbf2504, 0, 64 * 1024,  8, RD_NORM, SECT_4K | SST_WRITE) },
+	{ "sst25wf020a", INFO(0x621612, 0, 64 * 1024,  4, RD_NORM, SECT_4K) },
+	{ "sst25wf040b", INFO(0x621613, 0, 64 * 1024,  8, RD_NORM, SECT_4K) },
+	{ "sst25wf040",  INFO(0xbf2504, 0, 64 * 1024,  8, RD_NORM, SECT_4K | SST_WRITE) },
+	{ "sst25wf080",  INFO(0xbf2505, 0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WRITE) },
+#endif
+#ifdef CONFIG_SPI_FLASH_STMICRO		/* STMICRO */
+	/* ST Microelectronics -- newer production may have feature updates */
+	{ "m25p05",  INFO(0x202010,  0,  32 * 1024,   2, RD_NORM, 0) },
+	{ "m25p10",  INFO(0x202011,  0,  32 * 1024,   4, RD_NORM, 0) },
+	{ "m25p20",  INFO(0x202012,  0,  64 * 1024,   4, RD_NORM, 0) },
+	{ "m25p40",  INFO(0x202013,  0,  64 * 1024,   8, RD_NORM, 0) },
+	{ "m25p80",  INFO(0x202014,  0,  64 * 1024,  16, RD_NORM, 0) },
+	{ "m25p16",  INFO(0x202015,  0,  64 * 1024,  32, RD_NORM, 0) },
+	{ "m25p32",  INFO(0x202016,  0,  64 * 1024,  64, RD_NORM, 0) },
+	{ "m25p64",  INFO(0x202017,  0,  64 * 1024, 128, RD_NORM, 0) },
+	{ "m25p128", INFO(0x202018,  0, 256 * 1024,  64, RD_NORM, 0) },
+
+	{ "m25p05-nonjedec",  INFO(0, 0,  32 * 1024,   2, RD_NORM, 0) },
+	{ "m25p10-nonjedec",  INFO(0, 0,  32 * 1024,   4, RD_NORM, 0) },
+	{ "m25p20-nonjedec",  INFO(0, 0,  64 * 1024,   4, RD_NORM, 0) },
+	{ "m25p40-nonjedec",  INFO(0, 0,  64 * 1024,   8, RD_NORM, 0) },
+	{ "m25p80-nonjedec",  INFO(0, 0,  64 * 1024,  16, RD_NORM, 0) },
+	{ "m25p16-nonjedec",  INFO(0, 0,  64 * 1024,  32, RD_NORM, 0) },
+	{ "m25p32-nonjedec",  INFO(0, 0,  64 * 1024,  64, RD_NORM, 0) },
+	{ "m25p64-nonjedec",  INFO(0, 0,  64 * 1024, 128, RD_NORM, 0) },
+	{ "m25p128-nonjedec", INFO(0, 0, 256 * 1024,  64, RD_NORM, 0) },
+
+	{ "m45pe10", INFO(0x204011,  0, 64 * 1024,    2, RD_NORM, 0) },
+	{ "m45pe80", INFO(0x204014,  0, 64 * 1024,   16, RD_NORM, 0) },
+	{ "m45pe16", INFO(0x204015,  0, 64 * 1024,   32, RD_NORM, 0) },
+
+	{ "m25pe20", INFO(0x208012,  0, 64 * 1024,  4, RD_NORM, 0) },
+	{ "m25pe80", INFO(0x208014,  0, 64 * 1024, 16, RD_NORM, 0) },
+	{ "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, RD_NORM, SECT_4K) },
+
+	{ "m25px16",    INFO(0x207115,  0, 64 * 1024, 32, RD_NORM, SECT_4K) },
+	{ "m25px32",    INFO(0x207116,  0, 64 * 1024, 64, RD_NORM, SECT_4K) },
+	{ "m25px32-s0", INFO(0x207316,  0, 64 * 1024, 64, RD_NORM, SECT_4K) },
+	{ "m25px32-s1", INFO(0x206316,  0, 64 * 1024, 64, RD_NORM, SECT_4K) },
+	{ "m25px64",    INFO(0x207117,  0, 64 * 1024, 128, RD_NORM, 0) },
+	{ "m25px80",    INFO(0x207114,  0, 64 * 1024, 16, RD_NORM, 0) },
+#endif
+#ifdef CONFIG_SPI_FLASH_WINBOND		/* WINBOND */
+	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
+	{ "W25P80", INFO(0xef2014, 0, 64 * 1024, 16, RD_NORM, 0) },
+	{ "W25P16", INFO(0xef2015, 0, 64 * 1024, 32, RD_NORM, 0) },
+	{ "W25P32", INFO(0xef2016, 0, 64 * 1024, 64, RD_NORM, 0) },
+	{ "w25x05", INFO(0xef3010, 0, 64 * 1024,  1, RD_NORM, SECT_4K) },
+	{ "w25x10", INFO(0xef3011, 0, 64 * 1024,  2, RD_NORM, SECT_4K) },
+	{ "w25x20", INFO(0xef3012, 0, 64 * 1024,  4, RD_NORM, SECT_4K) },
+	{ "w25x40", INFO(0xef3013, 0, 64 * 1024,  8, RD_NORM, SECT_4K) },
+	{ "w25x80", INFO(0xef3014, 0, 64 * 1024,  16, RD_NORM, SECT_4K) },
+	{ "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, RD_NORM, SECT_4K) },
+	{ "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, RD_NORM, SECT_4K) },
+	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, RD_NORM, SECT_4K) },
+	{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, RD_FULL, WR_QPP | SECT_4K) },
+	{" w25q16cl", INFO(0xef4015, 0,	64 * 1024,  32, RD_FULL, WR_QPP | SECT_4K) },
+	{ "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, RD_FULL, WR_QPP | SECT_4K) },
+	{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K) },
+	{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, RD_FULL, WR_QPP | SECT_4K) },
+	{ "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, RD_FULL, WR_QPP | SECT_4K) },
+	{ "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, RD_FULL, WR_QPP | SECT_4K) },
+	{ "w25q16dw", INFO(0xef6015, 0, 64 * 1024,  32, RD_FULL, WR_QPP | SECT_4K) },
+	{ "w25q32dw", INFO(0xef6016, 0, 64 * 1024,  64, RD_FULL, WR_QPP | SECT_4K) },
+	{ "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K) },
+	{ "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, RD_FULL, WR_QPP | SECT_4K) },
+#endif
+	/* Catalyst / On Semiconductor -- non-JEDEC */
+	{ "cat25c11", CAT25_INFO(  16, 8, 16, 1, RD_NORM, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "cat25c03", CAT25_INFO(  32, 8, 16, 2, RD_NORM, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "cat25c09", CAT25_INFO( 128, 8, 32, 2, RD_NORM, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "cat25c17", CAT25_INFO( 256, 8, 32, 2, RD_NORM, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "cat25128", CAT25_INFO(2048, 8, 64, 2, RD_NORM, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ },
+};
+
+static const struct flash_info *spi_flash_id(struct spi_flash *flash)
+{
+	int			tmp;
+	u8			id[SPI_NOR_MAX_ID_LEN];
+	const struct flash_info	*info;
+
+	/* Read the ID codes */
+	tmp = spi_flash_cmd(flash->spi, CMD_READ_ID, id, sizeof(id));
+	if (tmp < 0) {
+		printf("SF: error %d reading JEDEC ID\n", tmp);
+		return ERR_PTR(tmp);
+	}
+
+	for (tmp = 0; tmp < ARRAY_SIZE(spi_flash_ids) - 1; tmp++) {
+		info = &spi_flash_ids[tmp];
+		if (info->id_len) {
+			if (!memcmp(info->id, id, info->id_len))
+				return &spi_flash_ids[tmp];
+		}
+	}
+	dev_err(flash->dev, "unrecognized JEDEC id bytes: %02x, %2x, %2x\n",
+		id[0], id[1], id[2]);
+	return ERR_PTR(-ENODEV);
+}
 
 #ifdef CONFIG_SPI_FLASH_MACRONIX
 static int macronix_quad_enable(struct spi_flash *flash)
@@ -914,9 +1244,9 @@ static int micron_quad_enable(struct spi_flash *flash)
 }
 #endif
 
-static int set_quad_mode(struct spi_flash *flash, u8 idcode0)
+static int set_quad_mode(struct spi_flash *flash, const struct flash_info *info)
 {
-	switch (idcode0) {
+	switch (JEDEC_MFR(info)) {
 #ifdef CONFIG_SPI_FLASH_MACRONIX
 	case SPI_FLASH_CFI_MFR_MACRONIX:
 		return macronix_quad_enable(flash);
@@ -931,7 +1261,8 @@ static int set_quad_mode(struct spi_flash *flash, u8 idcode0)
 		return micron_quad_enable(flash);
 #endif
 	default:
-		printf("SF: Need set QEB func for %02x flash\n", idcode0);
+		printf("SF: Need set QEB func for %02x flash\n",
+		       JEDEC_MFR(info));
 		return -1;
 	}
 }
@@ -967,10 +1298,7 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
 int spi_flash_scan(struct spi_flash *flash)
 {
 	struct spi_slave *spi = flash->spi;
-	const struct spi_flash_params *params;
-	u16 jedec, ext_jedec;
-	u8 cmd, idcode[5];
-	int ret;
+	const struct flash_info *info = NULL;
 	static u8 spi_read_cmds_array[] = {
 		CMD_READ_ARRAY_SLOW,
 		CMD_READ_ARRAY_FAST,
@@ -978,55 +1306,26 @@ int spi_flash_scan(struct spi_flash *flash)
 		CMD_READ_QUAD_OUTPUT_FAST,
 		CMD_READ_DUAL_IO_FAST,
 		CMD_READ_QUAD_IO_FAST };
+	u8 cmd;
+	int ret;
 
-	/* Read the ID codes */
-	ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
-	if (ret) {
-		printf("SF: Failed to get idcodes\n");
-		return -EINVAL;
-	}
-
-#ifdef DEBUG
-	printf("SF: Got idcodes\n");
-	print_buffer(0, idcode, 1, sizeof(idcode), 0);
-#endif
-
-	jedec = idcode[1] << 8 | idcode[2];
-	ext_jedec = idcode[3] << 8 | idcode[4];
-
-	/* Validate params from spi_flash_params table */
-	params = spi_flash_params_table;
-	for (; params->name != NULL; params++) {
-		if ((params->jedec >> 16) == idcode[0]) {
-			if ((params->jedec & 0xFFFF) == jedec) {
-				if (params->ext_jedec == 0)
-					break;
-				else if (params->ext_jedec == ext_jedec)
-					break;
-			}
-		}
-	}
-
-	if (!params->name) {
-		printf("SF: Unsupported flash IDs: ");
-		printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
-		       idcode[0], jedec, ext_jedec);
-		return -EPROTONOSUPPORT;
-	}
+	info = spi_flash_id(flash);
+	if (IS_ERR_OR_NULL(info))
+		return -ENOENT;
 
 	/* Flash powers up read-only, so clear BP# bits */
-	if (idcode[0] == SPI_FLASH_CFI_MFR_ATMEL ||
-	    idcode[0] == SPI_FLASH_CFI_MFR_MACRONIX ||
-	    idcode[0] == SPI_FLASH_CFI_MFR_SST)
+	if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_ATMEL ||
+	    JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MACRONIX ||
+	    JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST)
 		write_sr(flash, 0);
 
 	/* Assign spi data */
-	flash->name = params->name;
+	flash->name = info->name;
 	flash->memory_map = spi->memory_map;
 	flash->dual_flash = spi->option;
 
 	/* Assign spi flash flags */
-	if (params->flags & SST_WR)
+	if (info->flags & SST_WR)
 		flash->flags |= SNOR_F_SST_WR;
 
 	/* Assign spi_flash ops */
@@ -1045,7 +1344,7 @@ int spi_flash_scan(struct spi_flash *flash)
 #endif
 
 	/* lock hooks are flash specific - assign them based on idcode0 */
-	switch (idcode[0]) {
+	switch (JEDEC_MFR(info)) {
 #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
 	case SPI_FLASH_CFI_MFR_STMICRO:
 	case SPI_FLASH_CFI_MFR_SST:
@@ -1055,38 +1354,37 @@ int spi_flash_scan(struct spi_flash *flash)
 #endif
 		break;
 	default:
-		debug("SF: Lock ops not supported for %02x flash\n", idcode[0]);
+		debug("SF: Lock ops not supported for %02x flash\n",
+		      JEDEC_MFR(info));
 	}
 
 	/* Compute the flash size */
 	flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
+	flash->page_size = info->page_size;
 	/*
 	 * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the
 	 * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with
 	 * the 0x4d00 Extended JEDEC code have 512b pages. All of the others
 	 * have 256b pages.
 	 */
-	if (ext_jedec == 0x4d00) {
-		if ((jedec == 0x0215) || (jedec == 0x216))
-			flash->page_size = 256;
-		else
+	if (JEDEC_EXT(info) == 0x4d00) {
+		if ((JEDEC_ID(info) != 0x0215) &&
+		    (JEDEC_ID(info) != 0x0216))
 			flash->page_size = 512;
-	} else {
-		flash->page_size = 256;
 	}
 	flash->page_size <<= flash->shift;
-	flash->sector_size = params->sector_size << flash->shift;
-	flash->size = flash->sector_size * params->nr_sectors << flash->shift;
+	flash->sector_size = info->sector_size << flash->shift;
+	flash->size = flash->sector_size * info->n_sectors << flash->shift;
 #ifdef CONFIG_SF_DUAL_FLASH
 	if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
 		flash->size <<= 1;
 #endif
 
 	/* Compute erase sector and command */
-	if (params->flags & SECT_4K) {
+	if (info->flags & SECT_4K) {
 		flash->erase_cmd = CMD_ERASE_4K;
 		flash->erase_size = 4096 << flash->shift;
-	} else if (params->flags & SECT_32K) {
+	} else if (info->flags & SECT_32K) {
 		flash->erase_cmd = CMD_ERASE_32K;
 		flash->erase_size = 32768 << flash->shift;
 	} else {
@@ -1098,7 +1396,7 @@ int spi_flash_scan(struct spi_flash *flash)
 	flash->sector_size = flash->erase_size;
 
 	/* Look for the fastest read cmd */
-	cmd = fls(params->e_rd_cmd & spi->mode_rx);
+	cmd = fls(info->e_rd_cmd & spi->mode_rx);
 	if (cmd) {
 		cmd = spi_read_cmds_array[cmd - 1];
 		flash->read_cmd = cmd;
@@ -1108,7 +1406,7 @@ int spi_flash_scan(struct spi_flash *flash)
 	}
 
 	/* Not require to look for fastest only two write cmds yet */
-	if (params->flags & WR_QPP && spi->mode & SPI_TX_QUAD)
+	if (info->flags & WR_QPP && spi->mode & SPI_TX_QUAD)
 		flash->write_cmd = CMD_QUAD_PAGE_PROGRAM;
 	else
 		/* Go for default supported write cmd */
@@ -1118,9 +1416,10 @@ int spi_flash_scan(struct spi_flash *flash)
 	if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
 	    (flash->read_cmd == CMD_READ_QUAD_IO_FAST) ||
 	    (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
-		ret = set_quad_mode(flash, idcode[0]);
+		ret = set_quad_mode(flash, info);
 		if (ret) {
-			debug("SF: Fail to set QEB for %02x\n", idcode[0]);
+			debug("SF: Fail to set QEB for %02x\n",
+			      JEDEC_MFR(info));
 			return -EINVAL;
 		}
 	}
@@ -1145,13 +1444,13 @@ int spi_flash_scan(struct spi_flash *flash)
 	}
 
 #ifdef CONFIG_SPI_FLASH_STMICRO
-	if (params->flags & E_FSR)
+	if (info->flags & E_FSR)
 		flash->flags |= SNOR_F_USE_FSR;
 #endif
 
 	/* Configure the BAR - discover bank cmds and read current bank */
 #ifdef CONFIG_SPI_FLASH_BAR
-	ret = spi_flash_read_bar(flash, idcode[0]);
+	ret = spi_flash_read_bar(flash, info);
 	if (ret < 0)
 		return ret;
 #endif
diff --git a/include/linux/err.h b/include/linux/err.h
index 5b3c8bc..1bba498 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -36,6 +36,11 @@ static inline long IS_ERR(const void *ptr)
 	return IS_ERR_VALUE((unsigned long)ptr);
 }
 
+static inline bool IS_ERR_OR_NULL(const void *ptr)
+{
+	return !ptr || IS_ERR_VALUE((unsigned long)ptr);
+}
+
 /**
  * ERR_CAST - Explicitly cast an error-valued pointer to another pointer type
  * @ptr: The pointer to cast.
-- 
1.9.1

  reply	other threads:[~2015-12-31  9:21 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-31  9:21 [U-Boot] [PATCH v3 00/10] sf: Add flash_ids inside Core Jagan Teki
2015-12-31  9:21 ` Jagan Teki [this message]
2015-12-31  9:21 ` [U-Boot] [PATCH v3 02/10] sf: Rename SST_WR to SST_WRITE Jagan Teki
2015-12-31  9:21 ` [U-Boot] [PATCH v3 03/10] sf: Remove SPI_NOR_DUAL|QUAD_READ Jagan Teki
2015-12-31  9:21 ` [U-Boot] [PATCH v3 04/10] sf: Use sf_params in sandbox Jagan Teki
2016-01-11 16:59   ` Simon Glass
2015-12-31  9:22 ` [U-Boot] [PATCH v3 05/10] sf: Remove SECT_32K Jagan Teki
2015-12-31  9:22 ` [U-Boot] [PATCH v3 06/10] sf: Add SECT_4K_PMC Jagan Teki
2015-12-31  9:22 ` [U-Boot] [PATCH v3 07/10] sf: Use CONFIG_SPI_FLASH_USE_4K_SECTORS Jagan Teki
2015-12-31  9:22 ` [U-Boot] [PATCH v3 08/10] sf: Fix few naming convention for read modes Jagan Teki
2015-12-31  9:22 ` [U-Boot] [PATCH v3 09/10] sf: sandbox: Move spi_flash_params_table Jagan Teki
2016-01-06 14:33 ` [U-Boot] [PATCH v3 00/10] sf: Add flash_ids inside Core Jagan Teki
2016-01-09  7:11   ` Jagan Teki
2016-01-09 14:21   ` Bin Meng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1451553724-1098-2-git-send-email-jteki@openedev.com \
    --to=jteki@openedev.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.