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

paragon.c (3416B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2019 Jeff Kletsky
      4 *
      5 * Author: Jeff Kletsky <git-commits@allycomm.com>
      6 */
      7
      8#include <linux/device.h>
      9#include <linux/kernel.h>
     10#include <linux/mtd/spinand.h>
     11
     12
     13#define SPINAND_MFR_PARAGON	0xa1
     14
     15
     16#define PN26G0XA_STATUS_ECC_BITMASK		(3 << 4)
     17
     18#define PN26G0XA_STATUS_ECC_NONE_DETECTED	(0 << 4)
     19#define PN26G0XA_STATUS_ECC_1_7_CORRECTED	(1 << 4)
     20#define PN26G0XA_STATUS_ECC_ERRORED		(2 << 4)
     21#define PN26G0XA_STATUS_ECC_8_CORRECTED		(3 << 4)
     22
     23
     24static SPINAND_OP_VARIANTS(read_cache_variants,
     25		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
     26		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
     27		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
     28		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
     29		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
     30		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
     31
     32static SPINAND_OP_VARIANTS(write_cache_variants,
     33		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
     34		SPINAND_PROG_LOAD(true, 0, NULL, 0));
     35
     36static SPINAND_OP_VARIANTS(update_cache_variants,
     37		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
     38		SPINAND_PROG_LOAD(false, 0, NULL, 0));
     39
     40
     41static int pn26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
     42				   struct mtd_oob_region *region)
     43{
     44	if (section > 3)
     45		return -ERANGE;
     46
     47	region->offset = 6 + (15 * section); /* 4 BBM + 2 user bytes */
     48	region->length = 13;
     49
     50	return 0;
     51}
     52
     53static int pn26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
     54				   struct mtd_oob_region *region)
     55{
     56	if (section > 4)
     57		return -ERANGE;
     58
     59	if (section == 4) {
     60		region->offset = 64;
     61		region->length = 64;
     62	} else {
     63		region->offset = 4 + (15 * section);
     64		region->length = 2;
     65	}
     66
     67	return 0;
     68}
     69
     70static int pn26g0xa_ecc_get_status(struct spinand_device *spinand,
     71				   u8 status)
     72{
     73	switch (status & PN26G0XA_STATUS_ECC_BITMASK) {
     74	case PN26G0XA_STATUS_ECC_NONE_DETECTED:
     75		return 0;
     76
     77	case PN26G0XA_STATUS_ECC_1_7_CORRECTED:
     78		return 7;	/* Return upper limit by convention */
     79
     80	case PN26G0XA_STATUS_ECC_8_CORRECTED:
     81		return 8;
     82
     83	case PN26G0XA_STATUS_ECC_ERRORED:
     84		return -EBADMSG;
     85
     86	default:
     87		break;
     88	}
     89
     90	return -EINVAL;
     91}
     92
     93static const struct mtd_ooblayout_ops pn26g0xa_ooblayout = {
     94	.ecc = pn26g0xa_ooblayout_ecc,
     95	.free = pn26g0xa_ooblayout_free,
     96};
     97
     98
     99static const struct spinand_info paragon_spinand_table[] = {
    100	SPINAND_INFO("PN26G01A",
    101		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe1),
    102		     NAND_MEMORG(1, 2048, 128, 64, 1024, 21, 1, 1, 1),
    103		     NAND_ECCREQ(8, 512),
    104		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    105					      &write_cache_variants,
    106					      &update_cache_variants),
    107		     0,
    108		     SPINAND_ECCINFO(&pn26g0xa_ooblayout,
    109				     pn26g0xa_ecc_get_status)),
    110	SPINAND_INFO("PN26G02A",
    111		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe2),
    112		     NAND_MEMORG(1, 2048, 128, 64, 2048, 41, 1, 1, 1),
    113		     NAND_ECCREQ(8, 512),
    114		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
    115					      &write_cache_variants,
    116					      &update_cache_variants),
    117		     0,
    118		     SPINAND_ECCINFO(&pn26g0xa_ooblayout,
    119				     pn26g0xa_ecc_get_status)),
    120};
    121
    122static const struct spinand_manufacturer_ops paragon_spinand_manuf_ops = {
    123};
    124
    125const struct spinand_manufacturer paragon_spinand_manufacturer = {
    126	.id = SPINAND_MFR_PARAGON,
    127	.name = "Paragon",
    128	.chips = paragon_spinand_table,
    129	.nchips = ARRAY_SIZE(paragon_spinand_table),
    130	.ops = &paragon_spinand_manuf_ops,
    131};