跳转至

常见问题

1.编译执行make时报文件系统权限不够的问题

==================================================
target/allwinner/v851s-lizard/tina_busybox-init-basefiles.mk is called to generate shell scripts
==================================================
(/home/book/workspace/tina-v853/openwrt/target/v851s/v851s-lizard/busybox-init-base-files_generate/rootfs_hook_squash.sh /home/book/workspace/tina-v853/openwrt/target/v851s/v851s-lizard/busybox-init-base-files >/dev/null) || { \
    echo "Execute the /home/book/workspace/tina-v853/openwrt/target/v851s/v851s-lizard/busybox-init-base-files_generate/rootfs_hook_squash.sh is failed"; \
    exit 1; \
}
/bin/sh: 1: /home/book/workspace/tina-v853/openwrt/target/v851s/v851s-lizard/busybox-init-base-files_generate/rootfs_hook_squash.sh: Permission denied
Execute the /home/book/workspace/tina-v853/openwrt/target/v851s/v851s-lizard/busybox-init-base-files_generate/rootfs_hook_squash.sh is failed
tina_busybox-init-base-files.mk:14: recipe for target 'all' failed
make[4]: *** [all] Error 1
make[4]: Leaving directory '/home/book/workspace/tina-v853/openwrt/target/v851s/v851s-lizard'
Makefile:228: recipe for target '/home/book/workspace/tina-v853/out/v851s/lizard/openwrt/build_dir/target/linux-v851s-lizard/busybox-init-base-files/.built' failed
make[3]: *** [/home/book/workspace/tina-v853/out/v851s/lizard/openwrt/build_dir/target/linux-v851s-lizard/busybox-init-base-files/.built] Error 2
make[3]: Leaving directory '/home/book/workspace/tina-v853/openwrt/package/allwinner/system/busybox-init-base-files'
time: package/subpackage/allwinner/system/busybox-init-base-files/compile#0.32#0.25#0.55
    ERROR: package/subpackage/allwinner/system/busybox-init-base-files failed to build.
package/Makefile:114: recipe for target 'package/subpackage/allwinner/system/busybox-init-base-files/compile' failed
make[2]: *** [package/subpackage/allwinner/system/busybox-init-base-files/compile] Error 1
make[2]: Leaving directory '/home/book/workspace/tina-v853/openwrt/openwrt'
package/Makefile:110: recipe for target '/home/book/workspace/tina-v853/openwrt/openwrt/staging_dir/target/stamp/.package_compile' failed
make[1]: *** [/home/book/workspace/tina-v853/openwrt/openwrt/staging_dir/target/stamp/.package_compile] Error 2
make[1]: Leaving directory '/home/book/workspace/tina-v853/openwrt/openwrt'
/home/book/workspace/tina-v853/openwrt/openwrt/include/toplevel.mk:236: recipe for target 'world' failed
make: *** [world] Error 2
make: Leaving directory '/home/book/workspace/tina-v853/openwrt/openwrt'
INFO: build_openwrt_rootfs failed

解决办法是按如下方式增加文件权限

book@100ask:~/workspace/tina-v853$ chmod 755 /home/book/workspace/tina-v853/openwrt/target/v851s/v851s-lizard/busybox-init-base-files_generate/mk_extra_dir.sh

2.打包pack时提示文件系统大小太大

ERROR: dl file rootfs.fex size too large
ERROR: filename = rootfs.fex
ERROR: dl_file_size = 53760 sector
ERROR: part_size = 45360 sector
update_for_part_info -1
ERROR: update mbr file fail
ERROR: update_mbr failed

原本的part_size的值为45360,需要修改成dl_file_size的值53760

book@100ask:~/tina-v853$ vim device/config/chips/v851s/configs/lizard/linux-4.9/sys_partition.fex

YuzukiHD-Lizard-03-2-Question-1

3.开发板启动时,启动nand失败

[    4.087239]
[    4.087836] device_chose finished 122!
[    4.133404] Please append a correct "root=" boot option; here are the available partitions:
[    4.142801] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[    4.152057] CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.191 #1
[    4.158582] Hardware name: sun8iw21
[    4.162517] [<c010d5a0>] (unwind_backtrace) from [<c010a694>] (show_stack+0x10/0x14)
[    4.171192] [<c010a694>] (show_stack) from [<c017050c>] (panic+0xac/0x2b8)
[    4.178899] [<c017050c>] (panic) from [<c09012cc>] (mount_block_root+0x258/0x300)
[    4.187284] [<c09012cc>] (mount_block_root) from [<c0901500>] (prepare_namespace+0x118/0x178)
[    4.196834] [<c0901500>] (prepare_namespace) from [<c0900eb4>] (kernel_init_freeable+0x144/0x178)
[    4.206771] [<c0900eb4>] (kernel_init_freeable) from [<c067464c>] (kernel_init+0x8/0x118)
[    4.215932] [<c067464c>] (kernel_init) from [<c0106e08>] (ret_from_fork+0x14/0x2c)
[    4.224410] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[    4.234532] sunxi dump enabled
[    4.237944] dump regs done
[    4.241001] flush cache done
[    4.244239] crashdump enter

