]> Git Repo - linux.git/blob - drivers/mtd/nand/raw/nand_jedec.c
Merge tag 'microblaze-v5.0-rc1' of git://git.monstr.eu/linux-2.6-microblaze
[linux.git] / drivers / mtd / nand / raw / nand_jedec.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  Copyright (C) 2000 Steven J. Hill ([email protected])
4  *                2002-2006 Thomas Gleixner ([email protected])
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         ret = 1;
111
112 free_jedec_param_page:
113         kfree(p);
114         return ret;
115 }
This page took 0.039039 seconds and 4 git commands to generate.