Open sseseed opened 1 month ago
F50D1G41LB 不是这个ID。
请拆机确认你板子上用的NAND芯片
F50D1G41LB 不是这个ID。
请拆机确认你板子上用的NAND芯片
首先,谢谢你的回复。我对比过原厂固件启动信息,的确也是显示 nand: device found, Manufacturer ID: 0xa1, Chip ID: 0xa5,闪存型号我没认真拆开看,因为有散热片和屏蔽压着所以没拆到底,只是看网上别人的拆解图的确是F50D1G41LB 。
应该是0x11
F50D1G41LB 不是这个ID。
请拆机确认你板子上用的NAND芯片
刚刚拆开看了,的确和网上拆机图不同,硬件版本和网上一样,但网上拆的是 21 年产的,我手上的是 23 年产的,我手上这个的 SPI NAND 型号是 复旦微 FM25LS01。
F50D1G41LB 不是这个ID。
请拆机确认你板子上用的NAND芯片
经过一番的瞎探索,终于找到了添加 SPI NAND 的 patch 文件并添加了 FM25LS01 进去, {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) }, 但不懂这个结构体,应该有些参数设错了,特别是 ECC 那里,我在 https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 查到 FM25LS01 的 ECC 是 1bit,所以就填成 1,SZ_512,也不知道对不对。目前能成功到识别分区那里了,但后面读不到数据提示 ECC 错误。部分关键的 TTL 回显如下:
[ 0.867862] nand: device found, Manufacturer ID: 0xa1, Chip ID: 0xa5 [ 0.867909] nand: Unknown FM25LS01 SPI NAND 1G 1.8V [ 0.873733] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 128 [ 0.878408] QPIC controller hw version Major:2, Minor:1 [ 0.886111] 17 fixed-partitions partitions found on MTD device qcom_nand.0 [ 0.891223] Creating 17 MTD partitions on "qcom_nand.0": [ 0.898153] 0x000000000000-0x000000080000 : "0:SBL1" [ 0.905109] 0x000000080000-0x000000100000 : "0:MIBIB" [ 0.910138] 0x000000100000-0x000000140000 : "0:BOOTCONFIG" [ 0.914616] 0x000000140000-0x000000180000 : "0:BOOTCONFIG1" [ 0.920055] 0x000000180000-0x000000280000 : "0:QSEE" [ 0.926815] 0x000000280000-0x000000380000 : "0:QSEE_1" [ 0.931764] 0x000000380000-0x0000003c0000 : "0:DEVCFG" [ 0.935535] 0x0000003c0000-0x000000400000 : "0:DEVCFG_1" [ 0.940821] 0x000000400000-0x000000440000 : "0:CDT" [ 0.946324] 0x000000440000-0x000000480000 : "0:CDT_1" [ 0.950828] 0x000000480000-0x000000500000 : "0:APPSBLENV" [ 0.956449] 0x000000500000-0x000000640000 : "0:APPSBL" [ 0.962891] 0x000000640000-0x000000780000 : "0:APPSBL_1" [ 0.968129] 0x000000780000-0x000000880000 : "0:ART" [ 0.972979] 0x000000880000-0x000000900000 : "0:TRAINING" [ 0.976980] 0x000000900000-0x000004300000 : "rootfs" [ 1.064560] mtd: setting mtd15 (rootfs) as root device [ 1.065941] mtdsplit: error occured while reading from "rootfs" [ 1.068709] 0x000004300000-0x000007d00000 : "rootfs_1" [ 1.557315] i2c_dev: i2c /dev entries driver [ 1.558363] cpufreq: cpufreq_online: CPU0: Running at unlisted initial frequency: 24000 KHz, changing to: 800000 KHz [ 1.561003] sdhci: Secure Digital Host Controller Interface driver [ 1.571225] sdhci: Copyright(c) Pierre Ossman [ 1.577194] sdhci-pltfm: SDHCI platform and OF driver helper [ 1.584402] remoteproc remoteproc0: releasing cd00000.remoteproc [ 1.588620] cs_system_cfg: CoreSight Configuration manager initialised [ 1.594946] NET: Registered PF_INET6 protocol family [ 1.601500] Segment Routing with IPv6 [ 1.604897] In-situ OAM (IOAM) with IPv6 [ 1.608569] NET: Registered PF_PACKET protocol family [ 1.612457] 8021q: 802.1Q VLAN Support v1.8 [ 1.617587] Registering SWP/SWPB emulation handler [ 1.642534] remoteproc remoteproc0: cd00000.remoteproc is available [ 1.643945] remoteproc remoteproc1: 4ab000.remoteproc_pd1 is available [ 1.649375] remoteproc remoteproc2: cd00000.remoteproc:remoteproc_pd2 is available [ 1.655250] ubi0: attaching mtd15 [ 1.663580] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 0:0, read only 64 bytes, retry [ 1.666420] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 0:0, read only 64 bytes, retry [ 1.677328] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 0:0, read only 64 bytes, retry [ 1.688621] ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 0:0, read 64 bytes [ 1.698361] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.15.150 #0 [ 1.708375] Hardware name: Generic DT based system [ 1.714460] [<8030e0b0>] (unwind_backtrace) from [<80309bd8>] (show_stack+0x10/0x14) [ 1.719143] [<80309bd8>] (show_stack) from [<8067a780>] (dump_stack_lvl+0x40/0x4c) [ 1.727042] [<8067a780>] (dump_stack_lvl) from [<80791d88>] (ubi_io_read+0x138/0x33c) [ 1.734421] [<80791d88>] (ubi_io_read) from [<807921e0>] (ubi_io_read_ec_hdr+0x44/0x1f4) [ 1.742318] [<807921e0>] (ubi_io_read_ec_hdr) from [<807972f4>] (ubi_attach+0x428/0x1458) [ 1.750479] [<807972f4>] (ubi_attach) from [<8078c4e4>] (ubi_attach_mtd_dev+0x494/0xb34) [ 1.758552] [<8078c4e4>] (ubi_attach_mtd_dev) from [<80d1e7f0>] (ubi_init+0x124/0x354) [ 1.766712] [<80d1e7f0>] (ubi_init) from [<8030180c>] (do_one_initcall+0x54/0x1f4) [ 1.774436] [<8030180c>] (do_one_initcall) from [<80d013d8>] (kernel_init_freeable+0x218/0x26c) [ 1.781991] [<80d013d8>] (kernel_init_freeable) from [<809f9a1c>] (kernel_init+0x14/0x124) [ 1.790584] [<809f9a1c>] (kernel_init) from [<80300124>] (ret_from_fork+0x14/0x30) [ 1.798914] Exception stack(0x81029fb0 to 0x81029ff8) [ 1.806466] 9fa0: 00000000 00000000 00000000 00000000 [ 1.811592] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 1.819752] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 [ 1.830145] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 1:0, read only 64 bytes, retry [ 1.835616] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 1:0, read only 64 bytes, retry [ 1.846791] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 1:0, read only 64 bytes, retry [ 1.857866] ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 1:0, read 64 bytes [ 1.867733] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.15.150 #0 [ 1.877732] Hardware name: Generic DT based system [ 1.883815] [<8030e0b0>] (unwind_backtrace) from [<80309bd8>] (show_stack+0x10/0x14) [ 1.888501] [<80309bd8>] (show_stack) from [<8067a780>] (dump_stack_lvl+0x40/0x4c) [ 1.896398] [<8067a780>] (dump_stack_lvl) from [<80791d88>] (ubi_io_read+0x138/0x33c) [ 1.903778] [<80791d88>] (ubi_io_read) from [<807921e0>] (ubi_io_read_ec_hdr+0x44/0x1f4) [ 1.911675] [<807921e0>] (ubi_io_read_ec_hdr) from [<807972f4>] (ubi_attach+0x428/0x1458) [ 1.919836] [<807972f4>] (ubi_attach) from [<8078c4e4>] (ubi_attach_mtd_dev+0x494/0xb34) [ 1.927909] [<8078c4e4>] (ubi_attach_mtd_dev) from [<80d1e7f0>] (ubi_init+0x124/0x354) [ 1.936069] [<80d1e7f0>] (ubi_init) from [<8030180c>] (do_one_initcall+0x54/0x1f4) [ 1.943795] [<8030180c>] (do_one_initcall) from [<80d013d8>] (kernel_init_freeable+0x218/0x26c) [ 1.951348] [<80d013d8>] (kernel_init_freeable) from [<809f9a1c>] (kernel_init+0x14/0x124) [ 1.959941] [<809f9a1c>] (kernel_init) from [<80300124>] (ret_from_fork+0x14/0x30) [ 1.968271] Exception stack(0x81029fb0 to 0x81029ff8) [ 1.975825] 9fa0: 00000000 00000000 00000000 00000000 [ 1.980951] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 1.989110] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 [ 1.999424] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 64 bytes from PEB 2:0, read only 64 bytes, retry
后面是不停地循环。。。
应该是0x11
麻烦帮看下添加 FM25LS01 这个 SPI NAND 的结构体是不是哪里有错?芯片简单说明:https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 谢谢。 {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) },
应该是0x11
麻烦帮看下添加 FM25LS01 这个 SPI NAND 的结构体是不是哪里有错?芯片简单说明:https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 谢谢。 {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) },
请尝试NAND_ECC_INFO(4, SZ_512)
应该是0x11
麻烦帮看下添加 FM25LS01 这个 SPI NAND 的结构体是不是哪里有错?芯片简单说明:https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 谢谢。 {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) },
请尝试NAND_ECC_INFO(4, SZ_512)
这个试过了,也是不行,一开始就是用 4 ,然后用 8 都不行,最后才试 1 的。可能不只一个参数有问题,暂时只能乱试,现在把 0, 2, 128 那里改成 0,2,64 试,然后 ECC 那里就是 1、4、8 都轮着试。小白只能穷举了 :) 网上下载的别人说可以用的固件在我这里不可以,可能就是闪存不同的原因,别人的固件直接提示找不到 nand 然后就中断不动了。
应该是0x11
麻烦帮看下添加 FM25LS01 这个 SPI NAND 的结构体是不是哪里有错?芯片简单说明:https://www.fmsh.com/62934bb9-d96d-5f04-e1ce-dd9a26dbfebf/ 谢谢。 {"FM25LS01 SPI NAND 1G 1.8V", { .id = {0xa1, 0xa5} }, SZ_2K, SZ_128, SZ_128K, 0, 2, 128, NAND_ECC_INFO(1, SZ_512) },
请尝试NAND_ECC_INFO(4, SZ_512)
找到了另一个形式的对 FM25LS01 的结构体,但不会套过去... { .id = { 0xa1, 0xa5 }, .page_size = 2048, .erase_blk_size = 0x00020000, .pgs_per_blk = 64, .no_of_blocks = 1024, .spare_size = 64, .density = 0x08000000, .otp_region = 0x2000, .no_of_addr_cycle = 0x3, .num_bits_ecc_correctability = 4, .timing_mode_support = 0, .quad_mode = true, .check_quad_config = true, .name = "FM25LS01", },
From 6ee246291159ce8fa235aa4412941413e073c779 Mon Sep 17 00:00:00 2001
From: JiaY-shi <shi05275@163.com>
Date: Sun, 4 Aug 2024 13:19:32 +0800
Subject: mtd: nand: add ipq5018 spi nand support
---
drivers/mtd/nand/raw/qcom_nandc.c | 191 ++++++++++++++++++++++++++++--
1 file changed, 178 insertions(+), 13 deletions(-)
diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
index b8cff9240b28..9d0e690980b3 100644
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -35,13 +35,22 @@
#define NAND_DEV_CMD0 0xa0
#define NAND_DEV_CMD1 0xa4
#define NAND_DEV_CMD2 0xa8
+#define NAND_DEV_CMD3 0xd0
+#define NAND_DEV_CMD4 0xd4
+#define NAND_DEV_CMD5 0xd8
+#define NAND_DEV_CMD6 0xdc
+#define NAND_DEV_CMD7 0xb0
+#define NAND_DEV_CMD8 0xb4
+#define NAND_DEV_CMD9 0xb8
#define NAND_DEV_CMD_VLD 0xac
+#define NAND_FLASH_SPI_CFG 0xc0
+#define NAND_SPI_NUM_ADDR_CYCLES 0xc4
+#define NAND_SPI_BUSY_CHECK_WAIT_CNT 0xc8
#define SFLASHC_BURST_CFG 0xe0
#define NAND_ERASED_CW_DETECT_CFG 0xe8
#define NAND_ERASED_CW_DETECT_STATUS 0xec
#define NAND_EBI2_ECC_BUF_CFG 0xf0
#define FLASH_BUF_ACC 0x100
-
#define NAND_CTRL 0xf00
#define NAND_VERSION 0xf08
#define NAND_READ_LOCATION_0 0xf20
@@ -52,6 +61,7 @@
#define NAND_READ_LOCATION_LAST_CW_1 0xf44
#define NAND_READ_LOCATION_LAST_CW_2 0xf48
#define NAND_READ_LOCATION_LAST_CW_3 0xf4c
+#define NAND_QSPI_MSTR_CONFIG 0xf60
/* dummy register offsets, used by write_reg_dma */
#define NAND_DEV_CMD1_RESTORE 0xdead
@@ -189,6 +199,28 @@
#define ECC_BCH_4BIT BIT(2)
#define ECC_BCH_8BIT BIT(3)
+/* QSPI NAND config reg bits */
+#define LOAD_CLK_CNTR_INIT_EN (1 << 28)
+#define CLK_CNTR_INIT_VAL_VEC 0x924
+#define FEA_STATUS_DEV_ADDR 0xc0
+#define SPI_CFG (1 << 0)
+
+/* CMD register value for qspi nand */
+#define CMD0_VAL 0x1080D8D8
+#define CMD1_VAL 0xF00F3000
+#define CMD2_VAL 0xF0FF709F
+#define CMD3_VAL 0x3F310015
+#define CMD7_VAL 0x04061F0F
+#define CMD_VLD_VAL 0xd
+#define SPI_NUM_ADDR 0xDA4DB
+#define WAIT_CNT 0x10
+
+/* QSPI NAND CMD reg bits value */
+#define SPI_WP (1 << 28)
+#define SPI_HOLD (1 << 27)
+#define SPI_TRANSFER_MODE_x1 (1 << 29)
+#define SPI_TRANSFER_MODE_x4 (3 << 29)
+
#define nandc_set_read_loc_first(chip, reg, cw_offset, read_size, is_last_read_loc) \
nandc_set_reg(chip, reg, \
((cw_offset) << READ_LOCATION_OFFSET) | \
@@ -336,6 +368,9 @@ struct nandc_regs {
__le32 read_location_last1;
__le32 read_location_last2;
__le32 read_location_last3;
+ __le32 spi_cfg;
+ __le32 num_addr_cycle;
+ __le32 busy_wait_cnt;
__le32 erased_cw_detect_cfg_clr;
__le32 erased_cw_detect_cfg_set;
@@ -396,6 +431,7 @@ struct qcom_nand_controller {
struct clk *core_clk;
struct clk *aon_clk;
+ struct clk *iomacro_clk;
struct nandc_regs *regs;
struct bam_transaction *bam_txn;
@@ -439,6 +475,7 @@ struct qcom_nand_controller {
u32 cmd1, vld;
bool exec_opwrite;
+ u32 hw_version;
};
/*
@@ -553,6 +590,7 @@ struct qcom_nand_host {
* @is_qpic - whether NAND CTRL is part of qpic IP
* @qpic_v2 - flag to indicate QPIC IP version 2
* @use_codeword_fixup - whether NAND has different layout for boot partitions
+ * @is_serial_nand - QSPI nand flag, whether QPIC support serial nand or not
*/
struct qcom_nandc_props {
u32 ecc_modes;
@@ -561,6 +599,7 @@ struct qcom_nandc_props {
bool is_qpic;
bool qpic_v2;
bool use_codeword_fixup;
+ bool is_serial_nand;
};
/* Frees the BAM transaction memory */
@@ -743,6 +782,12 @@ static __le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset)
return ®s->read_location_last2;
case NAND_READ_LOCATION_LAST_CW_3:
return ®s->read_location_last3;
+ case NAND_FLASH_SPI_CFG:
+ return ®s->spi_cfg;
+ case NAND_SPI_NUM_ADDR_CYCLES:
+ return ®s->num_addr_cycle;
+ case NAND_SPI_BUSY_CHECK_WAIT_CNT:
+ return ®s->busy_wait_cnt;
default:
return NULL;
}
@@ -814,13 +859,18 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, i
u32 cmd, cfg0, cfg1, ecc_bch_cfg;
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
+ cmd = (PAGE_ACC | LAST_PAGE);
+
+ if (nandc->props->is_serial_nand)
+ cmd |= (SPI_TRANSFER_MODE_x1 | SPI_WP | SPI_HOLD);
+
if (read) {
if (host->use_ecc)
- cmd = OP_PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE;
+ cmd |= OP_PAGE_READ_WITH_ECC;
else
- cmd = OP_PAGE_READ | PAGE_ACC | LAST_PAGE;
+ cmd |= OP_PAGE_READ;
} else {
- cmd = OP_PROGRAM_PAGE | PAGE_ACC | LAST_PAGE;
+ cmd |= OP_PROGRAM_PAGE;
}
if (host->use_ecc) {
@@ -2371,12 +2421,32 @@ static int qcom_nand_attach_chip(struct nand_chip *chip)
int cwperpage, bad_block_byte, ret;
bool wide_bus;
int ecc_mode = 1;
+ int num_addr_cycle = 5, dsbl_sts_aftr_write = 0;
+ int wr_rd_bsy_gap = 2, recovery_cycle = 7;
+ u32 version_reg;
/* controller only supports 512 bytes data steps */
ecc->size = NANDC_STEP_SIZE;
wide_bus = chip->options & NAND_BUSWIDTH_16 ? true : false;
cwperpage = mtd->writesize / NANDC_STEP_SIZE;
+ /*
+ * Read the required ecc strength from NAND device and overwrite the
+ * device tree ecc strength
+ */
+ if (chip->base.ecc.requirements.strength >= 8)
+ ecc->strength = 8;
+
+ /* Read QPIC version register */
+ version_reg = (NAND_VERSION + 0x4000);
+ nandc->hw_version = nandc_read(nandc, version_reg);
+ pr_info("QPIC controller hw version Major:%d, Minor:%d\n",
+ ((nandc->hw_version & NAND_VERSION_MAJOR_MASK)
+ >> NAND_VERSION_MAJOR_SHIFT),
+ ((nandc->hw_version & NAND_VERSION_MINOR_MASK)
+ >> NAND_VERSION_MINOR_SHIFT));
+ nandc->hw_version = ((nandc->hw_version & NAND_VERSION_MAJOR_MASK)
+ >> NAND_VERSION_MAJOR_SHIFT);
/*
* Each CW has 4 available OOB bytes which will be protected with ECC
* so remaining bytes can be used for ECC.
@@ -2485,33 +2555,43 @@ static int qcom_nand_attach_chip(struct nand_chip *chip)
host->cw_size = host->cw_data + ecc->bytes;
bad_block_byte = mtd->writesize - host->cw_size * (cwperpage - 1) + 1;
+ /* For QSPI serial nand QPIC config register value got changed
+ * so configure the new value for qspi serial nand
+ */
+ if (nandc->props->is_serial_nand) {
+ num_addr_cycle = 3;
+ dsbl_sts_aftr_write = 1;
+ wr_rd_bsy_gap = 20;
+ recovery_cycle = 0;
+ }
+
host->cfg0 = (cwperpage - 1) << CW_PER_PAGE
| host->cw_data << UD_SIZE_BYTES
- | 0 << DISABLE_STATUS_AFTER_WRITE
- | 5 << NUM_ADDR_CYCLES
+ | dsbl_sts_aftr_write << DISABLE_STATUS_AFTER_WRITE
+ | num_addr_cycle << NUM_ADDR_CYCLES
| host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_RS
| 0 << STATUS_BFR_READ
| 1 << SET_RD_MODE_AFTER_STATUS
| host->spare_bytes << SPARE_SIZE_BYTES;
- host->cfg1 = 7 << NAND_RECOVERY_CYCLES
+ host->cfg1 = recovery_cycle << NAND_RECOVERY_CYCLES
| 0 << CS_ACTIVE_BSY
| bad_block_byte << BAD_BLOCK_BYTE_NUM
| 0 << BAD_BLOCK_IN_SPARE_AREA
- | 2 << WR_RD_BSY_GAP
+ | wr_rd_bsy_gap << WR_RD_BSY_GAP
| wide_bus << WIDE_FLASH
| host->bch_enabled << ENABLE_BCH_ECC;
host->cfg0_raw = (cwperpage - 1) << CW_PER_PAGE
| host->cw_size << UD_SIZE_BYTES
- | 5 << NUM_ADDR_CYCLES
+ | num_addr_cycle << NUM_ADDR_CYCLES
| 0 << SPARE_SIZE_BYTES;
- host->cfg1_raw = 7 << NAND_RECOVERY_CYCLES
+ host->cfg1_raw = recovery_cycle << NAND_RECOVERY_CYCLES
| 0 << CS_ACTIVE_BSY
| 17 << BAD_BLOCK_BYTE_NUM
| 1 << BAD_BLOCK_IN_SPARE_AREA
- | 2 << WR_RD_BSY_GAP
+ | wr_rd_bsy_gap << WR_RD_BSY_GAP
| wide_bus << WIDE_FLASH
| 1 << DEV0_CFG1_ECC_DISABLE;
@@ -2551,6 +2631,8 @@ static int qcom_op_cmd_mapping(struct nand_chip *chip, u8 opcode,
switch (opcode) {
case NAND_CMD_RESET:
cmd = OP_RESET_DEVICE;
+ if (nandc->props->is_serial_nand)
+ cmd |= (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1);
break;
case NAND_CMD_READID:
cmd = OP_FETCH_ID;
@@ -2763,6 +2845,17 @@ static int qcom_read_id_type_exec(struct nand_chip *chip, const struct nand_subo
clear_read_regs(nandc);
clear_bam_transaction(nandc);
+ if (nandc->props->is_serial_nand) {
+ q_op.cmd_reg |= (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1);
+ /* For spi nand read 2-bytes id only
+ * else if nandc->buf_count == 4; then the id value
+ * will repeat and the SLC device will be detect as MLC.
+ * by nand base layer
+ * so overwrite the nandc->buf_count == 2;
+ */
+ nandc->buf_count = 2;
+ }
+
nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg);
nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg);
nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg);
@@ -2785,6 +2878,15 @@ static int qcom_read_id_type_exec(struct nand_chip *chip, const struct nand_subo
instr = q_op.data_instr;
op_id = q_op.data_instr_idx;
len = nand_subop_get_data_len(subop, op_id);
+ if (nandc->props->is_serial_nand) {
+ /* For spi nand read 2-bytes id only
+ * else if nandc->buf_count == 4; then the id value
+ * will repeat and the SLC device will be detect as MLC.
+ * by nand base layer
+ * so overwrite the nandc->buf_count == 2;
+ */
+ len = 2;
+ }
nandc_read_buffer_sync(nandc, true);
memcpy(instr->ctx.data.buf.in, nandc->reg_read_buf, len);
@@ -2809,6 +2911,11 @@ static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
goto wait_rdy;
} else if (q_op.cmd_reg == OP_BLOCK_ERASE) {
q_op.cmd_reg |= PAGE_ACC | LAST_PAGE;
+ if (nandc->props->is_serial_nand) {
+ q_op.cmd_reg |= (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1);
+ q_op.addr2_reg = (q_op.addr1_reg >> 16) & 0xffff;
+ q_op.addr1_reg <<= 16;
+ }
nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg);
nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg);
nandc_set_reg(chip, NAND_DEV0_CFG0,
@@ -2859,7 +2966,7 @@ static int qcom_param_page_type_exec(struct nand_chip *chip, const struct nand_
unsigned int op_id = 0;
unsigned int len = 0;
int ret;
-
+ printk(KERN_INFO "%s:%d %d\n", __func__,__LINE__, nandc->props->is_serial_nand);
ret = qcom_parse_instructions(chip, subop, &q_op);
if (ret)
return ret;
@@ -3254,6 +3361,34 @@ static int qcom_nand_host_parse_boot_partitions(struct qcom_nand_controller *nan
return 0;
}
+static void qspi_nand_init(struct qcom_nand_controller *nandc)
+{
+ u32 spi_cfg_val = 0x0;
+ u32 reg = 0x0;
+
+ spi_cfg_val |= (LOAD_CLK_CNTR_INIT_EN | (CLK_CNTR_INIT_VAL_VEC << 16)
+ | (FEA_STATUS_DEV_ADDR << 8) | SPI_CFG);
+
+ reg = dev_cmd_reg_addr(nandc, NAND_FLASH_SPI_CFG);
+ nandc_write(nandc, reg, 0);
+ nandc_write(nandc, reg, spi_cfg_val);
+ spi_cfg_val &= ~LOAD_CLK_CNTR_INIT_EN;
+ nandc_write(nandc, reg, spi_cfg_val);
+
+ reg = dev_cmd_reg_addr(nandc, NAND_DEV_CMD0);
+ nandc_write(nandc, reg, CMD0_VAL);
+ nandc_write(nandc, reg + 4, CMD1_VAL);
+ nandc_write(nandc, reg + 8, CMD2_VAL);
+ nandc_write(nandc, reg + 12, CMD_VLD_VAL);
+ nandc_write(nandc, reg + 16, CMD7_VAL);
+ reg = dev_cmd_reg_addr(nandc, NAND_DEV_CMD3);
+ nandc_write(nandc, reg, CMD3_VAL);
+
+ reg = dev_cmd_reg_addr(nandc, NAND_SPI_NUM_ADDR_CYCLES);
+ nandc_write(nandc, reg, SPI_NUM_ADDR);
+ nandc_write(nandc, reg + 4, WAIT_CNT);
+}
+
static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
struct qcom_nand_host *host,
struct device_node *dn)
@@ -3295,6 +3430,9 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
/* set up initial status value */
host->status = NAND_STATUS_READY | NAND_STATUS_WP;
+ if (nandc->props->is_serial_nand)
+ qspi_nand_init(nandc);
+
ret = nand_scan(chip, 1);
if (ret)
return ret;
@@ -3399,6 +3537,12 @@ static int qcom_nandc_probe(struct platform_device *pdev)
if (IS_ERR(nandc->aon_clk))
return PTR_ERR(nandc->aon_clk);
+ if (nandc->props->is_serial_nand) {
+ nandc->iomacro_clk = devm_clk_get(dev, "io_macro");
+ if (IS_ERR(nandc->iomacro_clk))
+ return PTR_ERR(nandc->iomacro_clk);
+ }
+
ret = qcom_nandc_parse_dt(pdev);
if (ret)
return ret;
@@ -3426,6 +3570,12 @@ static int qcom_nandc_probe(struct platform_device *pdev)
if (ret)
goto err_nandc_alloc;
+ if (nandc->props->is_serial_nand) {
+ ret = clk_prepare_enable(nandc->iomacro_clk);
+ if (ret)
+ goto err_setup;
+ }
+
ret = qcom_nandc_setup(nandc);
if (ret)
goto err_setup;
@@ -3477,6 +3627,7 @@ static const struct qcom_nandc_props ipq806x_nandc_props = {
.is_bam = false,
.use_codeword_fixup = true,
.dev_cmd_reg_start = 0x0,
+ .is_serial_nand = false,
};
static const struct qcom_nandc_props ipq4019_nandc_props = {
@@ -3484,6 +3635,7 @@ static const struct qcom_nandc_props ipq4019_nandc_props = {
.is_bam = true,
.is_qpic = true,
.dev_cmd_reg_start = 0x0,
+ .is_serial_nand = false,
};
static const struct qcom_nandc_props ipq8074_nandc_props = {
@@ -3491,6 +3643,15 @@ static const struct qcom_nandc_props ipq8074_nandc_props = {
.is_bam = true,
.is_qpic = true,
.dev_cmd_reg_start = 0x7000,
+ .is_serial_nand = false,
+};
+
+static const struct qcom_nandc_props ipq5018_nandc_props = {
+ .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
+ .is_bam = true,
+ .qpic_v2 = true,
+ .dev_cmd_reg_start = 0x7000,
+ .is_serial_nand = true,
};
static const struct qcom_nandc_props sdx55_nandc_props = {
@@ -3526,6 +3687,10 @@ static const struct of_device_id qcom_nandc_of_match[] = {
.compatible = "qcom,sdx55-nand",
.data = &sdx55_nandc_props,
},
+ {
+ .compatible = "qcom,ipq5018-nand",
+ .data = &ipq5018_nandc_props,
+ },
{}
};
MODULE_DEVICE_TABLE(of, qcom_nandc_of_match);
@@ -3542,4 +3707,4 @@ module_platform_driver(qcom_nandc_driver);
MODULE_AUTHOR("Archit Taneja <architt@codeaurora.org>");
MODULE_DESCRIPTION("Qualcomm NAND Controller driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL v2");
\ No newline at end of file
--
2.43.0
试试这个,测试过,基于linux-6.6内核
看到你也在研究 IPQ5018,我最近也在搞这个,但我水平实在太业余,网上找到一些源码算是编译出来了,但因为试的机子是 PZ-L8,使用的是 ESMT F50D1G41LB 闪存,启动时就识别不正常,前一句还正常识别nand: device found, Manufacturer ID: 0xa1, Chip ID: 0xa5,后面就是nand: unknown nand 2gib 1,8v 8-bit这样的错误信息,原厂固件显示的正常的应该是nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 128。所以考虑到是不是源码不支持这个闪存。请问怎么添加这个闪存的支持?