Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
0004  *        2002-2006 Thomas Gleixner (tglx@linutronix.de)
0005  *
0006  *  Credits:
0007  *  David Woodhouse for adding multichip support
0008  *
0009  *  Aleph One Ltd. and Toby Churchill Ltd. for supporting the
0010  *  rework for 2K page size chips
0011  *
0012  * This file contains all ONFI helpers.
0013  */
0014 
0015 #include <linux/slab.h>
0016 
0017 #include "internals.h"
0018 
0019 #define ONFI_PARAM_PAGES 3
0020 
0021 u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
0022 {
0023     int i;
0024     while (len--) {
0025         crc ^= *p++ << 8;
0026         for (i = 0; i < 8; i++)
0027             crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
0028     }
0029 
0030     return crc;
0031 }
0032 
0033 /* Parse the Extended Parameter Page. */
0034 static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
0035                         struct nand_onfi_params *p)
0036 {
0037     struct nand_device *base = &chip->base;
0038     struct nand_ecc_props requirements;
0039     struct onfi_ext_param_page *ep;
0040     struct onfi_ext_section *s;
0041     struct onfi_ext_ecc_info *ecc;
0042     uint8_t *cursor;
0043     int ret;
0044     int len;
0045     int i;
0046 
0047     len = le16_to_cpu(p->ext_param_page_length) * 16;
0048     ep = kmalloc(len, GFP_KERNEL);
0049     if (!ep)
0050         return -ENOMEM;
0051 
0052     /*
0053      * Use the Change Read Column command to skip the ONFI param pages and
0054      * ensure we read at the right location.
0055      */
0056     ret = nand_change_read_column_op(chip,
0057                      sizeof(*p) * p->num_of_param_pages,
0058                      ep, len, true);
0059     if (ret)
0060         goto ext_out;
0061 
0062     ret = -EINVAL;
0063     if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2)
0064         != le16_to_cpu(ep->crc))) {
0065         pr_debug("fail in the CRC.\n");
0066         goto ext_out;
0067     }
0068 
0069     /*
0070      * Check the signature.
0071      * Do not strictly follow the ONFI spec, maybe changed in future.
0072      */
0073     if (strncmp(ep->sig, "EPPS", 4)) {
0074         pr_debug("The signature is invalid.\n");
0075         goto ext_out;
0076     }
0077 
0078     /* find the ECC section. */
0079     cursor = (uint8_t *)(ep + 1);
0080     for (i = 0; i < ONFI_EXT_SECTION_MAX; i++) {
0081         s = ep->sections + i;
0082         if (s->type == ONFI_SECTION_TYPE_2)
0083             break;
0084         cursor += s->length * 16;
0085     }
0086     if (i == ONFI_EXT_SECTION_MAX) {
0087         pr_debug("We can not find the ECC section.\n");
0088         goto ext_out;
0089     }
0090 
0091     /* get the info we want. */
0092     ecc = (struct onfi_ext_ecc_info *)cursor;
0093 
0094     if (!ecc->codeword_size) {
0095         pr_debug("Invalid codeword size\n");
0096         goto ext_out;
0097     }
0098 
0099     requirements.strength = ecc->ecc_bits;
0100     requirements.step_size = 1 << ecc->codeword_size;
0101     nanddev_set_ecc_requirements(base, &requirements);
0102 
0103     ret = 0;
0104 
0105 ext_out:
0106     kfree(ep);
0107     return ret;
0108 }
0109 
0110 /*
0111  * Recover data with bit-wise majority
0112  */
0113 static void nand_bit_wise_majority(const void **srcbufs,
0114                    unsigned int nsrcbufs,
0115                    void *dstbuf,
0116                    unsigned int bufsize)
0117 {
0118     int i, j, k;
0119 
0120     for (i = 0; i < bufsize; i++) {
0121         u8 val = 0;
0122 
0123         for (j = 0; j < 8; j++) {
0124             unsigned int cnt = 0;
0125 
0126             for (k = 0; k < nsrcbufs; k++) {
0127                 const u8 *srcbuf = srcbufs[k];
0128 
0129                 if (srcbuf[i] & BIT(j))
0130                     cnt++;
0131             }
0132 
0133             if (cnt > nsrcbufs / 2)
0134                 val |= BIT(j);
0135         }
0136 
0137         ((u8 *)dstbuf)[i] = val;
0138     }
0139 }
0140 
0141 /*
0142  * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
0143  */
0144 int nand_onfi_detect(struct nand_chip *chip)
0145 {
0146     struct nand_device *base = &chip->base;
0147     struct mtd_info *mtd = nand_to_mtd(chip);
0148     struct nand_memory_organization *memorg;
0149     struct nand_onfi_params *p = NULL, *pbuf;
0150     struct onfi_params *onfi;
0151     bool use_datain = false;
0152     int onfi_version = 0;
0153     char id[4];
0154     int i, ret, val;
0155     u16 crc;
0156 
0157     memorg = nanddev_get_memorg(&chip->base);
0158 
0159     /* Try ONFI for unknown chip or LP */
0160     ret = nand_readid_op(chip, 0x20, id, sizeof(id));
0161     if (ret || strncmp(id, "ONFI", 4))
0162         return 0;
0163 
0164     /* ONFI chip: allocate a buffer to hold its parameter page */
0165     pbuf = kzalloc((sizeof(*pbuf) * ONFI_PARAM_PAGES), GFP_KERNEL);
0166     if (!pbuf)
0167         return -ENOMEM;
0168 
0169     if (!nand_has_exec_op(chip) ||
0170         !nand_read_data_op(chip, &pbuf[0], sizeof(*pbuf), true, true))
0171         use_datain = true;
0172 
0173     for (i = 0; i < ONFI_PARAM_PAGES; i++) {
0174         if (!i)
0175             ret = nand_read_param_page_op(chip, 0, &pbuf[i],
0176                               sizeof(*pbuf));
0177         else if (use_datain)
0178             ret = nand_read_data_op(chip, &pbuf[i], sizeof(*pbuf),
0179                         true, false);
0180         else
0181             ret = nand_change_read_column_op(chip, sizeof(*pbuf) * i,
0182                              &pbuf[i], sizeof(*pbuf),
0183                              true);
0184         if (ret) {
0185             ret = 0;
0186             goto free_onfi_param_page;
0187         }
0188 
0189         crc = onfi_crc16(ONFI_CRC_BASE, (u8 *)&pbuf[i], 254);
0190         if (crc == le16_to_cpu(pbuf[i].crc)) {
0191             p = &pbuf[i];
0192             break;
0193         }
0194     }
0195 
0196     if (i == ONFI_PARAM_PAGES) {
0197         const void *srcbufs[ONFI_PARAM_PAGES];
0198         unsigned int j;
0199 
0200         for (j = 0; j < ONFI_PARAM_PAGES; j++)
0201             srcbufs[j] = pbuf + j;
0202 
0203         pr_warn("Could not find a valid ONFI parameter page, trying bit-wise majority to recover it\n");
0204         nand_bit_wise_majority(srcbufs, ONFI_PARAM_PAGES, pbuf,
0205                        sizeof(*pbuf));
0206 
0207         crc = onfi_crc16(ONFI_CRC_BASE, (u8 *)pbuf, 254);
0208         if (crc != le16_to_cpu(pbuf->crc)) {
0209             pr_err("ONFI parameter recovery failed, aborting\n");
0210             goto free_onfi_param_page;
0211         }
0212         p = pbuf;
0213     }
0214 
0215     if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
0216         chip->manufacturer.desc->ops->fixup_onfi_param_page)
0217         chip->manufacturer.desc->ops->fixup_onfi_param_page(chip, p);
0218 
0219     /* Check version */
0220     val = le16_to_cpu(p->revision);
0221     if (val & ONFI_VERSION_2_3)
0222         onfi_version = 23;
0223     else if (val & ONFI_VERSION_2_2)
0224         onfi_version = 22;
0225     else if (val & ONFI_VERSION_2_1)
0226         onfi_version = 21;
0227     else if (val & ONFI_VERSION_2_0)
0228         onfi_version = 20;
0229     else if (val & ONFI_VERSION_1_0)
0230         onfi_version = 10;
0231 
0232     if (!onfi_version) {
0233         pr_info("unsupported ONFI version: %d\n", val);
0234         goto free_onfi_param_page;
0235     }
0236 
0237     sanitize_string(p->manufacturer, sizeof(p->manufacturer));
0238     sanitize_string(p->model, sizeof(p->model));
0239     chip->parameters.model = kstrdup(p->model, GFP_KERNEL);
0240     if (!chip->parameters.model) {
0241         ret = -ENOMEM;
0242         goto free_onfi_param_page;
0243     }
0244 
0245     memorg->pagesize = le32_to_cpu(p->byte_per_page);
0246     mtd->writesize = memorg->pagesize;
0247 
0248     /*
0249      * pages_per_block and blocks_per_lun may not be a power-of-2 size
0250      * (don't ask me who thought of this...). MTD assumes that these
0251      * dimensions will be power-of-2, so just truncate the remaining area.
0252      */
0253     memorg->pages_per_eraseblock =
0254             1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
0255     mtd->erasesize = memorg->pages_per_eraseblock * memorg->pagesize;
0256 
0257     memorg->oobsize = le16_to_cpu(p->spare_bytes_per_page);
0258     mtd->oobsize = memorg->oobsize;
0259 
0260     memorg->luns_per_target = p->lun_count;
0261     memorg->planes_per_lun = 1 << p->interleaved_bits;
0262 
0263     /* See erasesize comment */
0264     memorg->eraseblocks_per_lun =
0265         1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
0266     memorg->max_bad_eraseblocks_per_lun = le32_to_cpu(p->blocks_per_lun);
0267     memorg->bits_per_cell = p->bits_per_cell;
0268 
0269     if (le16_to_cpu(p->features) & ONFI_FEATURE_16_BIT_BUS)
0270         chip->options |= NAND_BUSWIDTH_16;
0271 
0272     if (p->ecc_bits != 0xff) {
0273         struct nand_ecc_props requirements = {
0274             .strength = p->ecc_bits,
0275             .step_size = 512,
0276         };
0277 
0278         nanddev_set_ecc_requirements(base, &requirements);
0279     } else if (onfi_version >= 21 &&
0280         (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
0281 
0282         /*
0283          * The nand_flash_detect_ext_param_page() uses the
0284          * Change Read Column command which maybe not supported
0285          * by the chip->legacy.cmdfunc. So try to update the
0286          * chip->legacy.cmdfunc now. We do not replace user supplied
0287          * command function.
0288          */
0289         nand_legacy_adjust_cmdfunc(chip);
0290 
0291         /* The Extended Parameter Page is supported since ONFI 2.1. */
0292         if (nand_flash_detect_ext_param_page(chip, p))
0293             pr_warn("Failed to detect ONFI extended param page\n");
0294     } else {
0295         pr_warn("Could not retrieve ONFI ECC requirements\n");
0296     }
0297 
0298     /* Save some parameters from the parameter page for future use */
0299     if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES) {
0300         chip->parameters.supports_set_get_features = true;
0301         bitmap_set(chip->parameters.get_feature_list,
0302                ONFI_FEATURE_ADDR_TIMING_MODE, 1);
0303         bitmap_set(chip->parameters.set_feature_list,
0304                ONFI_FEATURE_ADDR_TIMING_MODE, 1);
0305     }
0306 
0307     onfi = kzalloc(sizeof(*onfi), GFP_KERNEL);
0308     if (!onfi) {
0309         ret = -ENOMEM;
0310         goto free_model;
0311     }
0312 
0313     onfi->version = onfi_version;
0314     onfi->tPROG = le16_to_cpu(p->t_prog);
0315     onfi->tBERS = le16_to_cpu(p->t_bers);
0316     onfi->tR = le16_to_cpu(p->t_r);
0317     onfi->tCCS = le16_to_cpu(p->t_ccs);
0318     onfi->fast_tCAD = le16_to_cpu(p->nvddr_nvddr2_features) & BIT(0);
0319     onfi->sdr_timing_modes = le16_to_cpu(p->sdr_timing_modes);
0320     if (le16_to_cpu(p->features) & ONFI_FEATURE_NV_DDR)
0321         onfi->nvddr_timing_modes = le16_to_cpu(p->nvddr_timing_modes);
0322     onfi->vendor_revision = le16_to_cpu(p->vendor_revision);
0323     memcpy(onfi->vendor, p->vendor, sizeof(p->vendor));
0324     chip->parameters.onfi = onfi;
0325 
0326     /* Identification done, free the full ONFI parameter page and exit */
0327     kfree(pbuf);
0328 
0329     return 1;
0330 
0331 free_model:
0332     kfree(chip->parameters.model);
0333 free_onfi_param_page:
0334     kfree(pbuf);
0335 
0336     return ret;
0337 }