* updated SNAND/SNFI driver brings support for MT7981 * add support for MediaTek NAND Memory bad Block Management (NMBM) (not used for any boards atm, but could be useful in future) * wire up NMBM support for MT7622, MT7629, MT7981 and MT7986 * replace some local patches with updated version from SDK * bring some legacy precompiler symbols which haven't been converted into Kconfig symbols in U-Boot 2022.07, remove when bumbping to U-Boot 2022.10: 100-28-include-configs-mt7986-h-from-SDK.patch Source: https://github.com/mtk-openwrt/u-boot Signed-off-by: Daniel Golle <daniel@makrotopia.org>
		
			
				
	
	
		
			143 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From c4172a95df8a57a66c70a8b9948b9600a01c4cb7 Mon Sep 17 00:00:00 2001
 | 
						|
From: Weijie Gao <weijie.gao@mediatek.com>
 | 
						|
Date: Mon, 25 Jul 2022 11:32:08 +0800
 | 
						|
Subject: [PATCH 49/71] mtd: spi-nor: add support to read flash unique ID
 | 
						|
 | 
						|
This patch adds support to read unique ID from spi-nor flashes.
 | 
						|
 | 
						|
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
 | 
						|
---
 | 
						|
 drivers/mtd/spi/spi-nor-core.c | 95 ++++++++++++++++++++++++++++++++++
 | 
						|
 include/linux/mtd/spi-nor.h    |  2 +
 | 
						|
 2 files changed, 97 insertions(+)
 | 
						|
 | 
						|
--- a/drivers/mtd/spi/spi-nor-core.c
 | 
						|
+++ b/drivers/mtd/spi/spi-nor-core.c
 | 
						|
