summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2015-12-07 16:46:45 -0500
committerBoris Brezillon <boris.brezillon@free-electrons.com>2016-05-05 17:51:49 -0400
commita411679fb5fd7ee2df64a55c23c81538ceeb6d06 (patch)
tree38fe2b4bead9c9297085503341dc26c632822ebd
parent421e81c4c6c03a5f6cbc40ea208fb07ad5797e09 (diff)
mtd: onenand: switch to mtd_ooblayout_ops
Implementing the mtd_ooblayout_ops interface is the new way of exposing ECC/OOB layout to MTD users. Modify the onenand drivers to switch to this approach. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
-rw-r--r--drivers/mtd/onenand/onenand_base.c162
-rw-r--r--include/linux/mtd/onenand.h2
2 files changed, 97 insertions, 67 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index d0fa505d40bd..a4b029a417f0 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -68,21 +68,33 @@ MODULE_PARM_DESC(otp, "Corresponding behaviour of OneNAND in OTP"
68 * flexonenand_oob_128 - oob info for Flex-Onenand with 4KB page 68 * flexonenand_oob_128 - oob info for Flex-Onenand with 4KB page
69 * For now, we expose only 64 out of 80 ecc bytes 69 * For now, we expose only 64 out of 80 ecc bytes
70 */ 70 */
71static struct nand_ecclayout flexonenand_oob_128 = { 71static int flexonenand_ooblayout_ecc(struct mtd_info *mtd, int section,
72 .eccbytes = 64, 72 struct mtd_oob_region *oobregion)
73 .eccpos = { 73{
74 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 74 if (section > 7)
75 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 75 return -ERANGE;
76 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 76
77 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 77 oobregion->offset = (section * 16) + 6;
78 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 78 oobregion->length = 10;
79 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 79
80 102, 103, 104, 105 80 return 0;
81 }, 81}
82 .oobfree = { 82
83 {2, 4}, {18, 4}, {34, 4}, {50, 4}, 83static int flexonenand_ooblayout_free(struct mtd_info *mtd, int section,
84 {66, 4}, {82, 4}, {98, 4}, {114, 4} 84 struct mtd_oob_region *oobregion)
85 } 85{
86 if (section > 7)
87 return -ERANGE;
88
89 oobregion->offset = (section * 16) + 2;
90 oobregion->length = 4;
91
92 return 0;
93}
94
95static const struct mtd_ooblayout_ops flexonenand_ooblayout_ops = {
96 .ecc = flexonenand_ooblayout_ecc,
97 .free = flexonenand_ooblayout_free,
86}; 98};
87 99
88/* 100/*
@@ -91,56 +103,77 @@ static struct nand_ecclayout flexonenand_oob_128 = {
91 * Based on specification: 103 * Based on specification:
92 * 4Gb M-die OneNAND Flash (KFM4G16Q4M, KFN8G16Q4M). Rev. 1.3, Apr. 2010 104 * 4Gb M-die OneNAND Flash (KFM4G16Q4M, KFN8G16Q4M). Rev. 1.3, Apr. 2010
93 * 105 *
94 * For eccpos we expose only 64 bytes out of 72 (see struct nand_ecclayout) 106 */
95 * 107static int onenand_ooblayout_128_ecc(struct mtd_info *mtd, int section,
96 * oobfree uses the spare area fields marked as 108 struct mtd_oob_region *oobregion)
97 * "Managed by internal ECC logic for Logical Sector Number area" 109{
98 */ 110 if (section > 7)
99static struct nand_ecclayout onenand_oob_128 = { 111 return -ERANGE;
100 .eccbytes = 64, 112
101 .eccpos = { 113 oobregion->offset = (section * 16) + 7;
102 7, 8, 9, 10, 11, 12, 13, 14, 15, 114 oobregion->length = 9;
103 23, 24, 25, 26, 27, 28, 29, 30, 31, 115
104 39, 40, 41, 42, 43, 44, 45, 46, 47, 116 return 0;
105 55, 56, 57, 58, 59, 60, 61, 62, 63, 117}
106 71, 72, 73, 74, 75, 76, 77, 78, 79, 118
107 87, 88, 89, 90, 91, 92, 93, 94, 95, 119static int onenand_ooblayout_128_free(struct mtd_info *mtd, int section,
108 103, 104, 105, 106, 107, 108, 109, 110, 111, 120 struct mtd_oob_region *oobregion)
109 119 121{
110 }, 122 if (section >= 8)
111 .oobfree = { 123 return -ERANGE;
112 {2, 3}, {18, 3}, {34, 3}, {50, 3}, 124
113 {66, 3}, {82, 3}, {98, 3}, {114, 3} 125 /*
114 } 126 * free bytes are using the spare area fields marked as
127 * "Managed by internal ECC logic for Logical Sector Number area"
128 */
129 oobregion->offset = (section * 16) + 2;
130 oobregion->length = 3;
131
132 return 0;
133}
134
135static const struct mtd_ooblayout_ops onenand_oob_128_ooblayout_ops = {
136 .ecc = onenand_ooblayout_128_ecc,
137 .free = onenand_ooblayout_128_free,
115}; 138};
116 139
117/** 140/**
118 * onenand_oob_64 - oob info for large (2KB) page 141 * onenand_oob_32_64 - oob info for large (2KB) page
119 */ 142 */
120static struct nand_ecclayout onenand_oob_64 = { 143static int onenand_ooblayout_32_64_ecc(struct mtd_info *mtd, int section,
121 .eccbytes = 20, 144 struct mtd_oob_region *oobregion)
122 .eccpos = { 145{
123 8, 9, 10, 11, 12, 146 if (section > 3)
124 24, 25, 26, 27, 28, 147 return -ERANGE;
125 40, 41, 42, 43, 44, 148
126 56, 57, 58, 59, 60, 149 oobregion->offset = (section * 16) + 8;
127 }, 150 oobregion->length = 5;
128 .oobfree = { 151
129 {2, 3}, {14, 2}, {18, 3}, {30, 2}, 152 return 0;
130 {34, 3}, {46, 2}, {50, 3}, {62, 2} 153}
154
155static int onenand_ooblayout_32_64_free(struct mtd_info *mtd, int section,
156 struct mtd_oob_region *oobregion)
157{
158 int sections = (mtd->oobsize / 32) * 2;
159
160 if (section >= sections)
161 return -ERANGE;
162
163 if (section & 1) {
164 oobregion->offset = ((section - 1) * 16) + 14;
165 oobregion->length = 2;
166 } else {
167 oobregion->offset = (section * 16) + 2;
168 oobregion->length = 3;
131 } 169 }
132};
133 170
134/** 171 return 0;
135 * onenand_oob_32 - oob info for middle (1KB) page 172}
136 */ 173
137static struct nand_ecclayout onenand_oob_32 = { 174static const struct mtd_ooblayout_ops onenand_oob_32_64_ooblayout_ops = {
138 .eccbytes = 10, 175 .ecc = onenand_ooblayout_32_64_ecc,
139 .eccpos = { 176 .free = onenand_ooblayout_32_64_free,
140 8, 9, 10, 11, 12,
141 24, 25, 26, 27, 28,
142 },
143 .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} }
144}; 177};
145 178
146static const unsigned char ffchars[] = { 179static const unsigned char ffchars[] = {
@@ -3957,22 +3990,22 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
3957 switch (mtd->oobsize) { 3990 switch (mtd->oobsize) {
3958 case 128: 3991 case 128:
3959 if (FLEXONENAND(this)) { 3992 if (FLEXONENAND(this)) {
3960 this->ecclayout = &flexonenand_oob_128; 3993 mtd_set_ooblayout(mtd, &flexonenand_ooblayout_ops);
3961 mtd->subpage_sft = 0; 3994 mtd->subpage_sft = 0;
3962 } else { 3995 } else {
3963 this->ecclayout = &onenand_oob_128; 3996 mtd_set_ooblayout(mtd, &onenand_oob_128_ooblayout_ops);
3964 mtd->subpage_sft = 2; 3997 mtd->subpage_sft = 2;
3965 } 3998 }
3966 if (ONENAND_IS_NOP_1(this)) 3999 if (ONENAND_IS_NOP_1(this))
3967 mtd->subpage_sft = 0; 4000 mtd->subpage_sft = 0;
3968 break; 4001 break;
3969 case 64: 4002 case 64:
3970 this->ecclayout = &onenand_oob_64; 4003 mtd_set_ooblayout(mtd, &onenand_oob_32_64_ooblayout_ops);
3971 mtd->subpage_sft = 2; 4004 mtd->subpage_sft = 2;
3972 break; 4005 break;
3973 4006
3974 case 32: 4007 case 32:
3975 this->ecclayout = &onenand_oob_32; 4008 mtd_set_ooblayout(mtd, &onenand_oob_32_64_ooblayout_ops);
3976 mtd->subpage_sft = 1; 4009 mtd->subpage_sft = 1;
3977 break; 4010 break;
3978 4011
@@ -3981,7 +4014,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
3981 __func__, mtd->oobsize); 4014 __func__, mtd->oobsize);
3982 mtd->subpage_sft = 0; 4015 mtd->subpage_sft = 0;
3983 /* To prevent kernel oops */ 4016 /* To prevent kernel oops */
3984 this->ecclayout = &onenand_oob_32; 4017 mtd_set_ooblayout(mtd, &onenand_oob_32_64_ooblayout_ops);
3985 break; 4018 break;
3986 } 4019 }
3987 4020
@@ -3997,7 +4030,6 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
3997 4030
3998 mtd->oobavail = ret; 4031 mtd->oobavail = ret;
3999 4032
4000 mtd_set_ecclayout(mtd, this->ecclayout);
4001 mtd->ecc_strength = 1; 4033 mtd->ecc_strength = 1;
4002 4034
4003 /* Fill in remaining MTD driver data */ 4035 /* Fill in remaining MTD driver data */
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 4596503c9da9..0aaa98b219a4 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -80,7 +80,6 @@ struct onenand_bufferram {
80 * @page_buf: [INTERN] page main data buffer 80 * @page_buf: [INTERN] page main data buffer
81 * @oob_buf: [INTERN] page oob data buffer 81 * @oob_buf: [INTERN] page oob data buffer
82 * @subpagesize: [INTERN] holds the subpagesize 82 * @subpagesize: [INTERN] holds the subpagesize
83 * @ecclayout: [REPLACEABLE] the default ecc placement scheme
84 * @bbm: [REPLACEABLE] pointer to Bad Block Management 83 * @bbm: [REPLACEABLE] pointer to Bad Block Management
85 * @priv: [OPTIONAL] pointer to private chip date 84 * @priv: [OPTIONAL] pointer to private chip date
86 */ 85 */
@@ -134,7 +133,6 @@ struct onenand_chip {
134#endif 133#endif
135 134
136 int subpagesize; 135 int subpagesize;
137 struct nand_ecclayout *ecclayout;
138 136
139 void *bbm; 137 void *bbm;
140 138