1 /*
2  * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3  */
4 
5 #ifndef __AOS_MTD_H
6 #define __AOS_MTD_H
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <aos/kernel.h>
11 #include "device/aos_device.h"
12 
13 #define MTD_TYPE_NOR    1
14 #define MTD_TYPE_NAND   2
15 
16 #define MTD_DEVICE_NAME_PREFIX "mtdblock"
17 #define MTD_DEVICE_NAME_FORMAT MTD_DEVICE_NAME_PREFIX"%u"
18 #define MTD_PARTITION_NAME_MAX 16
19 #define MTD_DEVICE_NAME_MAX 16
20 
21 #define IOC_MTD_BASE   'M'
22 #define IOC_MTD_GET_SIZE      (IOC_MTD_BASE + 0x1)
23 #define IOC_MTD_GET_OFFSET    (IOC_MTD_BASE + 0x2)
24 #define IOC_MTD_ERASE         (IOC_MTD_BASE + 0x3)
25 
26 /* standard partition names */
27 #define MTD_PART_NAME_BOOTLOADER "BOOT"    /*Bootloader*/
28 #define MTD_PART_NAME_BOOTLOADER_SEC "BOOTSEC" /*Secure Boot*/
29 #define MTD_PART_NAME_2ND_BOOTLOADER "BOOT2A"  /*The 2nd bootloader*/
30 #define MTD_PART_NAME_2ND_BOOTLOADER2 "BOOT2B" /*The 2nd bootloader backup*/
31 #define MTD_PART_NAME_ENV "ENV"   /* Eviroment, e.g. for OTA*/
32 #define MTD_PART_NAME_ENV2 "ENV2"  /* Enviroment, e.g. others.*/
33 #define MTD_PART_NAME_DTB "DTB"
34 #define MTD_PART_NAME_KERNEL "KERNEL"
35 #define MTD_PART_NAME_KERNEL2 "KERNEL2"
36 #define MTD_PART_NAME_ROMFS "ROMFS"
37 #define MTD_PART_NAME_ROMFS2 "ROMFS2"
38 #define MTD_PART_NAME_LITTLEFS "LFS"
39 #define MTD_PART_NAME_LITTLEFS2 "LFS2"
40 #define MTD_PART_NAME_APP "APP"
41 #define MTD_PART_NAME_FACTORY "FACTORY"  /* Factory data*/
42 #define MTD_PART_NAME_FACTORY2 "FACTORY2" /* Factory data backup */
43 #define MTD_PART_NAME_KV "KV"
44 #define MTD_PART_NAME_UNKNOWN "UNKNOWN"
45 /* subject to add more hereafter ... */
46 
47  /**
48   * MTD operation modes
49   *
50   * @MTD_OPM_PLACE_OOB:    OOB data are placed at the given offset (default)
51   * @MTD_OPM_AUTO_OOB:    OOB data are automatically placed at the free areas
52   * @MTD_OPM_RAW:        data are transferred as-is, with no error correction;
53   */
54 enum mtd_opm
55 {
56     MTD_OPM_PLACE_OOB = 0,
57     MTD_OPM_AUTO_OOB = 1,
58     MTD_OPM_RAW = 2,
59 };
60 
61 struct mtd_erase_info {
62     unsigned long offset;
63     unsigned long length;
64 };
65 
66 struct mtd_block_info {
67     unsigned long block_size;
68     unsigned long block_start;
69     unsigned long block_end;
70 };
71 
72 
73 struct mtd_oob_region
74 {
75     uint8_t offset;
76     uint8_t length;
77 };
78 
79 typedef struct mtd_info
80 {
81     struct aos_device parent;
82     const struct mtd_ops *ops;
83 
84     uint16_t oob_size;
85     uint16_t sector_size;   /* Minimal writable flash unit size */
86     uint32_t block_size:28; /* Erase size for the device */
87     uint32_t type:4;
88 
89     size_t size;    /* Total size of the MTD */
90     off_t offset;  /* At which this MTD starts, from the beginning of the MEMORY */
91     struct mtd_info *master;
92 
93     void *priv;
94 } aos_mtd_t;
95 
96 struct mtd_io_desc
97 {
98     uint8_t mode;      /* operation mode(enum mtd_opm) */
99     uint8_t ooblen;    /* number of oob bytes to write/read */
100     uint8_t oobretlen; /* number of oob bytes written/read */
101     uint8_t ooboffs;   /* offset in the oob area  */
102     uint8_t *oobbuf;
103 
104     size_t  datlen;    /* number of data bytes to write/read */
105     size_t  datretlen; /* number of data bytes written/read */
106     uint8_t *datbuf;   /* if NULL only oob are read/written */
107 };
108 
109 struct mtd_ops
110 {
111     int(*erase)(aos_mtd_t *mtd, off_t addr, size_t len);    /* return 0 if success */
112     int(*read) (aos_mtd_t *mtd, off_t from, struct mtd_io_desc *ops); /* return 0 if success */
113     int(*write) (aos_mtd_t *mtd, off_t to, struct mtd_io_desc *ops);  /* return 0 if success */
114     int(*isbad) (aos_mtd_t *mtd, uint32_t block);    /* return 1 if bad, 0 not bad */
115     int(*markbad) (aos_mtd_t *mtd, uint32_t block);  /* return 0 if success */
116 };
117 
118 struct mtd_part
119 {
120     const char *name;           /* platform specific name of the MTD partition provided, optionally to be the same as name_std */
121     const char *name_std;       /* standard name of the MTD partition define in alios */
122     off_t offset;               /* start addr of partion */
123     size_t size;                /* size of partion */
124 };
125 
126 struct mtd_part_info
127 {
128     off_t offset;                               /* start addr of partion */
129     size_t size;                                /* size of partion */
130     char part_name[MTD_PARTITION_NAME_MAX];     /* original name of the MTD partition, usually provided by platform */
131     char part_name_std[MTD_PARTITION_NAME_MAX]; /* standard name of the MTD partition, defined by alios */
132     char dev_name[MTD_DEVICE_NAME_MAX];         /* device name of the MTD partition */
133 };
134 
135 /**
136  * Open a mtd device
137  *
138  * @param[in]   name      partition name
139  *
140  * @return      A mtd device handle, NULL: error
141  */
142 aos_mtd_t* aos_mtd_open(const char *name);
143 
144 /**
145  * Close a mtd device
146  *
147  * @param[in]   mtd       A mtd device handle
148  *
149  * @return      0:success, <0: error
150  */
151 aos_status_t aos_mtd_close(aos_mtd_t *mtd);
152 
153 /**
154  * Read data from mtd device
155  *
156  * @param[in]   mtd       A mtd device handle
157  * @param[in]   offset    The offset address of mtd device which read from
158  * @param[out]  buf       The buffer to store data read from mtd device
159  * @param[in]   size      The size of request to read
160  *
161  * @return      >0:The size of data that really read; 0: end of device; <0: error
162  */
163 ssize_t aos_mtd_read(aos_mtd_t *mtd, off_t offset, void *buf, size_t size);
164 
165 /**
166  * Read out-of-band data from mtd device
167  *
168  * @param[in]   mtd       A mtd device handle
169  * @param[in]   offset    The offset address of mtd device which read from
170  * @param[in]   info      The description information of mtd IO
171  *
172  * @return      >0:The size of out-of-band data that really read; 0: end of device; <0: error
173  */
174 ssize_t aos_mtd_oob_read(aos_mtd_t *mtd, off_t offset, struct mtd_io_desc *info);
175 
176 /**
177  * Write data to mtd device
178  *
179  * @param[in]   mtd       A mtd device handle
180  * @param[in]   offset    The offset address of mtd device which write to
181  * @param[in]   buf       The buffer to store data to be written
182  * @param[in]   size      The size of request to write
183 
184  * @return      >0:The size of data that really be written; <0: error
185  */
186 ssize_t aos_mtd_write(aos_mtd_t *mtd, off_t offset, const void *buf, size_t size);
187 
188 /**
189  * Write out-of-band data to mtd device
190  *
191  * @param[in]   mtd       A mtd device handle
192  * @param[in]   offset    The offset address of mtd device which write to
193  * @param[in]   info      The description information of mtd IO
194  *
195  * @return      >0:The size of out-of-band data that really written; <0: error
196  */
197 ssize_t aos_mtd_oob_write(aos_mtd_t *mtd, off_t offset, struct mtd_io_desc *info);
198 
199 /**
200  * Erase a region of mtd device
201  *
202  * @param[in]   mtd       A mtd device handle
203  * @param[in]   offset    The offset address of mtd device to be erased
204  * @param[in]   size      The size of request to be erased
205  *
206  * @return      0: success, <0: error
207  */
208 aos_status_t aos_mtd_erase(aos_mtd_t *mtd, off_t offset, size_t size);
209 
210 /**
211  * Erase a block of mtd device
212  *
213  * @param[in]   mtd       A mtd device handle
214  * @param[in]   block     The block index to be erased
215  *
216  * @return      0: success, <0: error
217  */
218 aos_status_t aos_mtd_block_erase(aos_mtd_t *mtd, uint32_t block);
219 
220 /**
221  * Mark a block of mtd device as bad
222  *
223  * @param[in]   mtd       A mtd device handle
224  * @param[in]   block     The block index to be marked
225  *
226  * @return      0: success, <0: error
227  */
228 aos_status_t aos_mtd_block_mark_bad(aos_mtd_t *mtd, uint32_t block);
229 
230 /**
231  * Check if a block of mtd device is bad
232  *
233  * @param[in]   mtd       A mtd device handle
234  * @param[in]   block     The block index to be checked
235  *
236  * @return      0: success, <0: error
237  */
238 aos_status_t aos_mtd_block_is_bad(aos_mtd_t *mtd, uint32_t block);
239 
240 
241 /* get mtd partition information, caller to free the info memory */
242 int aos_mtd_part_info_get(struct mtd_part_info **info, int *cnt);
243 
244 /* register mtd paritions */
245 int aos_mtd_register(aos_mtd_t *master, const struct mtd_part *parts, int np);
246 
247 #endif /*__AOS_MTD_H*/
248