openwrt/package/boot/uboot-mediatek/patches/100-14-mtd-spi-nor-add-support-to-read-flash-unique-ID.patch

143 lines
3.7 KiB
Diff
Raw Permalink Normal View History

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
@@ -2958,6 +2958,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;
@@ -4077,6 +4171,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
@@ -29,6 +29,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
/*
@@ -567,6 +568,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);