1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) 4 * 2002-2006 Thomas Gleixner (tglx@linutronix.de) 5 * 6 * Credits: 7 * David Woodhouse for adding multichip support 8 * 9 * Aleph One Ltd. and Toby Churchill Ltd. for supporting the 10 * rework for 2K page size chips 11 * 12 * This file contains all ONFI helpers. 13 */ 14 15 #include <linux/slab.h> 16 17 #include "internals.h" 18 19 /* 20 * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. 21 */ 22 int nand_jedec_detect(struct nand_chip *chip) 23 { 24 struct mtd_info *mtd = nand_to_mtd(chip); 25 struct nand_jedec_params *p; 26 struct jedec_ecc_info *ecc; 27 int jedec_version = 0; 28 char id[5]; 29 int i, val, ret; 30 31 /* Try JEDEC for unknown chip or LP */ 32 ret = nand_readid_op(chip, 0x40, id, sizeof(id)); 33 if (ret || strncmp(id, "JEDEC", sizeof(id))) 34 return 0; 35 36 /* JEDEC chip: allocate a buffer to hold its parameter page */ 37 p = kzalloc(sizeof(*p), GFP_KERNEL); 38 if (!p) 39 return -ENOMEM; 40 41 ret = nand_read_param_page_op(chip, 0x40, NULL, 0); 42 if (ret) { 43 ret = 0; 44 goto free_jedec_param_page; 45 } 46 47 for (i = 0; i < 3; i++) { 48 ret = nand_read_data_op(chip, p, sizeof(*p), true); 49 if (ret) { 50 ret = 0; 51 goto free_jedec_param_page; 52 } 53 54 if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) == 55 le16_to_cpu(p->crc)) 56 break; 57 } 58 59 if (i == 3) { 60 pr_err("Could not find valid JEDEC parameter page; aborting\n"); 61 goto free_jedec_param_page; 62 } 63 64 /* Check version */ 65 val = le16_to_cpu(p->revision); 66 if (val & (1 << 2)) 67 jedec_version = 10; 68 else if (val & (1 << 1)) 69 jedec_version = 1; /* vendor specific version */ 70 71 if (!jedec_version) { 72 pr_info("unsupported JEDEC version: %d\n", val); 73 goto free_jedec_param_page; 74 } 75 76 sanitize_string(p->manufacturer, sizeof(p->manufacturer)); 77 sanitize_string(p->model, sizeof(p->model)); 78 chip->parameters.model = kstrdup(p->model, GFP_KERNEL); 79 if (!chip->parameters.model) { 80 ret = -ENOMEM; 81 goto free_jedec_param_page; 82 } 83 84 mtd->writesize = le32_to_cpu(p->byte_per_page); 85 86 /* Please reference to the comment for nand_flash_detect_onfi. */ 87 mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); 88 mtd->erasesize *= mtd->writesize; 89 90 mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); 91 92 /* Please reference to the comment for nand_flash_detect_onfi. */ 93 chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); 94 chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; 95 chip->bits_per_cell = p->bits_per_cell; 96 97 if (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS) 98 chip->options |= NAND_BUSWIDTH_16; 99 100 /* ECC info */ 101 ecc = &p->ecc_info[0]; 102 103 if (ecc->codeword_size >= 9) { 104 chip->ecc_strength_ds = ecc->ecc_bits; 105 chip->ecc_step_ds = 1 << ecc->codeword_size; 106 } else { 107 pr_warn("Invalid codeword size\n"); 108 } 109 110 free_jedec_param_page: 111 kfree(p); 112 return ret; 113 } 114