cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

toshiba.c (9563B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2018 exceet electronics GmbH
      4 * Copyright (c) 2018 Kontron Electronics GmbH
      5 *
      6 * Author: Frieder Schrempf <frieder.schrempf@kontron.de>
      7 */
      8
      9#include <linux/device.h>
     10#include <linux/kernel.h>
     11#include <linux/mtd/spinand.h>
     12
     13/* Kioxia is new name of Toshiba memory. */
     14#define SPINAND_MFR_TOSHIBA		0x98
     15#define TOSH_STATUS_ECC_HAS_BITFLIPS_T	(3 << 4)
     16
     17static SPINAND_OP_VARIANTS(read_cache_variants,
     18		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
     19		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
     20		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
     21		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
     22
     23static SPINAND_OP_VARIANTS(write_cache_x4_variants,
     24		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
     25		SPINAND_PROG_LOAD(true, 0, NULL, 0));
     26
     27static SPINAND_OP_VARIANTS(update_cache_x4_variants,
     28		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
     29		SPINAND_PROG_LOAD(false, 0, NULL, 0));
     30
     31/*
     32 * Backward compatibility for 1st generation Serial NAND devices
     33 * which don't support Quad Program Load operation.
     34 */
     35static SPINAND_OP_VARIANTS(write_cache_variants,
     36		SPINAND_PROG_LOAD(true, 0, NULL, 0));
     37
     38static SPINAND_OP_VARIANTS(update_cache_variants,
     39		SPINAND_PROG_LOAD(false, 0, NULL, 0));
     40
     41static int tx58cxgxsxraix_ooblayout_ecc(struct mtd_info *mtd, int section,
     42					struct mtd_oob_region *region)
     43{
     44	if (section > 0)
     45		return -ERANGE;
     46
     47	region->offset = mtd->oobsize / 2;
     48	region->length = mtd->oobsize / 2;
     49
     50	return 0;
     51}
     52
     53static int tx58cxgxsxraix_ooblayout_free(struct mtd_info *mtd, int section,
     54					 struct mtd_oob_region *region)
     55{
     56	if (section > 0)
     57		return -ERANGE;
     58
     59	/* 2 bytes reserved for BBM */
     60	region->offset = 2;
     61	region->length = (mtd->oobsize / 2) - 2;
     62
     63	return 0;
     64}
     65
     66static const struct mtd_ooblayout_ops tx58cxgxsxraix_ooblayout = {
     67	.ecc = tx58cxgxsxraix_ooblayout_ecc,
     68	.free = tx58cxgxsxraix_ooblayout_free,
     69};
     70
     71static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
     72					 u8 status)
     73{
     74	struct nand_device *nand = spinand_to_nand(spinand);
     75	u8 mbf = 0;
     76	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
     77
     78	switch (status & STATUS_ECC_MASK) {
     79	case STATUS_ECC_NO_BITFLIPS:
     80		return 0;
     81
     82	case STATUS_ECC_UNCOR_ERROR:
     83		return -EBADMSG;
     84
     85	case STATUS_ECC_HAS_BITFLIPS:
     86	case TOSH_STATUS_ECC_HAS_BITFLIPS_T:
     87		/*
     88		 * Let's try to retrieve the real maximum number of bitflips
     89		 * in order to avoid forcing the wear-leveling layer to move
     90		 * data around if it's not necessary.
     91		 */
     92		if (spi_mem_exec_op(spinand->spimem, &op))
     93			return nanddev_get_ecc_conf(nand)->strength;
     94
     95		mbf >>= 4;
     96
     97		if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
     98			return nanddev_get_ecc_conf(nand)->strength;
     99
    100		return mbf;
    101
    102	default:
    103		break;
    104	}
    105
    106	return -EINVAL;
    107}
    108
    109static const struct spinand_info toshiba_spinand_table[] = {
    110	/* 3.3V 1Gb (1st generation) */
    111	SPINAND_INFO("TC58CVG0S3HRAIG",
    112		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
    113		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
    114		     NAND_ECCREQ(8, 512),
    115		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    116					      &write_cache_variants,
    117					      &update_cache_variants),
    118		     0,
    119		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    120				     tx58cxgxsxraix_ecc_get_status)),
    121	/* 3.3V 2Gb (1st generation) */
    122	SPINAND_INFO("TC58CVG1S3HRAIG",
    123		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
    124		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
    125		     NAND_ECCREQ(8, 512),
    126		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    127					      &write_cache_variants,
    128					      &update_cache_variants),
    129		     0,
    130		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    131				     tx58cxgxsxraix_ecc_get_status)),
    132	/* 3.3V 4Gb (1st generation) */
    133	SPINAND_INFO("TC58CVG2S0HRAIG",
    134		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
    135		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
    136		     NAND_ECCREQ(8, 512),
    137		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    138					      &write_cache_variants,
    139					      &update_cache_variants),
    140		     0,
    141		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    142				     tx58cxgxsxraix_ecc_get_status)),
    143	/* 1.8V 1Gb (1st generation) */
    144	SPINAND_INFO("TC58CYG0S3HRAIG",
    145		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
    146		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
    147		     NAND_ECCREQ(8, 512),
    148		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    149					      &write_cache_variants,
    150					      &update_cache_variants),
    151		     0,
    152		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    153				     tx58cxgxsxraix_ecc_get_status)),
    154	/* 1.8V 2Gb (1st generation) */
    155	SPINAND_INFO("TC58CYG1S3HRAIG",
    156		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
    157		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
    158		     NAND_ECCREQ(8, 512),
    159		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    160					      &write_cache_variants,
    161					      &update_cache_variants),
    162		     0,
    163		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    164				     tx58cxgxsxraix_ecc_get_status)),
    165	/* 1.8V 4Gb (1st generation) */
    166	SPINAND_INFO("TC58CYG2S0HRAIG",
    167		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
    168		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
    169		     NAND_ECCREQ(8, 512),
    170		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    171					      &write_cache_variants,
    172					      &update_cache_variants),
    173		     0,
    174		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    175				     tx58cxgxsxraix_ecc_get_status)),
    176
    177	/*
    178	 * 2nd generation serial nand has HOLD_D which is equivalent to
    179	 * QE_BIT.
    180	 */
    181	/* 3.3V 1Gb (2nd generation) */
    182	SPINAND_INFO("TC58CVG0S3HRAIJ",
    183		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE2),
    184		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
    185		     NAND_ECCREQ(8, 512),
    186		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    187					      &write_cache_x4_variants,
    188					      &update_cache_x4_variants),
    189		     SPINAND_HAS_QE_BIT,
    190		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    191				     tx58cxgxsxraix_ecc_get_status)),
    192	/* 3.3V 2Gb (2nd generation) */
    193	SPINAND_INFO("TC58CVG1S3HRAIJ",
    194		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB),
    195		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
    196		     NAND_ECCREQ(8, 512),
    197		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    198					      &write_cache_x4_variants,
    199					      &update_cache_x4_variants),
    200		     SPINAND_HAS_QE_BIT,
    201		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    202				     tx58cxgxsxraix_ecc_get_status)),
    203	/* 3.3V 4Gb (2nd generation) */
    204	SPINAND_INFO("TC58CVG2S0HRAIJ",
    205		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED),
    206		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
    207		     NAND_ECCREQ(8, 512),
    208		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    209					      &write_cache_x4_variants,
    210					      &update_cache_x4_variants),
    211		     SPINAND_HAS_QE_BIT,
    212		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    213				     tx58cxgxsxraix_ecc_get_status)),
    214	/* 3.3V 8Gb (2nd generation) */
    215	SPINAND_INFO("TH58CVG3S0HRAIJ",
    216		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4),
    217		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
    218		     NAND_ECCREQ(8, 512),
    219		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    220					      &write_cache_x4_variants,
    221					      &update_cache_x4_variants),
    222		     SPINAND_HAS_QE_BIT,
    223		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    224				     tx58cxgxsxraix_ecc_get_status)),
    225	/* 1.8V 1Gb (2nd generation) */
    226	SPINAND_INFO("TC58CYG0S3HRAIJ",
    227		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2),
    228		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
    229		     NAND_ECCREQ(8, 512),
    230		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    231					      &write_cache_x4_variants,
    232					      &update_cache_x4_variants),
    233		     SPINAND_HAS_QE_BIT,
    234		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    235				     tx58cxgxsxraix_ecc_get_status)),
    236	/* 1.8V 2Gb (2nd generation) */
    237	SPINAND_INFO("TC58CYG1S3HRAIJ",
    238		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDB),
    239		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
    240		     NAND_ECCREQ(8, 512),
    241		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    242					      &write_cache_x4_variants,
    243					      &update_cache_x4_variants),
    244		     SPINAND_HAS_QE_BIT,
    245		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    246				     tx58cxgxsxraix_ecc_get_status)),
    247	/* 1.8V 4Gb (2nd generation) */
    248	SPINAND_INFO("TC58CYG2S0HRAIJ",
    249		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDD),
    250		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
    251		     NAND_ECCREQ(8, 512),
    252		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    253					      &write_cache_x4_variants,
    254					      &update_cache_x4_variants),
    255		     SPINAND_HAS_QE_BIT,
    256		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    257				     tx58cxgxsxraix_ecc_get_status)),
    258	/* 1.8V 8Gb (2nd generation) */
    259	SPINAND_INFO("TH58CYG3S0HRAIJ",
    260		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4),
    261		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
    262		     NAND_ECCREQ(8, 512),
    263		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    264					      &write_cache_x4_variants,
    265					      &update_cache_x4_variants),
    266		     SPINAND_HAS_QE_BIT,
    267		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
    268				     tx58cxgxsxraix_ecc_get_status)),
    269};
    270
    271static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
    272};
    273
    274const struct spinand_manufacturer toshiba_spinand_manufacturer = {
    275	.id = SPINAND_MFR_TOSHIBA,
    276	.name = "Toshiba",
    277	.chips = toshiba_spinand_table,
    278	.nchips = ARRAY_SIZE(toshiba_spinand_table),
    279	.ops = &toshiba_spinand_manuf_ops,
    280};