| 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 | #define ONFI_PARAM_PAGES 3 |
| 20 | |
| 21 | u16 onfi_crc16(u16 crc, u8 const *p, size_t len) |
| 22 | { |
| 23 | int i; |
| 24 | while (len--) { |
| 25 | crc ^= *p++ << 8; |
| 26 | for (i = 0; i < 8; i++) |
| 27 | crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0); |
| 28 | } |
| 29 | |
| 30 | return crc; |
| 31 | } |
| 32 | |
| 33 | /* Parse the Extended Parameter Page. */ |
| 34 | static int nand_flash_detect_ext_param_page(struct nand_chip *chip, |
| 35 | struct nand_onfi_params *p) |
| 36 | { |
| 37 | struct nand_device *base = &chip->base; |
| 38 | struct nand_ecc_props requirements; |
| 39 | struct onfi_ext_param_page *ep; |
| 40 | struct onfi_ext_section *s; |
| 41 | struct onfi_ext_ecc_info *ecc; |
| 42 | uint8_t *cursor; |
| 43 | int ret; |
| 44 | int len; |
| 45 | int i; |
| 46 | |
| 47 | len = le16_to_cpu(p->ext_param_page_length) * 16; |
| 48 | ep = kmalloc(len, GFP_KERNEL); |
| 49 | if (!ep) |
| 50 | return -ENOMEM; |
| 51 | |
| 52 | /* |
| 53 | * Use the Change Read Column command to skip the ONFI param pages and |
| 54 | * ensure we read at the right location. |
| 55 | */ |
| 56 | ret = nand_change_read_column_op(chip, |
| 57 | offset_in_page: sizeof(*p) * p->num_of_param_pages, |
| 58 | buf: ep, len, force_8bit: true); |
| 59 | if (ret) |
| 60 | goto ext_out; |
| 61 | |
| 62 | ret = -EINVAL; |
| 63 | if ((onfi_crc16(ONFI_CRC_BASE, p: ((uint8_t *)ep) + 2, len: len - 2) |
| 64 | != le16_to_cpu(ep->crc))) { |
| 65 | pr_debug("fail in the CRC.\n" ); |
| 66 | goto ext_out; |
| 67 | } |
| 68 | |
| 69 | /* |
| 70 | * Check the signature. |
| 71 | * Do not strictly follow the ONFI spec, maybe changed in future. |
| 72 | */ |
| 73 | if (strncmp(ep->sig, "EPPS" , 4)) { |
| 74 | pr_debug("The signature is invalid.\n" ); |
| 75 | goto ext_out; |
| 76 | } |
| 77 | |
| 78 | /* find the ECC section. */ |
| 79 | cursor = (uint8_t *)(ep + 1); |
| 80 | for (i = 0; i < ONFI_EXT_SECTION_MAX; i++) { |
| 81 | s = ep->sections + i; |
| 82 | if (s->type == ONFI_SECTION_TYPE_2) |
| 83 | break; |
| 84 | cursor += s->length * 16; |
| 85 | } |
| 86 | if (i == ONFI_EXT_SECTION_MAX) { |
| 87 | pr_debug("We can not find the ECC section.\n" ); |
| 88 | goto ext_out; |
| 89 | } |
| 90 | |
| 91 | /* get the info we want. */ |
| 92 | ecc = (struct onfi_ext_ecc_info *)cursor; |
| 93 | |
| 94 | if (!ecc->codeword_size) { |
| 95 | pr_debug("Invalid codeword size\n" ); |
| 96 | goto ext_out; |
| 97 | } |
| 98 | |
| 99 | requirements.strength = ecc->ecc_bits; |
| 100 | requirements.step_size = 1 << ecc->codeword_size; |
| 101 | nanddev_set_ecc_requirements(nand: base, reqs: &requirements); |
| 102 | |
| 103 | ret = 0; |
| 104 | |
| 105 | ext_out: |
| 106 | kfree(objp: ep); |
| 107 | return ret; |
| 108 | } |
| 109 | |
| 110 | /* |
| 111 | * Recover data with bit-wise majority |
| 112 | */ |
| 113 | static void nand_bit_wise_majority(const void **srcbufs, |
| 114 | unsigned int nsrcbufs, |
| 115 | void *dstbuf, |
| 116 | unsigned int bufsize) |
| 117 | { |
| 118 | int i, j, k; |
| 119 | |
| 120 | for (i = 0; i < bufsize; i++) { |
| 121 | u8 val = 0; |
| 122 | |
| 123 | for (j = 0; j < 8; j++) { |
| 124 | unsigned int cnt = 0; |
| 125 | |
| 126 | for (k = 0; k < nsrcbufs; k++) { |
| 127 | const u8 *srcbuf = srcbufs[k]; |
| 128 | |
| 129 | if (srcbuf[i] & BIT(j)) |
| 130 | cnt++; |
| 131 | } |
| 132 | |
| 133 | if (cnt > nsrcbufs / 2) |
| 134 | val |= BIT(j); |
| 135 | } |
| 136 | |
| 137 | ((u8 *)dstbuf)[i] = val; |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | /* |
| 142 | * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. |
| 143 | */ |
| 144 | int nand_onfi_detect(struct nand_chip *chip) |
| 145 | { |
| 146 | struct nand_device *base = &chip->base; |
| 147 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 148 | struct nand_memory_organization *memorg; |
| 149 | struct nand_onfi_params *p = NULL, *pbuf; |
| 150 | struct onfi_params *onfi; |
| 151 | bool use_datain = false; |
| 152 | int onfi_version = 0; |
| 153 | char id[4]; |
| 154 | int i, ret, val; |
| 155 | u16 crc; |
| 156 | |
| 157 | memorg = nanddev_get_memorg(nand: &chip->base); |
| 158 | |
| 159 | /* Try ONFI for unknown chip or LP */ |
| 160 | ret = nand_readid_op(chip, addr: 0x20, buf: id, len: sizeof(id)); |
| 161 | if (ret || strncmp(id, "ONFI" , 4)) |
| 162 | return 0; |
| 163 | |
| 164 | /* ONFI chip: allocate a buffer to hold its parameter page */ |
| 165 | pbuf = kzalloc((sizeof(*pbuf) * ONFI_PARAM_PAGES), GFP_KERNEL); |
| 166 | if (!pbuf) |
| 167 | return -ENOMEM; |
| 168 | |
| 169 | if (!nand_has_exec_op(chip) || chip->controller->supported_op.data_only_read) |
| 170 | use_datain = true; |
| 171 | |
| 172 | for (i = 0; i < ONFI_PARAM_PAGES; i++) { |
| 173 | if (!i) |
| 174 | ret = nand_read_param_page_op(chip, page: 0, buf: &pbuf[i], |
| 175 | len: sizeof(*pbuf)); |
| 176 | else if (use_datain) |
| 177 | ret = nand_read_data_op(chip, buf: &pbuf[i], len: sizeof(*pbuf), |
| 178 | force_8bit: true, check_only: false); |
| 179 | else |
| 180 | ret = nand_change_read_column_op(chip, offset_in_page: sizeof(*pbuf) * i, |
| 181 | buf: &pbuf[i], len: sizeof(*pbuf), |
| 182 | force_8bit: true); |
| 183 | if (ret) { |
| 184 | ret = 0; |
| 185 | goto free_onfi_param_page; |
| 186 | } |
| 187 | |
| 188 | crc = onfi_crc16(ONFI_CRC_BASE, p: (u8 *)&pbuf[i], len: 254); |
| 189 | if (crc == le16_to_cpu(pbuf[i].crc)) { |
| 190 | p = &pbuf[i]; |
| 191 | break; |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | if (i == ONFI_PARAM_PAGES) { |
| 196 | const void *srcbufs[ONFI_PARAM_PAGES]; |
| 197 | unsigned int j; |
| 198 | |
| 199 | for (j = 0; j < ONFI_PARAM_PAGES; j++) |
| 200 | srcbufs[j] = pbuf + j; |
| 201 | |
| 202 | pr_warn("Could not find a valid ONFI parameter page, trying bit-wise majority to recover it\n" ); |
| 203 | nand_bit_wise_majority(srcbufs, ONFI_PARAM_PAGES, dstbuf: pbuf, |
| 204 | bufsize: sizeof(*pbuf)); |
| 205 | |
| 206 | crc = onfi_crc16(ONFI_CRC_BASE, p: (u8 *)pbuf, len: 254); |
| 207 | if (crc != le16_to_cpu(pbuf->crc)) { |
| 208 | pr_err("ONFI parameter recovery failed, aborting\n" ); |
| 209 | goto free_onfi_param_page; |
| 210 | } |
| 211 | p = pbuf; |
| 212 | } |
| 213 | |
| 214 | if (chip->manufacturer.desc && chip->manufacturer.desc->ops && |
| 215 | chip->manufacturer.desc->ops->fixup_onfi_param_page) |
| 216 | chip->manufacturer.desc->ops->fixup_onfi_param_page(chip, p); |
| 217 | |
| 218 | /* Check version */ |
| 219 | val = le16_to_cpu(p->revision); |
| 220 | if (val & ONFI_VERSION_2_3) |
| 221 | onfi_version = 23; |
| 222 | else if (val & ONFI_VERSION_2_2) |
| 223 | onfi_version = 22; |
| 224 | else if (val & ONFI_VERSION_2_1) |
| 225 | onfi_version = 21; |
| 226 | else if (val & ONFI_VERSION_2_0) |
| 227 | onfi_version = 20; |
| 228 | else if (val & ONFI_VERSION_1_0) |
| 229 | onfi_version = 10; |
| 230 | |
| 231 | if (!onfi_version) { |
| 232 | pr_info("unsupported ONFI version: %d\n" , val); |
| 233 | goto free_onfi_param_page; |
| 234 | } |
| 235 | |
| 236 | sanitize_string(s: p->manufacturer, len: sizeof(p->manufacturer)); |
| 237 | sanitize_string(s: p->model, len: sizeof(p->model)); |
| 238 | chip->parameters.model = kstrdup(s: p->model, GFP_KERNEL); |
| 239 | if (!chip->parameters.model) { |
| 240 | ret = -ENOMEM; |
| 241 | goto free_onfi_param_page; |
| 242 | } |
| 243 | |
| 244 | memorg->pagesize = le32_to_cpu(p->byte_per_page); |
| 245 | mtd->writesize = memorg->pagesize; |
| 246 | |
| 247 | /* |
| 248 | * pages_per_block and blocks_per_lun may not be a power-of-2 size |
| 249 | * (don't ask me who thought of this...). MTD assumes that these |
| 250 | * dimensions will be power-of-2, so just truncate the remaining area. |
| 251 | */ |
| 252 | memorg->pages_per_eraseblock = |
| 253 | 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); |
| 254 | mtd->erasesize = memorg->pages_per_eraseblock * memorg->pagesize; |
| 255 | |
| 256 | memorg->oobsize = le16_to_cpu(p->spare_bytes_per_page); |
| 257 | mtd->oobsize = memorg->oobsize; |
| 258 | |
| 259 | memorg->luns_per_target = p->lun_count; |
| 260 | memorg->planes_per_lun = 1 << p->interleaved_bits; |
| 261 | |
| 262 | /* See erasesize comment */ |
| 263 | memorg->eraseblocks_per_lun = |
| 264 | 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); |
| 265 | memorg->max_bad_eraseblocks_per_lun = le32_to_cpu(p->blocks_per_lun); |
| 266 | memorg->bits_per_cell = p->bits_per_cell; |
| 267 | |
| 268 | if (le16_to_cpu(p->features) & ONFI_FEATURE_16_BIT_BUS) |
| 269 | chip->options |= NAND_BUSWIDTH_16; |
| 270 | |
| 271 | if (p->ecc_bits != 0xff) { |
| 272 | struct nand_ecc_props requirements = { |
| 273 | .strength = p->ecc_bits, |
| 274 | .step_size = 512, |
| 275 | }; |
| 276 | |
| 277 | nanddev_set_ecc_requirements(nand: base, reqs: &requirements); |
| 278 | } else if (onfi_version >= 21 && |
| 279 | (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) { |
| 280 | |
| 281 | /* |
| 282 | * The nand_flash_detect_ext_param_page() uses the |
| 283 | * Change Read Column command which maybe not supported |
| 284 | * by the chip->legacy.cmdfunc. So try to update the |
| 285 | * chip->legacy.cmdfunc now. We do not replace user supplied |
| 286 | * command function. |
| 287 | */ |
| 288 | nand_legacy_adjust_cmdfunc(chip); |
| 289 | |
| 290 | /* The Extended Parameter Page is supported since ONFI 2.1. */ |
| 291 | if (nand_flash_detect_ext_param_page(chip, p)) |
| 292 | pr_warn("Failed to detect ONFI extended param page\n" ); |
| 293 | } else { |
| 294 | pr_warn("Could not retrieve ONFI ECC requirements\n" ); |
| 295 | } |
| 296 | |
| 297 | /* Save some parameters from the parameter page for future use */ |
| 298 | if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES) { |
| 299 | chip->parameters.supports_set_get_features = true; |
| 300 | bitmap_set(map: chip->parameters.get_feature_list, |
| 301 | ONFI_FEATURE_ADDR_TIMING_MODE, nbits: 1); |
| 302 | bitmap_set(map: chip->parameters.set_feature_list, |
| 303 | ONFI_FEATURE_ADDR_TIMING_MODE, nbits: 1); |
| 304 | } |
| 305 | |
| 306 | if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_READ_CACHE) |
| 307 | chip->parameters.supports_read_cache = true; |
| 308 | |
| 309 | onfi = kzalloc(sizeof(*onfi), GFP_KERNEL); |
| 310 | if (!onfi) { |
| 311 | ret = -ENOMEM; |
| 312 | goto free_model; |
| 313 | } |
| 314 | |
| 315 | onfi->version = onfi_version; |
| 316 | onfi->tPROG = le16_to_cpu(p->t_prog); |
| 317 | onfi->tBERS = le16_to_cpu(p->t_bers); |
| 318 | onfi->tR = le16_to_cpu(p->t_r); |
| 319 | onfi->tCCS = le16_to_cpu(p->t_ccs); |
| 320 | onfi->fast_tCAD = le16_to_cpu(p->nvddr_nvddr2_features) & BIT(0); |
| 321 | onfi->sdr_timing_modes = le16_to_cpu(p->sdr_timing_modes); |
| 322 | if (le16_to_cpu(p->features) & ONFI_FEATURE_NV_DDR) |
| 323 | onfi->nvddr_timing_modes = le16_to_cpu(p->nvddr_timing_modes); |
| 324 | onfi->vendor_revision = le16_to_cpu(p->vendor_revision); |
| 325 | memcpy(onfi->vendor, p->vendor, sizeof(p->vendor)); |
| 326 | chip->parameters.onfi = onfi; |
| 327 | |
| 328 | /* Identification done, free the full ONFI parameter page and exit */ |
| 329 | kfree(objp: pbuf); |
| 330 | |
| 331 | return 1; |
| 332 | |
| 333 | free_model: |
| 334 | kfree(objp: chip->parameters.model); |
| 335 | free_onfi_param_page: |
| 336 | kfree(objp: pbuf); |
| 337 | |
| 338 | return ret; |
| 339 | } |
| 340 | |