| .. | .. |
|---|
| 10 | 10 | #include <linux/kernel.h> |
|---|
| 11 | 11 | #include <linux/mtd/spinand.h> |
|---|
| 12 | 12 | |
|---|
| 13 | | -#define SPINAND_MFR_UNIM 0xA1 |
|---|
| 13 | +#define SPINAND_MFR_UNIM_ZL 0xA1 |
|---|
| 14 | +#define SPINAND_MFR_UNIM 0xB0 |
|---|
| 14 | 15 | |
|---|
| 15 | 16 | static SPINAND_OP_VARIANTS(read_cache_variants, |
|---|
| 16 | 17 | SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), |
|---|
| .. | .. |
|---|
| 57 | 58 | .free = tx25g01_ooblayout_free, |
|---|
| 58 | 59 | }; |
|---|
| 59 | 60 | |
|---|
| 61 | + |
|---|
| 62 | +static int um19a0xisw_ooblayout_ecc(struct mtd_info *mtd, int section, |
|---|
| 63 | + struct mtd_oob_region *region) |
|---|
| 64 | +{ |
|---|
| 65 | + return -ERANGE; |
|---|
| 66 | +} |
|---|
| 67 | + |
|---|
| 68 | +static int um19a0xisw_ooblayout_free(struct mtd_info *mtd, int section, |
|---|
| 69 | + struct mtd_oob_region *region) |
|---|
| 70 | +{ |
|---|
| 71 | + if (section) |
|---|
| 72 | + return -ERANGE; |
|---|
| 73 | + |
|---|
| 74 | + region->offset = 2; |
|---|
| 75 | + region->length = 62; |
|---|
| 76 | + |
|---|
| 77 | + return 0; |
|---|
| 78 | +} |
|---|
| 79 | + |
|---|
| 80 | +static const struct mtd_ooblayout_ops um19a0xisw_ooblayout = { |
|---|
| 81 | + .ecc = um19a0xisw_ooblayout_ecc, |
|---|
| 82 | + .free = um19a0xisw_ooblayout_free, |
|---|
| 83 | +}; |
|---|
| 84 | + |
|---|
| 85 | +static int um19a1xisw_ooblayout_ecc(struct mtd_info *mtd, int section, |
|---|
| 86 | + struct mtd_oob_region *region) |
|---|
| 87 | +{ |
|---|
| 88 | + if (section) |
|---|
| 89 | + return -ERANGE; |
|---|
| 90 | + |
|---|
| 91 | + region->offset = 64; |
|---|
| 92 | + region->length = 64; |
|---|
| 93 | + |
|---|
| 94 | + return 0; |
|---|
| 95 | +} |
|---|
| 96 | + |
|---|
| 97 | +static int um19a1xisw_ooblayout_free(struct mtd_info *mtd, int section, |
|---|
| 98 | + struct mtd_oob_region *region) |
|---|
| 99 | +{ |
|---|
| 100 | + if (section) |
|---|
| 101 | + return -ERANGE; |
|---|
| 102 | + |
|---|
| 103 | + region->offset = 2; |
|---|
| 104 | + region->length = 62; |
|---|
| 105 | + |
|---|
| 106 | + return 0; |
|---|
| 107 | +} |
|---|
| 108 | + |
|---|
| 109 | +static const struct mtd_ooblayout_ops um19a1xisw_ooblayout = { |
|---|
| 110 | + .ecc = um19a1xisw_ooblayout_ecc, |
|---|
| 111 | + .free = um19a1xisw_ooblayout_free, |
|---|
| 112 | +}; |
|---|
| 113 | + |
|---|
| 60 | 114 | /* |
|---|
| 61 | 115 | * ecc bits: 0xC0[4,6] |
|---|
| 62 | 116 | * [0b000], No bit errors were detected; |
|---|
| .. | .. |
|---|
| 69 | 123 | static int tx25g01_ecc_get_status(struct spinand_device *spinand, |
|---|
| 70 | 124 | u8 status) |
|---|
| 71 | 125 | { |
|---|
| 72 | | - u8 eccsr = (status & GENMASK(6, 4)) >> 2; |
|---|
| 126 | + struct nand_device *nand = spinand_to_nand(spinand); |
|---|
| 127 | + u8 eccsr = (status & GENMASK(6, 4)) >> 4; |
|---|
| 73 | 128 | |
|---|
| 74 | | - if (eccsr <= 7) |
|---|
| 129 | + if (eccsr < 4) |
|---|
| 75 | 130 | return eccsr; |
|---|
| 76 | | - else if (eccsr == 12) |
|---|
| 77 | | - return 8; |
|---|
| 131 | + else if (eccsr == 4) |
|---|
| 132 | + return nanddev_get_ecc_requirements(nand)->strength; |
|---|
| 78 | 133 | else |
|---|
| 79 | 134 | return -EBADMSG; |
|---|
| 80 | 135 | } |
|---|
| 81 | 136 | |
|---|
| 82 | | -static const struct spinand_info unim_spinand_table[] = { |
|---|
| 137 | +/* |
|---|
| 138 | + * ecc bits: 0xC0[4,6] |
|---|
| 139 | + * [0b000], No bit errors were detected; |
|---|
| 140 | + * [0b001] and [0b011], 1~6 Bit errors were detected and corrected. Not |
|---|
| 141 | + * reach Flipping Bits; |
|---|
| 142 | + * [0b101], Bit error count equals the bit flip |
|---|
| 143 | + * detection threshold |
|---|
| 144 | + * [0b010], Multiple bit errors were detected and |
|---|
| 145 | + * not corrected. |
|---|
| 146 | + * others, Reserved. |
|---|
| 147 | + */ |
|---|
| 148 | +static int um19axxisw_ecc_ecc_get_status(struct spinand_device *spinand, |
|---|
| 149 | + u8 status) |
|---|
| 150 | +{ |
|---|
| 151 | + struct nand_device *nand = spinand_to_nand(spinand); |
|---|
| 152 | + u8 eccsr = (status & GENMASK(6, 4)) >> 4; |
|---|
| 153 | + |
|---|
| 154 | + if (eccsr <= 1 || eccsr == 3) |
|---|
| 155 | + return eccsr; |
|---|
| 156 | + else if (eccsr == 5) |
|---|
| 157 | + return nanddev_get_ecc_requirements(nand)->strength; |
|---|
| 158 | + else |
|---|
| 159 | + return -EBADMSG; |
|---|
| 160 | +} |
|---|
| 161 | + |
|---|
| 162 | +static const struct spinand_info unim_zl_spinand_table[] = { |
|---|
| 83 | 163 | SPINAND_INFO("TX25G01", |
|---|
| 84 | 164 | SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xF1), |
|---|
| 85 | 165 | NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), |
|---|
| .. | .. |
|---|
| 91 | 171 | SPINAND_ECCINFO(&tx25g01_ooblayout, tx25g01_ecc_get_status)), |
|---|
| 92 | 172 | }; |
|---|
| 93 | 173 | |
|---|
| 174 | +static const struct spinand_info unim_spinand_table[] = { |
|---|
| 175 | + SPINAND_INFO("UM19A1HISW", |
|---|
| 176 | + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24), |
|---|
| 177 | + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), |
|---|
| 178 | + NAND_ECCREQ(8, 512), |
|---|
| 179 | + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
|---|
| 180 | + &write_cache_variants, |
|---|
| 181 | + &update_cache_variants), |
|---|
| 182 | + SPINAND_HAS_QE_BIT, |
|---|
| 183 | + SPINAND_ECCINFO(&um19a1xisw_ooblayout, um19axxisw_ecc_ecc_get_status)), |
|---|
| 184 | + SPINAND_INFO("UM19A0HCSW", |
|---|
| 185 | + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), |
|---|
| 186 | + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), |
|---|
| 187 | + NAND_ECCREQ(8, 512), |
|---|
| 188 | + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
|---|
| 189 | + &write_cache_variants, |
|---|
| 190 | + &update_cache_variants), |
|---|
| 191 | + SPINAND_HAS_QE_BIT, |
|---|
| 192 | + SPINAND_ECCINFO(&um19a0xisw_ooblayout, um19axxisw_ecc_ecc_get_status)), |
|---|
| 193 | + SPINAND_INFO("UM19A0LCSW", |
|---|
| 194 | + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15), |
|---|
| 195 | + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), |
|---|
| 196 | + NAND_ECCREQ(8, 512), |
|---|
| 197 | + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
|---|
| 198 | + &write_cache_variants, |
|---|
| 199 | + &update_cache_variants), |
|---|
| 200 | + SPINAND_HAS_QE_BIT, |
|---|
| 201 | + SPINAND_ECCINFO(&um19a0xisw_ooblayout, um19axxisw_ecc_ecc_get_status)), |
|---|
| 202 | + SPINAND_INFO("UM19A1LISW", |
|---|
| 203 | + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25), |
|---|
| 204 | + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), |
|---|
| 205 | + NAND_ECCREQ(8, 512), |
|---|
| 206 | + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
|---|
| 207 | + &write_cache_variants, |
|---|
| 208 | + &update_cache_variants), |
|---|
| 209 | + SPINAND_HAS_QE_BIT, |
|---|
| 210 | + SPINAND_ECCINFO(&um19a1xisw_ooblayout, um19axxisw_ecc_ecc_get_status)), |
|---|
| 211 | +}; |
|---|
| 212 | + |
|---|
| 94 | 213 | static const struct spinand_manufacturer_ops unim_spinand_manuf_ops = { |
|---|
| 95 | 214 | }; |
|---|
| 96 | 215 | |
|---|
| 216 | +const struct spinand_manufacturer unim_zl_spinand_manufacturer = { |
|---|
| 217 | + .id = SPINAND_MFR_UNIM_ZL, |
|---|
| 218 | + .name = "UNIM_ZL", |
|---|
| 219 | + .chips = unim_zl_spinand_table, |
|---|
| 220 | + .nchips = ARRAY_SIZE(unim_zl_spinand_table), |
|---|
| 221 | + .ops = &unim_spinand_manuf_ops, |
|---|
| 222 | +}; |
|---|
| 223 | + |
|---|
| 97 | 224 | const struct spinand_manufacturer unim_spinand_manufacturer = { |
|---|
| 98 | 225 | .id = SPINAND_MFR_UNIM, |
|---|
| 99 | 226 | .name = "UNIM", |
|---|