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

nand_samsung.c (3162B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2017 Free Electrons
      4 * Copyright (C) 2017 NextThing Co
      5 *
      6 * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
      7 */
      8
      9#include "internals.h"
     10
     11static void samsung_nand_decode_id(struct nand_chip *chip)
     12{
     13	struct nand_device *base = &chip->base;
     14	struct nand_ecc_props requirements = {};
     15	struct mtd_info *mtd = nand_to_mtd(chip);
     16	struct nand_memory_organization *memorg;
     17
     18	memorg = nanddev_get_memorg(&chip->base);
     19
     20	/* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */
     21	if (chip->id.len == 6 && !nand_is_slc(chip) &&
     22	    chip->id.data[5] != 0x00) {
     23		u8 extid = chip->id.data[3];
     24
     25		/* Get pagesize */
     26		memorg->pagesize = 2048 << (extid & 0x03);
     27		mtd->writesize = memorg->pagesize;
     28
     29		extid >>= 2;
     30
     31		/* Get oobsize */
     32		switch (((extid >> 2) & 0x4) | (extid & 0x3)) {
     33		case 1:
     34			memorg->oobsize = 128;
     35			break;
     36		case 2:
     37			memorg->oobsize = 218;
     38			break;
     39		case 3:
     40			memorg->oobsize = 400;
     41			break;
     42		case 4:
     43			memorg->oobsize = 436;
     44			break;
     45		case 5:
     46			memorg->oobsize = 512;
     47			break;
     48		case 6:
     49			memorg->oobsize = 640;
     50			break;
     51		default:
     52			/*
     53			 * We should never reach this case, but if that
     54			 * happens, this probably means Samsung decided to use
     55			 * a different extended ID format, and we should find
     56			 * a way to support it.
     57			 */
     58			WARN(1, "Invalid OOB size value");
     59			break;
     60		}
     61
     62		mtd->oobsize = memorg->oobsize;
     63
     64		/* Get blocksize */
     65		extid >>= 2;
     66		memorg->pages_per_eraseblock = (128 * 1024) <<
     67					       (((extid >> 1) & 0x04) |
     68						(extid & 0x03)) /
     69					       memorg->pagesize;
     70		mtd->erasesize = (128 * 1024) <<
     71				 (((extid >> 1) & 0x04) | (extid & 0x03));
     72
     73		/* Extract ECC requirements from 5th id byte*/
     74		extid = (chip->id.data[4] >> 4) & 0x07;
     75		if (extid < 5) {
     76			requirements.step_size = 512;
     77			requirements.strength = 1 << extid;
     78		} else {
     79			requirements.step_size = 1024;
     80			switch (extid) {
     81			case 5:
     82				requirements.strength = 24;
     83				break;
     84			case 6:
     85				requirements.strength = 40;
     86				break;
     87			case 7:
     88				requirements.strength = 60;
     89				break;
     90			default:
     91				WARN(1, "Could not decode ECC info");
     92				requirements.step_size = 0;
     93			}
     94		}
     95	} else {
     96		nand_decode_ext_id(chip);
     97
     98		if (nand_is_slc(chip)) {
     99			switch (chip->id.data[1]) {
    100			/* K9F4G08U0D-S[I|C]B0(T00) */
    101			case 0xDC:
    102				requirements.step_size = 512;
    103				requirements.strength = 1;
    104				break;
    105
    106			/* K9F1G08U0E 21nm chips do not support subpage write */
    107			case 0xF1:
    108				if (chip->id.len > 4 &&
    109				    (chip->id.data[4] & GENMASK(1, 0)) == 0x1)
    110					chip->options |= NAND_NO_SUBPAGE_WRITE;
    111				break;
    112			default:
    113				break;
    114			}
    115		}
    116	}
    117
    118	nanddev_set_ecc_requirements(base, &requirements);
    119}
    120
    121static int samsung_nand_init(struct nand_chip *chip)
    122{
    123	struct mtd_info *mtd = nand_to_mtd(chip);
    124
    125	if (mtd->writesize > 512)
    126		chip->options |= NAND_SAMSUNG_LP_OPTIONS;
    127
    128	if (!nand_is_slc(chip))
    129		chip->options |= NAND_BBM_LASTPAGE;
    130	else
    131		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
    132
    133	return 0;
    134}
    135
    136const struct nand_manufacturer_ops samsung_nand_manuf_ops = {
    137	.detect = samsung_nand_decode_id,
    138	.init = samsung_nand_init,
    139};