@@ -2742,6 +2742,100 @@ static int spi_nor_init_params(struct sp
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static int spi_nor_read_uuid(struct spi_nor *nor)
 | 
						|
+{
 | 
						|
+	u8 read_opcode, addr_width, read_dummy;
 | 
						|
+	loff_t addr;
 | 
						|
+	u8 *uuid;
 | 
						|
+	u8 uuid_len;
 | 
						|
+	int shift = 0;
 | 
						|
+	int ret;
 | 
						|
+	int i;
 | 
						|
+	struct spi_mem_op op;
 | 
						|
+
 | 
						|
+	read_opcode = nor->read_opcode;
 | 
						|
+	addr_width = nor->addr_width;
 | 
						|
+	read_dummy = nor->read_dummy;
 | 
						|
+
 | 
						|
+	switch (JEDEC_MFR(nor->info)) {
 | 
						|
+	case SNOR_MFR_WINBOND:
 | 
						|
+		uuid_len = 8;
 | 
						|
+		nor->read_opcode = 0x4b;
 | 
						|
+		nor->addr_width = 0;
 | 
						|
+		addr = 0x0;
 | 
						|
+		nor->read_dummy = 4;
 | 
						|
+		break;
 | 
						|
+	case SNOR_MFR_GIGADEVICE:
 | 
						|
+		uuid_len = 16;
 | 
						|
+		nor->read_opcode = 0x4b;
 | 
						|
+		nor->addr_width = 3;
 | 
						|
+		addr = 0x0;
 | 
						|
+		nor->read_dummy = 1;
 | 
						|
+		break;
 | 
						|
+	case CFI_MFR_ST:
 | 
						|
+	case SNOR_MFR_MICRON:
 | 
						|
+		uuid_len = 17;
 | 
						|
+		shift = 3;
 | 
						|
+		nor->read_opcode = 0x9f;
 | 
						|
+		nor->addr_width = 0;
 | 
						|
+		addr = 0x0;
 | 
						|
+		nor->read_dummy = 0;
 | 
						|
+		break;
 | 
						|
+	case SNOR_MFR_EON:
 | 
						|
+		uuid_len = 12;
 | 
						|
+		nor->read_opcode = 0x5a;
 | 
						|
+		nor->addr_width = 3;
 | 
						|
+		addr = 0x80;
 | 
						|
+		nor->read_dummy = 1;
 | 
						|
+		break;
 | 
						|
+	/* Automotive only in SPANSION's NOR devices */
 | 
						|
+	case SNOR_MFR_SPANSION:
 | 
						|
+		uuid_len = 11;
 | 
						|
+		shift = 386;
 | 
						|
+		nor->read_opcode = 0x9f;
 | 
						|
+		nor->addr_width = 0;
 | 
						|
+		addr = 0x0;
 | 
						|
+		nor->read_dummy = 0;
 | 
						|
+		break;
 | 
						|
+	default:
 | 
						|
+		printf("UUID not supported on this device.\n");
 | 
						|
+		return -ENOTSUPP;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	uuid = kmalloc((uuid_len + shift) * sizeof(*uuid), GFP_KERNEL);
 | 
						|
+	if (!uuid) {
 | 
						|
+		ret = -ENOMEM;
 | 
						|
+		goto read_err;
 | 
						|
+	}
 | 
						|
+	memset(uuid, 0x0, (uuid_len + shift) * sizeof(*uuid));
 | 
						|
+
 | 
						|
+	op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0),
 | 
						|
+					   SPI_MEM_OP_ADDR(nor->addr_width, addr, 0),
 | 
						|
+					   SPI_MEM_OP_DUMMY(nor->read_dummy, 0),
 | 
						|
+					   SPI_MEM_OP_DATA_IN(uuid_len+shift, NULL, 0));
 | 
						|
+
 | 
						|
+	spi_nor_setup_op(nor, &op, nor->reg_proto);
 | 
						|
+
 | 
						|
+	ret = spi_nor_read_write_reg(nor, &op, uuid);
 | 
						|
+	if (ret < 0) {
 | 
						|
+		dev_dbg(nor->dev, "error %d reading %x\n", ret, nor->read_opcode);
 | 
						|
+		goto read_err;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	printf("UUID: 0x");
 | 
						|
+	for(i = 0; i<uuid_len; i++)
 | 
						|
+		printf("%02x", uuid[i+shift]);
 | 
						|
+	puts("\n");
 | 
						|
+
 | 
						|
+read_err:
 | 
						|
+	nor->read_opcode = read_opcode;
 | 
						|
+	nor->addr_width = addr_width;
 | 
						|
+	nor->read_dummy = read_dummy;
 | 
						|
+	kfree(uuid);
 | 
						|
+
 | 
						|
+	return ret;
 | 
						|
+}
 | 
						|
+
 | 
						|
 static int spi_nor_hwcaps2cmd(u32 hwcaps, const int table[][2], size_t size)
 | 
						|
 {
 | 
						|
 	size_t i;
 | 
						|
@@ -3719,6 +3813,7 @@ int spi_nor_scan(struct spi_nor *nor)
 | 
						|
 	nor->write = spi_nor_write_data;
 | 
						|
 	nor->read_reg = spi_nor_read_reg;
 | 
						|
 	nor->write_reg = spi_nor_write_reg;
 | 
						|
+	nor->read_uuid = spi_nor_read_uuid;
 | 
						|
 
 | 
						|
 	nor->setup = spi_nor_default_setup;
 | 
						|
 
 | 
						|
--- a/include/linux/mtd/spi-nor.h
 | 
						|
+++ b/include/linux/mtd/spi-nor.h
 | 
						|
@@ -28,6 +28,7 @@
 | 
						|
 #define SNOR_MFR_SPANSION	CFI_MFR_AMD
 | 
						|
 #define SNOR_MFR_SST		CFI_MFR_SST
 | 
						|
 #define SNOR_MFR_WINBOND	0xef /* Also used by some Spansion */
 | 
						|
+#define SNOR_MFR_EON		CFI_MFR_EON
 | 
						|
 #define SNOR_MFR_CYPRESS	0x34
 | 
						|
 
 | 
						|
 /*
 | 
						|
@@ -547,6 +548,7 @@ struct spi_nor {
 | 
						|
 	void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
 | 
						|
 	int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
 | 
						|
 	int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
 | 
						|
+	int (*read_uuid)(struct spi_nor *nor);
 | 
						|
 
 | 
						|
 	ssize_t (*read)(struct spi_nor *nor, loff_t from,
 | 
						|
 			size_t len, u_char *read_buf);
 |