Loading drivers/mtd/nand/spi/fmsh.c +72 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,13 @@ #include <linux/kernel.h> #include <linux/mtd/spinand.h> #define FM25S01BI3_STATUS_ECC_MASK (7 << 4) #define FM25S01BI3_STATUS_ECC_NO_BITFLIPS (0 << 4) #define FM25S01BI3_STATUS_ECC_1_3_BITFLIPS (1 << 4) #define FM25S01BI3_STATUS_ECC_UNCOR_ERROR (2 << 4) #define FM25S01BI3_STATUS_ECC_4_6_BITFLIPS (3 << 4) #define FM25S01BI3_STATUS_ECC_7_8_BITFLIPS (5 << 4) #define SPINAND_MFR_FMSH 0xA1 static SPINAND_OP_VARIANTS(read_cache_variants, Loading Loading @@ -45,11 +52,66 @@ static int fm25s01a_ooblayout_free(struct mtd_info *mtd, int section, return 0; } static int fm25s01bi3_ecc_get_status(struct spinand_device *spinand, u8 status) { switch (status & FM25S01BI3_STATUS_ECC_MASK) { case FM25S01BI3_STATUS_ECC_NO_BITFLIPS: return 0; case FM25S01BI3_STATUS_ECC_UNCOR_ERROR: return -EBADMSG; case FM25S01BI3_STATUS_ECC_1_3_BITFLIPS: return 3; case FM25S01BI3_STATUS_ECC_4_6_BITFLIPS: return 6; case FM25S01BI3_STATUS_ECC_7_8_BITFLIPS: return 8; default: break; } return -EINVAL; } static int fm25s01bi3_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *region) { if (section) return -ERANGE; region->offset = 64; region->length = 64; return 0; } static int fm25s01bi3_ooblayout_free(struct mtd_info *mtd, int section, struct mtd_oob_region *region) { if (section > 3) return -ERANGE; region->offset = (16 * section) + 4; region->length = 12; return 0; } static const struct mtd_ooblayout_ops fm25s01a_ooblayout = { .ecc = fm25s01a_ooblayout_ecc, .free = fm25s01a_ooblayout_free, }; static const struct mtd_ooblayout_ops fm25s01bi3_ooblayout = { .ecc = fm25s01bi3_ooblayout_ecc, .free = fm25s01bi3_ooblayout_free, }; static const struct spinand_info fmsh_spinand_table[] = { SPINAND_INFO("FM25S01A", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), Loading @@ -60,6 +122,16 @@ static const struct spinand_info fmsh_spinand_table[] = { &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), SPINAND_INFO("FM25S01BI3", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd4), NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&fm25s01bi3_ooblayout, fm25s01bi3_ecc_get_status)), }; static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = { Loading Loading
drivers/mtd/nand/spi/fmsh.c +72 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,13 @@ #include <linux/kernel.h> #include <linux/mtd/spinand.h> #define FM25S01BI3_STATUS_ECC_MASK (7 << 4) #define FM25S01BI3_STATUS_ECC_NO_BITFLIPS (0 << 4) #define FM25S01BI3_STATUS_ECC_1_3_BITFLIPS (1 << 4) #define FM25S01BI3_STATUS_ECC_UNCOR_ERROR (2 << 4) #define FM25S01BI3_STATUS_ECC_4_6_BITFLIPS (3 << 4) #define FM25S01BI3_STATUS_ECC_7_8_BITFLIPS (5 << 4) #define SPINAND_MFR_FMSH 0xA1 static SPINAND_OP_VARIANTS(read_cache_variants, Loading Loading @@ -45,11 +52,66 @@ static int fm25s01a_ooblayout_free(struct mtd_info *mtd, int section, return 0; } static int fm25s01bi3_ecc_get_status(struct spinand_device *spinand, u8 status) { switch (status & FM25S01BI3_STATUS_ECC_MASK) { case FM25S01BI3_STATUS_ECC_NO_BITFLIPS: return 0; case FM25S01BI3_STATUS_ECC_UNCOR_ERROR: return -EBADMSG; case FM25S01BI3_STATUS_ECC_1_3_BITFLIPS: return 3; case FM25S01BI3_STATUS_ECC_4_6_BITFLIPS: return 6; case FM25S01BI3_STATUS_ECC_7_8_BITFLIPS: return 8; default: break; } return -EINVAL; } static int fm25s01bi3_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *region) { if (section) return -ERANGE; region->offset = 64; region->length = 64; return 0; } static int fm25s01bi3_ooblayout_free(struct mtd_info *mtd, int section, struct mtd_oob_region *region) { if (section > 3) return -ERANGE; region->offset = (16 * section) + 4; region->length = 12; return 0; } static const struct mtd_ooblayout_ops fm25s01a_ooblayout = { .ecc = fm25s01a_ooblayout_ecc, .free = fm25s01a_ooblayout_free, }; static const struct mtd_ooblayout_ops fm25s01bi3_ooblayout = { .ecc = fm25s01bi3_ooblayout_ecc, .free = fm25s01bi3_ooblayout_free, }; static const struct spinand_info fmsh_spinand_table[] = { SPINAND_INFO("FM25S01A", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), Loading @@ -60,6 +122,16 @@ static const struct spinand_info fmsh_spinand_table[] = { &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), SPINAND_INFO("FM25S01BI3", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd4), NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&fm25s01bi3_ooblayout, fm25s01bi3_ecc_get_status)), }; static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = { Loading