1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "mtd_legacy_lite.h"
32 #include "hdf_log.h"
33 #include "mtd_core.h"
34 #include "mtd_list.h"
35 #include "osal_mem.h"
36 #include "string.h"
37
38 struct MtdDevNode {
39 char *type;
40 int status;
41 struct MtdDev *mtdDev;
42 struct MtdDevNode *next;
43 };
44
45 static struct MtdDevNode g_mtdHead;
46
GetMtd(const char * type)47 void *GetMtd(const char *type)
48 {
49 struct MtdDevNode *p = NULL;
50
51 if (type == NULL) {
52 return NULL;
53 }
54
55 for (p = g_mtdHead.next; p != NULL; p = p->next) {
56 if (strcmp(type, p->type) == 0) {
57 p->status++;
58 return p->mtdDev;
59 }
60 }
61 return NULL;
62 }
63
GetMtdInfo(const char * type)64 int GetMtdInfo(const char *type)
65 {
66 struct MtdDevNode *p = NULL;
67
68 if (type == NULL) {
69 return -1;
70 }
71
72 for (p = g_mtdHead.next; p != NULL; p = p->next) {
73 if (strcmp(type, p->type) == 0) {
74 return 0;
75 }
76 }
77 return -1;
78 }
79
FreeMtd(struct MtdDev * mtdDev)80 int FreeMtd(struct MtdDev *mtdDev)
81 {
82 struct MtdDevNode *p = NULL;
83
84 if (mtdDev == NULL) {
85 return -1;
86 }
87
88 for (p = g_mtdHead.next; p != NULL; p = p->next) {
89 if (p->mtdDev == mtdDev) {
90 p->status--;
91 return 0;
92 }
93 }
94
95 return -1;
96 }
97
DelMtdList(struct MtdDev * mtdDev)98 int DelMtdList(struct MtdDev *mtdDev)
99 {
100 struct MtdDevNode *p = NULL;
101 struct MtdDevNode *q = NULL;
102
103 if (mtdDev == NULL) {
104 return -1;
105 }
106
107 for (p = g_mtdHead.next, q = &g_mtdHead; p != NULL; q = p, p = p->next) {
108 if (p->mtdDev == mtdDev) {
109 if (p->status == 0) {
110 q->next = p->next;
111 free(p);
112 return 0;
113 }
114 return -1;
115 }
116 }
117 return -1;
118 }
119
AddMtdList(char * type,struct MtdDev * mtdDev)120 void AddMtdList(char *type, struct MtdDev *mtdDev)
121 {
122 struct MtdDevNode *p = NULL;
123 struct MtdDevNode *q = NULL;
124
125 if (type == NULL || mtdDev == NULL) {
126 return;
127 }
128
129 p = g_mtdHead.next;
130 q = (struct MtdDevNode *)OsalMemCalloc(sizeof(*q));
131 if (q == NULL) {
132 return;
133 }
134
135 q->type = type;
136 q->mtdDev = mtdDev;
137 q->status = 0;
138 g_mtdHead.next = q;
139 q->next = p;
140 }
141
142 MtdInfoLegacy g_mtdInfo;
143 MtdInfoLegacy *nand_mtd;
144 struct MtdDevice *g_nandMtd;
145 /************** compatibale of old hisi interfaces ***************************/
146 // from device/hisilicon/drivers/xxxx/mtd/nand/src/common/nand.c
nand_init(void)147 int nand_init(void)
148 {
149 HDF_LOGI("%s: this is a stub cause new mtd drivers has been used", __func__);
150 return 0;
151 }
152
153 // form device/hisilicon/drivers/xxxx/mtd/nand/src/common/nand_utils.c
hinand_read(void * memaddr,unsigned long start,unsigned long size)154 int hinand_read(void *memaddr, unsigned long start, unsigned long size)
155 {
156 int32_t ret;
157
158 if (g_nandMtd == NULL) {
159 HDF_LOGE("%s: g_nandMtd is null", __func__);
160 return -ENODEV;
161 }
162 ret = MtdDeviceRead(g_nandMtd, (off_t)start, (size_t)size, (uint8_t *)memaddr);
163 if ((unsigned long)ret != size) {
164 HDF_LOGE("%s: ret=%d, size=%lu", __func__, ret, size);
165 }
166 return ((unsigned long)ret == size) ? HDF_SUCCESS : ret;
167 }
168
hinand_write(void * memaddr,unsigned long start,unsigned long size)169 int hinand_write(void *memaddr, unsigned long start, unsigned long size)
170 {
171 int32_t ret;
172
173 if (g_nandMtd == NULL) {
174 HDF_LOGE("%s: g_nandMtd is null", __func__);
175 return -ENODEV;
176 }
177 ret = MtdDeviceWrite(g_nandMtd, (off_t)start, (size_t)size, (const uint8_t *)memaddr);
178 if ((unsigned long)ret != size) {
179 HDF_LOGE("%s: ret=%d, size=%lu", __func__, ret, size);
180 }
181 return ((unsigned long)ret == size) ? HDF_SUCCESS : ret;
182 }
183
hinand_erase(unsigned long start,unsigned long size)184 int hinand_erase(unsigned long start, unsigned long size)
185 {
186 int ret;
187 off_t failAddr;
188
189 if (g_nandMtd == NULL) {
190 HDF_LOGE("%s: g_nandMtd is null", __func__);
191 return -ENODEV;
192 }
193 ret = MtdDeviceErase(g_nandMtd, (off_t)start, (size_t)size, &failAddr);
194 if (ret != 0) {
195 HDF_LOGE("%s: MtdDeviceErase failed, ret=%d", __func__, ret);
196 }
197 return ret;
198 }
199
hinand_yaffs_read(void * memaddr,unsigned long start,unsigned long size)200 int hinand_yaffs_read(void *memaddr, unsigned long start, unsigned long size)
201 {
202 int32_t ret;
203
204 if (g_nandMtd == NULL) {
205 HDF_LOGE("%s: g_nandMtd is null", __func__);
206 return -ENODEV;
207 }
208 ret = MtdDeviceReadWithOob(g_nandMtd, (off_t)start, (size_t)size, (uint8_t *)memaddr);
209 if ((unsigned long)ret != size) {
210 HDF_LOGE("%s: ret=%d, size=%lu", __func__, ret, size);
211 }
212 return ((unsigned long)ret == size) ? HDF_SUCCESS : ret;
213 }
214
hinand_yaffs_write(void * memaddr,unsigned long start,unsigned long size)215 int hinand_yaffs_write(void *memaddr, unsigned long start, unsigned long size)
216 {
217 int32_t ret;
218
219 if (g_nandMtd == NULL) {
220 HDF_LOGE("%s: g_nandMtd is null", __func__);
221 return -ENODEV;
222 }
223 ret = MtdDeviceWriteWithOob(g_nandMtd, (off_t)start, (size_t)size, (uint8_t *)memaddr);
224 if ((unsigned long)ret != size) {
225 HDF_LOGE("%s: ret=%d, size=%lu", __func__, ret, size);
226 }
227 return ((unsigned long)ret == size) ? HDF_SUCCESS : ret;
228 }
229
hinand_yaffs_nand_block_isbad(loff_t ofs)230 int hinand_yaffs_nand_block_isbad(loff_t ofs)
231 {
232 return MtdDeviceIsBadBlock(g_nandMtd, ofs);
233 }
234
hinand_yaffs_nand_block_markbad(loff_t ofs)235 int hinand_yaffs_nand_block_markbad(loff_t ofs)
236 {
237 return MtdDeviceMarkBadBlock(g_nandMtd, ofs);
238 }
239
spinor_init(void)240 int spinor_init(void)
241 {
242 HDF_LOGI("%s: this function has been hacked ...", __func__);
243 return HDF_SUCCESS;
244 }
245
MtdDeviceLegacyNandErase(MtdInfoLegacy * mtd,EraseInfoLegacy * ops)246 static int MtdDeviceLegacyNandErase(MtdInfoLegacy *mtd, EraseInfoLegacy *ops)
247 {
248 int ret;
249 off_t failAddr;
250
251 if (mtd == NULL || ops == NULL) {
252 return -EINVAL;
253 }
254 ops->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
255
256 ret = MtdDeviceErase((struct MtdDevice *)mtd->priv, (off_t)ops->addr, (size_t)ops->len, &failAddr);
257 if (ret != HDF_SUCCESS) {
258 ops->fail_addr = failAddr;
259 }
260 return ret;
261 }
262
MtdDeviceLegacyNandRead(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,char * buf)263 static int MtdDeviceLegacyNandRead(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, char *buf)
264 {
265 int ret;
266
267 if (mtd == NULL) {
268 return -EINVAL;
269 }
270
271 ret = MtdDeviceRead((struct MtdDevice *)mtd->priv, addr, len, (uint8_t *)buf);
272 *retlen = (ret == HDF_SUCCESS) ? len : 0;
273 return ret;
274 }
275
MtdDeviceLegacyNandWrite(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,const char * buf)276 static int MtdDeviceLegacyNandWrite(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, const char *buf)
277 {
278 int ret;
279
280 if (mtd == NULL) {
281 return -EINVAL;
282 }
283
284 ret = MtdDeviceWrite((struct MtdDevice *)mtd->priv, addr, len, (const uint8_t *)buf);
285 *retlen = (ret == HDF_SUCCESS) ? len : 0;
286 return ret;
287 }
288
MtdDeviceLegacyNandReadOob(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,char * buf)289 static int MtdDeviceLegacyNandReadOob(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, char *buf)
290 {
291 int ret;
292
293 if (mtd == NULL) {
294 return -EINVAL;
295 }
296
297 ret = MtdDeviceReadWithOob((struct MtdDevice *)mtd->priv, addr, len, (uint8_t *)buf);
298 *retlen = (ret == HDF_SUCCESS) ? len : 0;
299 return ret;
300 }
301
MtdDeviceLegacyNandWriteOob(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,const char * buf)302 static int MtdDeviceLegacyNandWriteOob(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, const char *buf)
303 {
304 int ret;
305
306 if (mtd == NULL) {
307 return -EINVAL;
308 }
309
310 ret = MtdDeviceWriteWithOob((struct MtdDevice *)mtd->priv, addr, len, (const uint8_t *)buf);
311 *retlen = (ret == HDF_SUCCESS) ? len : 0;
312 return ret;
313 }
314
MtdDeviceLegacyBlockIsBad(MtdInfoLegacy * mtd,off_t ofs)315 static int MtdDeviceLegacyBlockIsBad(MtdInfoLegacy *mtd, off_t ofs)
316 {
317 if (mtd == NULL) {
318 return -EINVAL;
319 }
320
321 return (int)MtdDeviceIsBadBlock((struct MtdDevice *)mtd->priv, ofs);
322 }
323
MtdDeviceLegacyBlockMarkBad(MtdInfoLegacy * mtd,off_t ofs)324 static int MtdDeviceLegacyBlockMarkBad(MtdInfoLegacy *mtd, off_t ofs)
325 {
326 if (mtd == NULL) {
327 return -EINVAL;
328 }
329
330 return (int)MtdDeviceMarkBadBlock((struct MtdDevice *)mtd->priv, ofs);
331 }
332
MtdDeviceLegacyFillMtdInfo(struct MtdDevice * mtdDevice)333 void MtdDeviceLegacyFillMtdInfo(struct MtdDevice *mtdDevice)
334 {
335 if (mtdDevice == NULL) {
336 return;
337 }
338 nand_mtd = &g_mtdInfo;
339
340 nand_mtd->size = mtdDevice->capacity;
341 nand_mtd->erasesize = mtdDevice->eraseSize;
342 nand_mtd->writesize = mtdDevice->writeSize;
343 nand_mtd->oobsize = mtdDevice->oobSize;
344 nand_mtd->name = "nand";
345 nand_mtd->type = MTD_NANDFLASH;
346 nand_mtd->flags = MTD_CAP_NANDFLASH;
347
348 nand_mtd->erase = MtdDeviceLegacyNandErase;
349 nand_mtd->read = MtdDeviceLegacyNandRead;
350 nand_mtd->write = MtdDeviceLegacyNandWrite;
351 nand_mtd->read_oob = MtdDeviceLegacyNandReadOob;
352 nand_mtd->write_oob = MtdDeviceLegacyNandWriteOob;
353 nand_mtd->block_isbad = MtdDeviceLegacyBlockIsBad;
354 nand_mtd->block_markbad = MtdDeviceLegacyBlockMarkBad;
355 nand_mtd->priv = mtdDevice;
356
357 g_nandMtd = mtdDevice;
358 }
359