1 /*
2 * Copyright (c) 2021-2023 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("nand_init: this is a stub cause new mtd drivers has been used!");
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("hinand_read: g_nandMtd is null!");
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("hinand_read: ret=%d, size=%lu!", 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("hinand_write: g_nandMtd is null!");
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("hinand_write: ret=%d, size=%lu!", 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("hinand_erase: g_nandMtd is null!");
191 return -ENODEV;
192 }
193 ret = MtdDeviceErase(g_nandMtd, (off_t)start, (size_t)size, &failAddr);
194 if (ret != 0) {
195 HDF_LOGE("hinand_erase: MtdDeviceErase fail, ret= %d!", 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("hinand_yaffs_read: g_nandMtd is null!");
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("hinand_yaffs_read: ret=%d, size=%lu!", 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("hinand_yaffs_write: g_nandMtd is null!");
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("hinand_yaffs_write: ret=%d, size=%lu!", 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("spinor_init: this function has been hacked ...");
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 HDF_LOGE("MtdDeviceLegacyNandErase: mtd or ops is null!");
253 return -EINVAL;
254 }
255 ops->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
256
257 ret = MtdDeviceErase((struct MtdDevice *)mtd->priv, (off_t)ops->addr, (size_t)ops->len, &failAddr);
258 if (ret != HDF_SUCCESS) {
259 ops->fail_addr = failAddr;
260 }
261 return ret;
262 }
263
MtdDeviceLegacyNandRead(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,char * buf)264 static int MtdDeviceLegacyNandRead(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, char *buf)
265 {
266 int ret;
267
268 if (mtd == NULL || mtd->priv == NULL || retlen == NULL || buf == NULL) {
269 HDF_LOGE("MtdDeviceLegacyNandRead: function parameter is null!");
270 return -EINVAL;
271 }
272
273 ret = MtdDeviceRead((struct MtdDevice *)mtd->priv, addr, len, (uint8_t *)buf);
274 *retlen = (ret == HDF_SUCCESS) ? len : 0;
275 return ret;
276 }
277
MtdDeviceLegacyNandWrite(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,const char * buf)278 static int MtdDeviceLegacyNandWrite(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, const char *buf)
279 {
280 int ret;
281
282 if (mtd == NULL || retlen == NULL) {
283 HDF_LOGE("MtdDeviceLegacyNandWrite: function parameter is null!");
284 return -EINVAL;
285 }
286
287 ret = MtdDeviceWrite((struct MtdDevice *)mtd->priv, addr, len, (const uint8_t *)buf);
288 *retlen = (ret == HDF_SUCCESS) ? len : 0;
289 return ret;
290 }
291
MtdDeviceLegacyNandReadOob(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,char * buf)292 static int MtdDeviceLegacyNandReadOob(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, char *buf)
293 {
294 int ret;
295
296 if (mtd == NULL || retlen == NULL) {
297 HDF_LOGE("MtdDeviceLegacyNandReadOob: function parameter is null!");
298 return -EINVAL;
299 }
300
301 ret = MtdDeviceReadWithOob((struct MtdDevice *)mtd->priv, addr, len, (uint8_t *)buf);
302 *retlen = (ret == HDF_SUCCESS) ? len : 0;
303 return ret;
304 }
305
MtdDeviceLegacyNandWriteOob(MtdInfoLegacy * mtd,off_t addr,size_t len,size_t * retlen,const char * buf)306 static int MtdDeviceLegacyNandWriteOob(MtdInfoLegacy *mtd, off_t addr, size_t len, size_t *retlen, const char *buf)
307 {
308 int ret;
309
310 if (mtd == NULL || retlen == NULL) {
311 HDF_LOGE("MtdDeviceLegacyNandWriteOob: function parameter is null!");
312 return -EINVAL;
313 }
314
315 ret = MtdDeviceWriteWithOob((struct MtdDevice *)mtd->priv, addr, len, (const uint8_t *)buf);
316 *retlen = (ret == HDF_SUCCESS) ? len : 0;
317 return ret;
318 }
319
MtdDeviceLegacyBlockIsBad(MtdInfoLegacy * mtd,off_t ofs)320 static int MtdDeviceLegacyBlockIsBad(MtdInfoLegacy *mtd, off_t ofs)
321 {
322 if (mtd == NULL) {
323 HDF_LOGE("MtdDeviceLegacyBlockIsBad: mtd is null!");
324 return -EINVAL;
325 }
326
327 return (int)MtdDeviceIsBadBlock((struct MtdDevice *)mtd->priv, ofs);
328 }
329
MtdDeviceLegacyBlockMarkBad(MtdInfoLegacy * mtd,off_t ofs)330 static int MtdDeviceLegacyBlockMarkBad(MtdInfoLegacy *mtd, off_t ofs)
331 {
332 if (mtd == NULL) {
333 HDF_LOGE("MtdDeviceLegacyBlockMarkBad: mtd is null!");
334 return -EINVAL;
335 }
336
337 return (int)MtdDeviceMarkBadBlock((struct MtdDevice *)mtd->priv, ofs);
338 }
339
MtdDeviceLegacyFillMtdInfo(struct MtdDevice * mtdDevice)340 void MtdDeviceLegacyFillMtdInfo(struct MtdDevice *mtdDevice)
341 {
342 if (mtdDevice == NULL) {
343 HDF_LOGE("MtdDeviceLegacyFillMtdInfo: mtdDevice is null!");
344 return;
345 }
346 nand_mtd = &g_mtdInfo;
347
348 nand_mtd->size = mtdDevice->capacity;
349 nand_mtd->erasesize = mtdDevice->eraseSize;
350 nand_mtd->writesize = mtdDevice->writeSize;
351 nand_mtd->oobsize = mtdDevice->oobSize;
352 nand_mtd->name = "nand";
353 nand_mtd->type = MTD_NANDFLASH;
354 nand_mtd->flags = MTD_CAP_NANDFLASH;
355
356 nand_mtd->erase = MtdDeviceLegacyNandErase;
357 nand_mtd->read = MtdDeviceLegacyNandRead;
358 nand_mtd->write = MtdDeviceLegacyNandWrite;
359 nand_mtd->read_oob = MtdDeviceLegacyNandReadOob;
360 nand_mtd->write_oob = MtdDeviceLegacyNandWriteOob;
361 nand_mtd->block_isbad = MtdDeviceLegacyBlockIsBad;
362 nand_mtd->block_markbad = MtdDeviceLegacyBlockMarkBad;
363 nand_mtd->priv = mtdDevice;
364
365 g_nandMtd = mtdDevice;
366 }
367