Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: spinand: Add support for AllianceMemory AS5F34G04SND

Add support for AllianceMemory AS5F34G04SND SPI NAND flash

Datasheet:
- https://www.alliancememory.com/wp-content/uploads/pdf/flash/AllianceMemory_SPI_NAND_Flash_July2020_Rev1.0.pdf

Signed-off-by: Mario Kicherer <dev@kicherer.org>
Reviewed-by: Dhruva Gole <d-gole@ti.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20230126144050.2656358-1-dev@kicherer.org

authored by

Mario Kicherer and committed by
Miquel Raynal
724ef015 ebed787a

+156 -1
+1 -1
drivers/mtd/nand/spi/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - spinand-objs := core.o ato.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o 2 + spinand-objs := core.o alliancememory.o ato.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o 3 3 obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
+153
drivers/mtd/nand/spi/alliancememory.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Author: Mario Kicherer <dev@kicherer.org> 4 + */ 5 + 6 + #include <linux/device.h> 7 + #include <linux/kernel.h> 8 + #include <linux/mtd/spinand.h> 9 + 10 + #define SPINAND_MFR_ALLIANCEMEMORY 0x52 11 + 12 + #define AM_STATUS_ECC_BITMASK (3 << 4) 13 + 14 + #define AM_STATUS_ECC_NONE_DETECTED (0 << 4) 15 + #define AM_STATUS_ECC_CORRECTED (1 << 4) 16 + #define AM_STATUS_ECC_ERRORED (2 << 4) 17 + #define AM_STATUS_ECC_MAX_CORRECTED (3 << 4) 18 + 19 + static SPINAND_OP_VARIANTS(read_cache_variants, 20 + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), 21 + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), 22 + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), 23 + SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), 24 + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), 25 + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); 26 + 27 + static SPINAND_OP_VARIANTS(write_cache_variants, 28 + SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), 29 + SPINAND_PROG_LOAD(true, 0, NULL, 0)); 30 + 31 + static SPINAND_OP_VARIANTS(update_cache_variants, 32 + SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), 33 + SPINAND_PROG_LOAD(false, 0, NULL, 0)); 34 + 35 + static int am_get_eccsize(struct mtd_info *mtd) 36 + { 37 + if (mtd->oobsize == 64) 38 + return 0x20; 39 + else if (mtd->oobsize == 128) 40 + return 0x38; 41 + else if (mtd->oobsize == 256) 42 + return 0x70; 43 + else 44 + return -EINVAL; 45 + } 46 + 47 + static int am_ooblayout_ecc(struct mtd_info *mtd, int section, 48 + struct mtd_oob_region *region) 49 + { 50 + int ecc_bytes; 51 + 52 + ecc_bytes = am_get_eccsize(mtd); 53 + if (ecc_bytes < 0) 54 + return ecc_bytes; 55 + 56 + region->offset = mtd->oobsize - ecc_bytes; 57 + region->length = ecc_bytes; 58 + 59 + return 0; 60 + } 61 + 62 + static int am_ooblayout_free(struct mtd_info *mtd, int section, 63 + struct mtd_oob_region *region) 64 + { 65 + int ecc_bytes; 66 + 67 + if (section) 68 + return -ERANGE; 69 + 70 + ecc_bytes = am_get_eccsize(mtd); 71 + if (ecc_bytes < 0) 72 + return ecc_bytes; 73 + 74 + /* 75 + * It is unclear how many bytes are used for the bad block marker. We 76 + * reserve the common two bytes here. 77 + * 78 + * The free area in this kind of flash is divided into chunks where the 79 + * first 4 bytes of each chunk are unprotected. The number of chunks 80 + * depends on the specific model. The models with 4096+256 bytes pages 81 + * have 8 chunks, the others 4 chunks. 82 + */ 83 + 84 + region->offset = 2; 85 + region->length = mtd->oobsize - 2 - ecc_bytes; 86 + 87 + return 0; 88 + } 89 + 90 + static const struct mtd_ooblayout_ops am_ooblayout = { 91 + .ecc = am_ooblayout_ecc, 92 + .free = am_ooblayout_free, 93 + }; 94 + 95 + static int am_ecc_get_status(struct spinand_device *spinand, u8 status) 96 + { 97 + switch (status & AM_STATUS_ECC_BITMASK) { 98 + case AM_STATUS_ECC_NONE_DETECTED: 99 + return 0; 100 + 101 + case AM_STATUS_ECC_CORRECTED: 102 + /* 103 + * use oobsize to determine the flash model and the maximum of 104 + * correctable errors and return maximum - 1 by convention 105 + */ 106 + if (spinand->base.mtd.oobsize == 64) 107 + return 3; 108 + else 109 + return 7; 110 + 111 + case AM_STATUS_ECC_ERRORED: 112 + return -EBADMSG; 113 + 114 + case AM_STATUS_ECC_MAX_CORRECTED: 115 + /* 116 + * use oobsize to determine the flash model and the maximum of 117 + * correctable errors 118 + */ 119 + if (spinand->base.mtd.oobsize == 64) 120 + return 4; 121 + else 122 + return 8; 123 + 124 + default: 125 + break; 126 + } 127 + 128 + return -EINVAL; 129 + } 130 + 131 + static const struct spinand_info alliancememory_spinand_table[] = { 132 + SPINAND_INFO("AS5F34G04SND", 133 + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x2f), 134 + NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1), 135 + NAND_ECCREQ(4, 512), 136 + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 137 + &write_cache_variants, 138 + &update_cache_variants), 139 + SPINAND_HAS_QE_BIT, 140 + SPINAND_ECCINFO(&am_ooblayout, 141 + am_ecc_get_status)), 142 + }; 143 + 144 + static const struct spinand_manufacturer_ops alliancememory_spinand_manuf_ops = { 145 + }; 146 + 147 + const struct spinand_manufacturer alliancememory_spinand_manufacturer = { 148 + .id = SPINAND_MFR_ALLIANCEMEMORY, 149 + .name = "AllianceMemory", 150 + .chips = alliancememory_spinand_table, 151 + .nchips = ARRAY_SIZE(alliancememory_spinand_table), 152 + .ops = &alliancememory_spinand_manuf_ops, 153 + };
+1
drivers/mtd/nand/spi/core.c
··· 937 937 }; 938 938 939 939 static const struct spinand_manufacturer *spinand_manufacturers[] = { 940 + &alliancememory_spinand_manufacturer, 940 941 &ato_spinand_manufacturer, 941 942 &gigadevice_spinand_manufacturer, 942 943 &macronix_spinand_manufacturer,
+1
include/linux/mtd/spinand.h
··· 260 260 }; 261 261 262 262 /* SPI NAND manufacturers */ 263 + extern const struct spinand_manufacturer alliancememory_spinand_manufacturer; 263 264 extern const struct spinand_manufacturer ato_spinand_manufacturer; 264 265 extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; 265 266 extern const struct spinand_manufacturer macronix_spinand_manufacturer;