在/tina-v853/kernel/linux-4.9/drivers/mtd/awnand/spinand/physic/目录下,将我们提供的id.c文件替换原本目录中的id.c文件。id.c文件内容为:

// SPDX-License-Identifier: GPL-2.0

#define pr_fmt(fmt) "sunxi-spinand-phy: " fmt

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/aw-spinand.h>
#include <linux/of.h>

#include "physic.h"

#define KB (1024)
#define MB (KB * 1024)
#define to_kb(size) (size / KB)
#define to_mb(size) (size / MB)

/* manufacture num */
#define MICRON_MANUFACTURE  0x2c
#define GD_MANUFACTURE      0xc8
#define ATO_MANUFACTURE     0x9b
#define WINBOND_MANUFACTURE 0xef
#define MXIC_MANUFACTURE    0xc2
#define TOSHIBA_MANUFACTURE 0x98
#define ETRON_MANUFACTURE   0xd5
#define XTXTECH_MANUFACTURE 0x0b
#define DSTECH_MANUFACTURE  0xe5
#define FORESEE_MANUFACTURE 0xcd
#define ZETTA_MANUFACTURE   0xba
#define FM_MANUFACTURE      0xa1

struct spinand_manufacture m;

struct aw_spinand_phy_info gigadevice[] = {
    {
        .Model      = "GD5F1GQ4UCYIG",
        .NandID     = {0xc8, 0xb1, 0x48, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ | SPINAND_ONEDUMMY_AFTER_RANDOMREAD,
        .MaxEraseTimes  = 50000,
        .EccType    = BIT3_LIMIT2_TO_6_ERR7,
        .EccProtectedType = SIZE16_OFF0_LEN16,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        .Model      = "GD5F1GQ4UBYIG",
        .NandID     = {0xc8, 0xd1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .EccFlag    = HAS_EXT_ECC_SE01,
        .EccType    = BIT4_LIMIT5_TO_7_ERR8_LIMIT_12,
        .EccProtectedType = SIZE16_OFF4_LEN8_OFF4,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        /* GD5F2GQ4UB9IG did not check yet */
        .Model      = "GD5F2GQ4UB9IG",
        .NandID     = {0xc8, 0xd2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 2048,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .EccFlag    = HAS_EXT_ECC_SE01,
        .EccType    = BIT4_LIMIT5_TO_7_ERR8_LIMIT_12,
        .EccProtectedType = SIZE16_OFF4_LEN12,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        .Model    = "GD5F1GQ5UEYIG",
        .NandID    = {0xc8, 0x51, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie  = 1024,
        .OobSizePerPage = 64,
        .OperationOpt  = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .EccFlag  = HAS_EXT_ECC_SE01,
        .EccType  = BIT4_LIMIT5_TO_7_ERR8_LIMIT_12,
        .EccProtectedType = SIZE16_OFF4_LEN12,
        .BadBlockFlag  = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        .Model      = "F50L1G41LB(2M)",
        .NandID     = {0xc8, 0x01, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ | SPINAND_QUAD_NO_NEED_ENABLE,
        .MaxEraseTimes  = 65000,
        .EccType    = BIT2_LIMIT1_ERR2,
        .EccProtectedType = SIZE16_OFF4_LEN4_OFF8,
        .BadBlockFlag   = BAD_BLK_FLAG_FIRST_2_PAGE,
    },
    {
        .Model      = "GD5F2GM7UEYI",
        .NandID     = {0xc8, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 2048,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .EccFlag    = HAS_EXT_ECC_SE01,
        .EccType    = BIT4_LIMIT5_TO_7_ERR8_LIMIT_12,
        .EccProtectedType = SIZE16_OFF0_LEN16,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
};

struct aw_spinand_phy_info micron[] = {
    {
        .Model      = "MT29F1G01ABAGDWB",
        .NandID     = {0x2c, 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ | SPINAND_QUAD_NO_NEED_ENABLE,
        .MaxEraseTimes  = 65000,
        .EccType    = BIT3_LIMIT5_ERR2,
        .EccProtectedType = SIZE16_OFF32_LEN16,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        .Model      = "MT29F2G01ABAGDWB",
        .NandID     = {0x2c, 0x24, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 2048,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ | SPINAND_QUAD_NO_NEED_ENABLE,
        .MaxEraseTimes  = 65000,
        .EccType    = BIT3_LIMIT5_ERR2,
        .EccProtectedType = SIZE16_OFF32_LEN16,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
};

struct aw_spinand_phy_info xtx[] = {
    {
        /* XTX26G02A */
        .Model      = "XTX26G02A",
        .NandID     = {0x0B, 0xE2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 2048,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .ecc_status_shift = ECC_STATUS_SHIFT_2,
        .EccType    = BIT4_LIMIT5_TO_7_ERR8_LIMIT_12,
        .EccProtectedType = SIZE16_OFF8_LEN16,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        /* XTX26G02A */
        .Model      = "XTX26G01A",
        .NandID     = {0x0B, 0xE1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .ecc_status_shift = ECC_STATUS_SHIFT_2,
        .EccType    = BIT4_LIMIT5_TO_7_ERR8_LIMIT_12,
        .EccProtectedType = SIZE16_OFF8_LEN16,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        /* XT26G01C */
        .Model      = "XT26G01C",
        .NandID     = {0x0B, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .ecc_status_shift = ECC_STATUS_SHIFT_4,
        .EccType    = BIT4_LIMIT5_TO_8_ERR9_TO_15,
        .EccProtectedType = SIZE16_OFF0_LEN16,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        /* XT26G02C */
        .Model      = "XT26G02CWSIG",
        .NandID     = {0x0B, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 2048,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_DUAL_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .ecc_status_shift = ECC_STATUS_SHIFT_2,
        .EccType    = BIT4_LIMIT5_TO_7_ERR8_LIMIT_12,
        .EccProtectedType = SIZE16_OFF8_LEN16,
        .BadBlockFlag   = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
};

struct aw_spinand_phy_info fm[] = {
    {
        /* only rw stress test */
        .Model      = "FM25S01",
        .NandID     = {0xa1, 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ | SPINAND_QUAD_NO_NEED_ENABLE,
        .MaxEraseTimes  = 65000,
        .EccType    = BIT2_LIMIT1_ERR2,
        .EccProtectedType = SIZE16_OFF0_LEN16,
        .BadBlockFlag = BAD_BLK_FLAG_FIRST_2_PAGE,
    },
};

struct aw_spinand_phy_info etron[] = {

};

struct aw_spinand_phy_info toshiba[] = {

};

struct aw_spinand_phy_info ato[] = {

};

struct aw_spinand_phy_info mxic[] = {
    {
        .Model      = "MX35LF1GE4AB",
        .NandID     = {0xc2, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 65000,
        .EccFlag    = HAS_EXT_ECC_STATUS,
        .EccType    = BIT4_LIMIT3_TO_4_ERR15,
        /**
         * MX35LF1GE4AB should use SIZE16_OFF4_LEN12, however, in order
         * to compatibility with versions already sent to customers,
         * which do not use general physical layout, we used
         * SIZE16_OFF4_LEN4_OFF8 instead.
         */
        .EccProtectedType = SIZE16_OFF4_LEN4_OFF8,
        .BadBlockFlag = BAD_BLK_FLAG_FIRST_2_PAGE,
    },
    {
        .Model      = "MX35LF2GE4AD",
        .NandID     = {0xc2, 0x26, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 2048,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 65000,
        .EccFlag    = HAS_EXT_ECC_STATUS,
        .EccType    = BIT4_LIMIT5_TO_8_ERR9_TO_15,
        .EccProtectedType = SIZE16_OFF4_LEN4_OFF8,
        .BadBlockFlag = BAD_BLK_FLAG_FIRST_2_PAGE,
    },
};

struct aw_spinand_phy_info winbond[] = {
    {
        .Model      = "W25N01GVZEIG",
        .NandID     = {0xef, 0xaa, 0x21, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 65000,
        .EccType    = BIT2_LIMIT1_ERR2,
        .EccProtectedType = SIZE16_OFF4_LEN4_OFF8,
        .BadBlockFlag = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
};

struct aw_spinand_phy_info dosilicon[] = {
    {
        .Model      = "DS35X1GAXXX",
        .NandID     = {0xe5, 0x71, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 65000,
        .EccType    = BIT2_LIMIT1_ERR2,
        .EccProtectedType = SIZE16_OFF4_LEN4_OFF8,
        .BadBlockFlag = BAD_BLK_FLAG_FIRST_2_PAGE,
    },
};

struct aw_spinand_phy_info foresee[] = {
    {
        .Model      = "FS35ND01G-S1F1QWFI000",
        .NandID     = {0xcd, 0xb1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .EccType    = BIT3_LIMIT3_TO_4_ERR7,
        .EccProtectedType = SIZE16_OFF0_LEN16,
        .BadBlockFlag = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        .Model      = "FS35ND01G-S1Y2QWFI000",
        .NandID     = {0xcd, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .EccType    = BIT2_LIMIT1_ERR2,
        .EccProtectedType = SIZE16_OFF0_LEN16,
        .BadBlockFlag = BAD_BLK_FLAG_FRIST_1_PAGE,
    },
    {
        .Model      = "FS35SQA001G",
        .NandID     = {0xcd, 0x71, 0x71, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .EccType    = BIT2_LIMIT1_ERR2,
        .EccProtectedType = SIZE16_OFF0_LEN16,
        .BadBlockFlag = BAD_BLK_FLAG_FRIST_1_PAGE,
    }
};

struct aw_spinand_phy_info zetta[] = {
    {
        .Model      = "ZD35Q1GAIB",
        .NandID     = {0xba, 0x71, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
        .DieCntPerChip  = 1,
        .SectCntPerPage = 4,
        .PageCntPerBlk  = 64,
        .BlkCntPerDie   = 1024,
        .OobSizePerPage = 64,
        .OperationOpt   = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM |
            SPINAND_DUAL_READ,
        .MaxEraseTimes  = 50000,
        .EccType    = BIT2_LIMIT1_ERR2,
        .EccProtectedType = SIZE16_OFF4_LEN4_OFF8,
        .BadBlockFlag = BAD_BLK_FLAG_FIRST_2_PAGE,
    },
};

static const char *aw_spinand_info_model(struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    return pinfo->Model;
}

static void aw_spinand_info_nandid(struct aw_spinand_chip *chip,
        unsigned char *id, int cnt)
{
    int i;
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    cnt = min(cnt, MAX_ID_LEN);
    for (i = 0; i < cnt; i++)
        id[i] = pinfo->NandID[i];
}

static unsigned int aw_spinand_info_sector_size(struct aw_spinand_chip *chip)
{
    return 1 << SECTOR_SHIFT;
}

static unsigned int aw_spinand_info_phy_page_size(struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    return pinfo->SectCntPerPage * aw_spinand_info_sector_size(chip);
}

static unsigned int aw_spinand_info_page_size(struct aw_spinand_chip *chip)
{
#if IS_ENABLED(CONFIG_AW_SPINAND_SIMULATE_MULTIPLANE)
    return aw_spinand_info_phy_page_size(chip) * 2;
#else
    return aw_spinand_info_phy_page_size(chip);
#endif
}

static unsigned int aw_spinand_info_phy_block_size(
        struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    return pinfo->PageCntPerBlk * aw_spinand_info_phy_page_size(chip);
}

static unsigned int aw_spinand_info_block_size(struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    return pinfo->PageCntPerBlk * aw_spinand_info_page_size(chip);
}

static unsigned int aw_spinand_info_phy_oob_size(struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    return pinfo->OobSizePerPage;
}

static unsigned int aw_spinand_info_oob_size(struct aw_spinand_chip *chip)
{
#if IS_ENABLED(CONFIG_AW_SPINAND_SIMULATE_MULTIPLANE)
    return aw_spinand_info_phy_oob_size(chip) * 2;
#else
    return aw_spinand_info_phy_oob_size(chip);
#endif
}

static unsigned int aw_spinand_info_die_cnt(struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    return pinfo->DieCntPerChip;
}

static unsigned int aw_spinand_info_total_size(struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    return pinfo->DieCntPerChip * pinfo->BlkCntPerDie *
        aw_spinand_info_phy_block_size(chip);
}

static int aw_spinand_info_operation_opt(struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    return pinfo->OperationOpt;
}

static int aw_spinand_info_max_erase_times(struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo = chip->info->phy_info;

    return pinfo->MaxEraseTimes;
}

struct spinand_manufacture {
    unsigned char id;
    const char *name;
    struct aw_spinand_phy_info *info;
    unsigned int cnt;
};

#define SPINAND_FACTORY_INFO(_id, _name, _info)         \
    {                           \
        .id = _id,                  \
        .name = _name,                  \
        .info = _info,                  \
        .cnt = ARRAY_SIZE(_info),           \
    }
static struct spinand_manufacture spinand_factory[] = {
    SPINAND_FACTORY_INFO(MICRON_MANUFACTURE, "Micron", micron),
    SPINAND_FACTORY_INFO(GD_MANUFACTURE, "GD", gigadevice),
    SPINAND_FACTORY_INFO(ATO_MANUFACTURE, "ATO", ato),
    SPINAND_FACTORY_INFO(WINBOND_MANUFACTURE, "Winbond", winbond),
    SPINAND_FACTORY_INFO(MXIC_MANUFACTURE, "Mxic", mxic),
    SPINAND_FACTORY_INFO(TOSHIBA_MANUFACTURE, "Toshiba", toshiba),
    SPINAND_FACTORY_INFO(ETRON_MANUFACTURE, "Etron", etron),
    SPINAND_FACTORY_INFO(XTXTECH_MANUFACTURE, "XTX", xtx),
    SPINAND_FACTORY_INFO(DSTECH_MANUFACTURE, "Dosilicon", dosilicon),
    SPINAND_FACTORY_INFO(FORESEE_MANUFACTURE, "Foresee", foresee),
    SPINAND_FACTORY_INFO(ZETTA_MANUFACTURE, "Zetta", zetta),
    SPINAND_FACTORY_INFO(FM_MANUFACTURE, "FM", fm),
};


static int spinand_get_chip_munufacture(struct aw_spinand_chip *chip, const char **m)
{
    struct aw_spinand_phy_info *info = chip->info->phy_info;

    switch (info->NandID[0]) {
    case MICRON_MANUFACTURE:
        *m = "Micron";
    break;
    case GD_MANUFACTURE:
        *m = "GD";
    break;
    case ATO_MANUFACTURE:
        *m = "ATO";
    break;
    case WINBOND_MANUFACTURE:
        *m = "Winbond";
    break;
    case MXIC_MANUFACTURE:
        *m = "Mxic";
    break;
    case TOSHIBA_MANUFACTURE:
        *m = "Toshiba";
    break;
    case ETRON_MANUFACTURE:
        *m = "Etron";
    break;
    case XTXTECH_MANUFACTURE:
        *m = "XTX";
    break;
    case DSTECH_MANUFACTURE:
        *m = "Dosilicon";
    break;
    case FORESEE_MANUFACTURE:
        *m = "Foresee";
    break;
    case ZETTA_MANUFACTURE:
        *m = "Zetta";
    break;
    default:
        *m = NULL;
    break;
    }

    if (*m == NULL)
        return false;
    else
        return true;

}
static const char *aw_spinand_info_manufacture(struct aw_spinand_chip *chip)
{
    int i, j;
    struct spinand_manufacture *m;
    struct aw_spinand_phy_info *pinfo;
    const char *m_name = NULL;
    int ret = 0;

    for (i = 0; i < ARRAY_SIZE(spinand_factory); i++) {
        m = &spinand_factory[i];
        pinfo = chip->info->phy_info;
        for (j = 0; j < m->cnt; j++)
            if (pinfo == &m->info[j])
                return m->name;
    }

    /*for compatible fdt support spi-nand*/
    ret = spinand_get_chip_munufacture(chip, &m_name);
    if (ret < 0)
        return NULL;
    else
        return m_name;
}

static struct spinand_manufacture *spinand_detect_munufacture(unsigned char id)
{
    int index;
    struct spinand_manufacture *m;

    for (index = 0; index < ARRAY_SIZE(spinand_factory); index++) {
        m = &spinand_factory[index];
        if (m->id == id) {
            pr_info("detect munufacture from id table: %s\n", m->name);
            return m;
        }
    }

    pr_err("not detect any munufacture from id table\n");
    return NULL;
}

static struct aw_spinand_phy_info *spinand_match_id(
        struct spinand_manufacture *m,
        unsigned char *id)
{
    int i, j, match_max = 1, match_index = 0;
    struct aw_spinand_phy_info *pinfo;

    for (i = 0; i < m->cnt; i++) {
        int match = 1;

        pinfo = &m->info[i];
        for (j = 1; j < MAX_ID_LEN; j++) {
            /* 0xFF matching all ID value */
            if (pinfo->NandID[j] != id[j] &&
                    pinfo->NandID[j] != 0xFF)
                break;

            if (pinfo->NandID[j] != 0xFF)
                match++;
        }

        if (match > match_max) {
            match_max = match;
            match_index = i;
        }
    }

    if (match_max > 1)
        return &m->info[match_index];
    return NULL;
}

struct aw_spinand_phy_info *spinand_get_phy_info_from_fdt(struct aw_spinand_chip *chip)
{
    static struct aw_spinand_phy_info info;
    static int had_get;
    int ret = 0;
    const char *bad_blk_mark_pos = NULL;
    const char *quad_read_not_need_enable = NULL;
    const char *read_seq_need_onedummy = NULL;
    int len = 0;
    u32 id = 0xffffffff;
    struct device_node *node = chip->spi->dev.of_node;
    u32 rx_bus_width = 0;
    u32 tx_bus_width = 0;


    if (had_get == true)
        return &info;

#define BAD_BLK_MARK_POS1 "first_1_page"
#define BAD_BLK_MARK_POS2 "first_2_page"
#define BAD_BLK_MARK_POS3 "last_1_page"
#define BAD_BLK_MARK_POS4 "last_2_page"
    memset(&info, 0, sizeof(struct aw_spinand_phy_info));

    ret = of_property_read_string(node, "model", &(info.Model));
    if (ret < 0) {
        pr_err("get spi-nand Model from fdt fail\n");
        goto err;
    }

    ret = of_property_read_u32(node, "id-0", &id);
    if (ret < 0) {
        pr_err("get spi-nand id Low 4 Byte from fdt fail\n");
        goto err;
    }
    len = sizeof(id);
    memmove(info.NandID, &id, min(MAX_ID_LEN, len));

    id = 0xffffffff;
    ret = of_property_read_u32(node, "id-1", &id);
    if (ret < 0) {
        pr_info("can't get spi-nand id high 4 Byte from fdt, may be not need\n");
    }
    memmove(info.NandID + min(MAX_ID_LEN, len), &id, max(MAX_ID_LEN, len) - min(MAX_ID_LEN, len));

    ret = of_property_read_u32(node, "die_cnt_per_chip", &(info.DieCntPerChip));
    if (ret < 0) {
        pr_err("get spi-nand DieCntPerChip from fdt fail\n");
        goto err;
    }

    ret = of_property_read_u32(node, "blk_cnt_per_die", &(info.BlkCntPerDie));
    if (ret < 0) {
        pr_err("get spi-nand BlkCntPerDie from fdt fail\n");
        goto err;
    }

    ret = of_property_read_u32(node, "page_cnt_per_blk", &(info.PageCntPerBlk));
    if (ret < 0) {
        pr_err("get spi-nand PageCntPerBlk from fdt fail\n");
        goto err;
    }

    ret = of_property_read_u32(node, "sect_cnt_per_page", &(info.SectCntPerPage));
    if (ret < 0) {
        pr_err("get spi-nand SectCntPerPage from fdt fail\n");
        goto err;
    }

    ret = of_property_read_u32(node, "oob_size_per_page", &(info.OobSizePerPage));
    if (ret < 0) {
        pr_err("get spi-nand OobSizePerPage from fdt fail\n");
        goto err;
    }

    ret = of_property_read_string(node, "bad_block_mark_pos", &bad_blk_mark_pos);
    if (ret < 0 || NULL == bad_blk_mark_pos) {
        pr_err("get spi-nand BadBlockFlag from fdt fail\n");
        goto err;
    } else {
        if (!memcmp(bad_blk_mark_pos, BAD_BLK_MARK_POS1, strlen(BAD_BLK_MARK_POS1)))
            info.BadBlockFlag = BAD_BLK_FLAG_FRIST_1_PAGE;
        else if (!memcmp(bad_blk_mark_pos, BAD_BLK_MARK_POS2, strlen(BAD_BLK_MARK_POS2)))
            info.BadBlockFlag = BAD_BLK_FLAG_FRIST_1_PAGE;
        else if (!memcmp(bad_blk_mark_pos, BAD_BLK_MARK_POS3, strlen(BAD_BLK_MARK_POS3)))
            info.BadBlockFlag = BAD_BLK_FLAG_LAST_1_PAGE;
        else if (!memcmp(bad_blk_mark_pos, BAD_BLK_MARK_POS4, strlen(BAD_BLK_MARK_POS4)))
            info.BadBlockFlag = BAD_BLK_FLAG_LAST_2_PAGE;
        else {
            pr_err("get spi-nand BadBlockFlag pattern is not right\n");
            goto err;
        }
    }

    ret = of_property_read_s32(node, "max_erase_times", &(info.MaxEraseTimes));
    if (ret < 0) {
        pr_err("get spi-nand MaxEraseTimes from fdt fail\n");
        goto err;
    }

    ret = of_property_read_u32(node, "ecc_type", &(info.EccType));
    if (ret < 0) {
        pr_err("get spi-nand EccFlag from fdt fail\n");
        goto err;
    }

    ret = of_property_read_u32(node, "ecc_protected_type", &(info.EccProtectedType));
    if (ret < 0) {
        pr_err("get spi-nand ecc_protected_type from fdt fail\n");
        goto err;
    }

    ret = of_property_read_u32(node, "spi-rx-bus-width", &rx_bus_width);
    if (ret < 0) {
        pr_err("get spi-nand spi-rx-bus-width from fdt fail\n");
        goto err;
    } else {
        switch (rx_bus_width) {
        case SPI_NBITS_DUAL:
            info.OperationOpt |= SPINAND_DUAL_READ;
        break;
        case SPI_NBITS_QUAD:
            info.OperationOpt |= SPINAND_QUAD_READ;
        break;
        default:
            info.OperationOpt |= 0;
        break;
        }
    }

    ret = of_property_read_u32(node, "spi-tx-bus-width", &tx_bus_width);
    if (ret < 0) {
        pr_err("get spi-nand spi-tx-bus-width from fdt fail\n");
        goto err;
    } else {
        switch (tx_bus_width) {
        case SPI_NBITS_QUAD:
            info.OperationOpt |= SPINAND_QUAD_PROGRAM;
        break;
        default:
            info.OperationOpt |= 0;
        break;
        }
    }

    ret = of_property_read_string(node, "read_from_cache_x4_not_need_enable",
            &quad_read_not_need_enable);
    pr_info("%d quad_read_not_need_enable:%s\n", __LINE__, quad_read_not_need_enable);
    if (ret < 0 || NULL == quad_read_not_need_enable) {
        pr_info("can't get spi-nand read_from_cache_x4_need_enable or it is null,"
                " maybe not need enable quad read before read from cache x4\n");
    } else {
        if (!memcmp(quad_read_not_need_enable, "yes", strlen("yes")))
            info.OperationOpt |= SPINAND_QUAD_NO_NEED_ENABLE;
    }

    ret = of_property_read_string(node, "read_from_cache_need_onedummy",
            &read_seq_need_onedummy);
    if (ret < 0 || NULL == read_seq_need_onedummy) {
        pr_info("can't get spi-nand read_from_cache_need_onedummy or it is null,"
                " maybe read from cache sequence not need one dummy in second Byte\n");
    } else {
        if (!memcmp(read_seq_need_onedummy, "yes", strlen("yes")))
            info.OperationOpt |= SPINAND_ONEDUMMY_AFTER_RANDOMREAD;
    }


    ret = of_property_read_s32(node, "ecc_flag", &(info.EccFlag));
    if (ret < 0) {
        pr_err("can't get spi-nand EccFlag from fdt,"
                " maybe(default) use 0FH + C0H to get feature,wich obtain ecc status\n");
    }

    ret = of_property_read_u32(node, "ecc_status_shift", &(info.ecc_status_shift));
    if (ret < 0) {
        pr_info("can't get spi-nand ecc_status_shift from fdt,"
                " use default ecc_status_shift_4 to get ecc status in C0H\n");
    }

    pr_debug("get spinand phy info from fdt\n");
    pr_debug("Model:%s\n", info.Model);
    pr_debug("ID:%02x %02x %02x %02x %02x %02x %02x %02x\n",
            info.NandID[0], info.NandID[1], info.NandID[2], info.NandID[3],
            info.NandID[4], info.NandID[5], info.NandID[6], info.NandID[7]);
    pr_debug("DieCntPerChip:%d\n", info.DieCntPerChip);
    pr_debug("BlkCntPerDie:%d\n", info.BlkCntPerDie);
    pr_debug("PageCntPerBlk:%d\n", info.PageCntPerBlk);
    pr_debug("SectCntPerPage:%d\n", info.SectCntPerPage);
    pr_debug("OobSizePerPage:%d\n", info.OobSizePerPage);
    pr_debug("BadBlockFlag:%d\n", info.BadBlockFlag);
    pr_debug("OperationOpt:0x%x\n", info.OperationOpt);
    pr_debug("MaxEraseTimes:%d\n", info.MaxEraseTimes);
    pr_debug("EccFlag:%x\n", info.EccFlag);
    pr_debug("ecc_status_shift:%x\n", info.ecc_status_shift);
    pr_debug("EccType:%x\n", info.EccType);
    pr_debug("EccProtectedType:%x\n", info.EccProtectedType);

    had_get = true;

    return &info;
err:
    had_get = false;
    return NULL;
}

static struct aw_spinand_info aw_spinand_info = {
    .model = aw_spinand_info_model,
    .manufacture = aw_spinand_info_manufacture,
    .nandid = aw_spinand_info_nandid,
    .die_cnt = aw_spinand_info_die_cnt,
    .oob_size = aw_spinand_info_oob_size,
    .page_size = aw_spinand_info_page_size,
    .block_size = aw_spinand_info_block_size,
    .phy_oob_size = aw_spinand_info_phy_oob_size,
    .phy_page_size = aw_spinand_info_phy_page_size,
    .phy_block_size = aw_spinand_info_phy_block_size,
    .sector_size = aw_spinand_info_sector_size,
    .total_size = aw_spinand_info_total_size,
    .operation_opt = aw_spinand_info_operation_opt,
    .max_erase_times = aw_spinand_info_max_erase_times,
};

static struct spinand_manufacture *spinand_detect_munufacture_from_fdt(struct aw_spinand_chip *chip, unsigned char id)
{
    struct aw_spinand_phy_info *info = NULL;
    struct spinand_manufacture *pm = &m;
    int ret = 0;

    info = spinand_get_phy_info_from_fdt(chip);
    if (info == NULL) {
        pr_err("get phy info from fdt fail\n");
        goto err;
    }

    if (id == info->NandID[0]) {
        pm->id = info->NandID[0];
        pm->info = info;
        chip->info = &aw_spinand_info;
        chip->info->phy_info = info;
        ret = spinand_get_chip_munufacture(chip, &(pm->name));
        if (ret < 0)
            goto err;
        else
            pr_info("detect munufacture from fdt: %s \n", pm->name);
    } else {
        goto err;
    }

    return pm;
err:
    pr_info("not detect munufacture from fdt\n");
    return NULL;
}

static struct aw_spinand_phy_info *spinand_match_id_from_fdt(struct aw_spinand_chip *chip,
        struct spinand_manufacture *m,
        unsigned char *id)
{
    struct aw_spinand_phy_info *info = NULL;
    int i = 0;

    info = spinand_get_phy_info_from_fdt(chip);
    if (info == NULL) {
        pr_err("get phy info from fdt fail\n");
        goto err;
    }

    for (i = 0; i < MAX_ID_LEN; i++) {
        /*0xff match all id value*/
        if (id[i] != info->NandID[i] && info->NandID[i] != 0xff)
            goto err;
    }

    return info;

err:
    return NULL;
}
static int aw_spinand_info_init(struct aw_spinand_chip *chip,
        struct aw_spinand_phy_info *pinfo)
{
    chip->info = &aw_spinand_info;
    chip->info->phy_info = pinfo;

    pr_info("========== arch info ==========\n");
    pr_info("Model:               %s\n", pinfo->Model);
    pr_info("Munufacture:         %s\n", aw_spinand_info_manufacture(chip));
    pr_info("DieCntPerChip:       %u\n", pinfo->DieCntPerChip);
    pr_info("BlkCntPerDie:        %u\n", pinfo->BlkCntPerDie);
    pr_info("PageCntPerBlk:       %u\n", pinfo->PageCntPerBlk);
    pr_info("SectCntPerPage:      %u\n", pinfo->SectCntPerPage);
    pr_info("OobSizePerPage:      %u\n", pinfo->OobSizePerPage);
    pr_info("BadBlockFlag:        0x%x\n", pinfo->BadBlockFlag);
    pr_info("OperationOpt:        0x%x\n", pinfo->OperationOpt);
    pr_info("MaxEraseTimes:       %d\n", pinfo->MaxEraseTimes);
    pr_info("EccFlag:             0x%x\n", pinfo->EccFlag);
    pr_info("EccType:             %d\n", pinfo->EccType);
    pr_info("EccProtectedType:    %d\n", pinfo->EccProtectedType);
    pr_info("========================================\n");
    pr_info("\n");
    pr_info("========== physical info ==========\n");
    pr_info("TotalSize:    %u M\n", to_mb(aw_spinand_info_total_size(chip)));
    pr_info("SectorSize:   %u B\n", aw_spinand_info_sector_size(chip));
    pr_info("PageSize:     %u K\n", to_kb(aw_spinand_info_phy_page_size(chip)));
    pr_info("BlockSize:    %u K\n", to_kb(aw_spinand_info_phy_block_size(chip)));
    pr_info("OOBSize:      %u B\n", aw_spinand_info_phy_oob_size(chip));
    pr_info("========================================\n");
    pr_info("\n");
    pr_info("========== logical info ==========\n");
    pr_info("TotalSize:    %u M\n", to_mb(aw_spinand_info_total_size(chip)));
    pr_info("SectorSize:   %u B\n", aw_spinand_info_sector_size(chip));
    pr_info("PageSize:     %u K\n", to_kb(aw_spinand_info_page_size(chip)));
    pr_info("BlockSize:    %u K\n", to_kb(aw_spinand_info_block_size(chip)));
    pr_info("OOBSize:      %u B\n", aw_spinand_info_oob_size(chip));
    pr_info("========================================\n");

    return 0;
}

int aw_spinand_chip_detect(struct aw_spinand_chip *chip)
{
    struct aw_spinand_phy_info *pinfo;
    struct spinand_manufacture *m;
    unsigned char id[MAX_ID_LEN] = {0xFF};
    struct aw_spinand_chip_ops *ops = chip->ops;
    int ret, dummy = 1;

retry:
    /*first read with dummy/address@0x00*/
    ret = ops->read_id(chip, id, MAX_ID_LEN, dummy);
    if (ret) {
        pr_err("read id failed : %d\n", ret);
        return ret;
    }

    m = spinand_detect_munufacture(id[0]);
    if (!m)
        goto detect_from_fdt;

    pinfo = spinand_match_id(m, id);
    if (pinfo)
        goto detect;

detect_from_fdt:
        m = spinand_detect_munufacture_from_fdt(chip, id[0]);
        if (!m)
            goto not_detect;

        pinfo = spinand_match_id_from_fdt(chip, m, id);
        if (pinfo)
            goto detect;

not_detect:
    /* retry without dummy/address@0x00 */
    if (dummy) {
        dummy = 0;
        goto retry;
    }
    pr_info("not match spinand: %x %x\n",
            *(__u32 *)id,
            *((__u32 *)id + 1));
    return -ENODEV;
detect:
    pr_info("detect spinand id: %x %x\n",
            *((__u32 *)pinfo->NandID),
            *((__u32 *)pinfo->NandID + 1));
    return aw_spinand_info_init(chip, pinfo);
}

MODULE_AUTHOR("liaoweixiong <liaoweixiong@allwinnertech.com>");
MODULE_DESCRIPTION("Commond physic layer for Allwinner's spinand driver");

重新编译打包

book@100ask:~/tina-v853$ make
...
book@100ask:~/tina-v853$ pack
...