diff options
Diffstat (limited to 'include/linux/mtd/mtd.h')
-rw-r--r-- | include/linux/mtd/mtd.h | 304 |
1 files changed, 84 insertions, 220 deletions
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index d43dc25af82e..cf5ea8cdcf8e 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
@@ -164,6 +164,9 @@ struct mtd_info { | |||
164 | /* ECC layout structure pointer - read only! */ | 164 | /* ECC layout structure pointer - read only! */ |
165 | struct nand_ecclayout *ecclayout; | 165 | struct nand_ecclayout *ecclayout; |
166 | 166 | ||
167 | /* max number of correctible bit errors per writesize */ | ||
168 | unsigned int ecc_strength; | ||
169 | |||
167 | /* Data for variable erase regions. If numeraseregions is zero, | 170 | /* Data for variable erase regions. If numeraseregions is zero, |
168 | * it means that the whole device has erasesize as given above. | 171 | * it means that the whole device has erasesize as given above. |
169 | */ | 172 | */ |
@@ -174,52 +177,52 @@ struct mtd_info { | |||
174 | * Do not call via these pointers, use corresponding mtd_*() | 177 | * Do not call via these pointers, use corresponding mtd_*() |
175 | * wrappers instead. | 178 | * wrappers instead. |
176 | */ | 179 | */ |
177 | int (*erase) (struct mtd_info *mtd, struct erase_info *instr); | 180 | int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); |
178 | int (*point) (struct mtd_info *mtd, loff_t from, size_t len, | 181 | int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, |
179 | size_t *retlen, void **virt, resource_size_t *phys); | 182 | size_t *retlen, void **virt, resource_size_t *phys); |
180 | void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len); | 183 | int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); |
181 | unsigned long (*get_unmapped_area) (struct mtd_info *mtd, | 184 | unsigned long (*_get_unmapped_area) (struct mtd_info *mtd, |
182 | unsigned long len, | 185 | unsigned long len, |
183 | unsigned long offset, | 186 | unsigned long offset, |
184 | unsigned long flags); | 187 | unsigned long flags); |
185 | int (*read) (struct mtd_info *mtd, loff_t from, size_t len, | 188 | int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, |
186 | size_t *retlen, u_char *buf); | 189 | size_t *retlen, u_char *buf); |
187 | int (*write) (struct mtd_info *mtd, loff_t to, size_t len, | 190 | int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, |
188 | size_t *retlen, const u_char *buf); | 191 | size_t *retlen, const u_char *buf); |
189 | int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, | 192 | int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, |
190 | size_t *retlen, const u_char *buf); | 193 | size_t *retlen, const u_char *buf); |
191 | int (*read_oob) (struct mtd_info *mtd, loff_t from, | 194 | int (*_read_oob) (struct mtd_info *mtd, loff_t from, |
192 | struct mtd_oob_ops *ops); | ||
193 | int (*write_oob) (struct mtd_info *mtd, loff_t to, | ||
194 | struct mtd_oob_ops *ops); | 195 | struct mtd_oob_ops *ops); |
195 | int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, | 196 | int (*_write_oob) (struct mtd_info *mtd, loff_t to, |
196 | size_t len); | 197 | struct mtd_oob_ops *ops); |
197 | int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, | 198 | int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, |
198 | size_t len, size_t *retlen, u_char *buf); | 199 | size_t len); |
199 | int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, | 200 | int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, |
200 | size_t len); | 201 | size_t len, size_t *retlen, u_char *buf); |
201 | int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, | 202 | int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, |
202 | size_t len, size_t *retlen, u_char *buf); | 203 | size_t len); |
203 | int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t to, size_t len, | 204 | int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, |
204 | size_t *retlen, u_char *buf); | 205 | size_t len, size_t *retlen, u_char *buf); |
205 | int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, | 206 | int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, |
206 | size_t len); | 207 | size_t len, size_t *retlen, u_char *buf); |
207 | int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, | 208 | int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, |
209 | size_t len); | ||
210 | int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs, | ||
208 | unsigned long count, loff_t to, size_t *retlen); | 211 | unsigned long count, loff_t to, size_t *retlen); |
209 | void (*sync) (struct mtd_info *mtd); | 212 | void (*_sync) (struct mtd_info *mtd); |
210 | int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 213 | int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
211 | int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 214 | int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
212 | int (*is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 215 | int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
213 | int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); | 216 | int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); |
214 | int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); | 217 | int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); |
215 | int (*suspend) (struct mtd_info *mtd); | 218 | int (*_suspend) (struct mtd_info *mtd); |
216 | void (*resume) (struct mtd_info *mtd); | 219 | void (*_resume) (struct mtd_info *mtd); |
217 | /* | 220 | /* |
218 | * If the driver is something smart, like UBI, it may need to maintain | 221 | * If the driver is something smart, like UBI, it may need to maintain |
219 | * its own reference counting. The below functions are only for driver. | 222 | * its own reference counting. The below functions are only for driver. |
220 | */ | 223 | */ |
221 | int (*get_device) (struct mtd_info *mtd); | 224 | int (*_get_device) (struct mtd_info *mtd); |
222 | void (*put_device) (struct mtd_info *mtd); | 225 | void (*_put_device) (struct mtd_info *mtd); |
223 | 226 | ||
224 | /* Backing device capabilities for this device | 227 | /* Backing device capabilities for this device |
225 | * - provides mmap capabilities | 228 | * - provides mmap capabilities |
@@ -240,214 +243,75 @@ struct mtd_info { | |||
240 | int usecount; | 243 | int usecount; |
241 | }; | 244 | }; |
242 | 245 | ||
243 | /* | 246 | int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); |
244 | * Erase is an asynchronous operation. Device drivers are supposed | 247 | int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, |
245 | * to call instr->callback() whenever the operation completes, even | 248 | void **virt, resource_size_t *phys); |
246 | * if it completes with a failure. | 249 | int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len); |
247 | * Callers are supposed to pass a callback function and wait for it | 250 | unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, |
248 | * to be called before writing to the block. | 251 | unsigned long offset, unsigned long flags); |
249 | */ | 252 | int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, |
250 | static inline int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) | 253 | u_char *buf); |
251 | { | 254 | int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, |
252 | return mtd->erase(mtd, instr); | 255 | const u_char *buf); |
253 | } | 256 | int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, |
254 | 257 | const u_char *buf); | |
255 | /* | ||
256 | * This stuff for eXecute-In-Place. phys is optional and may be set to NULL. | ||
257 | */ | ||
258 | static inline int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, | ||
259 | size_t *retlen, void **virt, resource_size_t *phys) | ||
260 | { | ||
261 | *retlen = 0; | ||
262 | if (!mtd->point) | ||
263 | return -EOPNOTSUPP; | ||
264 | return mtd->point(mtd, from, len, retlen, virt, phys); | ||
265 | } | ||
266 | |||
267 | /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ | ||
268 | static inline void mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len) | ||
269 | { | ||
270 | return mtd->unpoint(mtd, from, len); | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * Allow NOMMU mmap() to directly map the device (if not NULL) | ||
275 | * - return the address to which the offset maps | ||
276 | * - return -ENOSYS to indicate refusal to do the mapping | ||
277 | */ | ||
278 | static inline unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, | ||
279 | unsigned long len, | ||
280 | unsigned long offset, | ||
281 | unsigned long flags) | ||
282 | { | ||
283 | if (!mtd->get_unmapped_area) | ||
284 | return -EOPNOTSUPP; | ||
285 | return mtd->get_unmapped_area(mtd, len, offset, flags); | ||
286 | } | ||
287 | |||
288 | static inline int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
289 | size_t *retlen, u_char *buf) | ||
290 | { | ||
291 | return mtd->read(mtd, from, len, retlen, buf); | ||
292 | } | ||
293 | |||
294 | static inline int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
295 | size_t *retlen, const u_char *buf) | ||
296 | { | ||
297 | *retlen = 0; | ||
298 | if (!mtd->write) | ||
299 | return -EROFS; | ||
300 | return mtd->write(mtd, to, len, retlen, buf); | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * In blackbox flight recorder like scenarios we want to make successful writes | ||
305 | * in interrupt context. panic_write() is only intended to be called when its | ||
306 | * known the kernel is about to panic and we need the write to succeed. Since | ||
307 | * the kernel is not going to be running for much longer, this function can | ||
308 | * break locks and delay to ensure the write succeeds (but not sleep). | ||
309 | */ | ||
310 | static inline int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
311 | size_t *retlen, const u_char *buf) | ||
312 | { | ||
313 | *retlen = 0; | ||
314 | if (!mtd->panic_write) | ||
315 | return -EOPNOTSUPP; | ||
316 | return mtd->panic_write(mtd, to, len, retlen, buf); | ||
317 | } | ||
318 | 258 | ||
319 | static inline int mtd_read_oob(struct mtd_info *mtd, loff_t from, | 259 | static inline int mtd_read_oob(struct mtd_info *mtd, loff_t from, |
320 | struct mtd_oob_ops *ops) | 260 | struct mtd_oob_ops *ops) |
321 | { | 261 | { |
322 | ops->retlen = ops->oobretlen = 0; | 262 | ops->retlen = ops->oobretlen = 0; |
323 | if (!mtd->read_oob) | 263 | if (!mtd->_read_oob) |
324 | return -EOPNOTSUPP; | 264 | return -EOPNOTSUPP; |
325 | return mtd->read_oob(mtd, from, ops); | 265 | return mtd->_read_oob(mtd, from, ops); |
326 | } | 266 | } |
327 | 267 | ||
328 | static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, | 268 | static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, |
329 | struct mtd_oob_ops *ops) | 269 | struct mtd_oob_ops *ops) |
330 | { | 270 | { |
331 | ops->retlen = ops->oobretlen = 0; | 271 | ops->retlen = ops->oobretlen = 0; |
332 | if (!mtd->write_oob) | 272 | if (!mtd->_write_oob) |
333 | return -EOPNOTSUPP; | ||
334 | return mtd->write_oob(mtd, to, ops); | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Method to access the protection register area, present in some flash | ||
339 | * devices. The user data is one time programmable but the factory data is read | ||
340 | * only. | ||
341 | */ | ||
342 | static inline int mtd_get_fact_prot_info(struct mtd_info *mtd, | ||
343 | struct otp_info *buf, size_t len) | ||
344 | { | ||
345 | if (!mtd->get_fact_prot_info) | ||
346 | return -EOPNOTSUPP; | 273 | return -EOPNOTSUPP; |
347 | return mtd->get_fact_prot_info(mtd, buf, len); | 274 | if (!(mtd->flags & MTD_WRITEABLE)) |
348 | } | 275 | return -EROFS; |
349 | 276 | return mtd->_write_oob(mtd, to, ops); | |
350 | static inline int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, | ||
351 | size_t len, size_t *retlen, | ||
352 | u_char *buf) | ||
353 | { | ||
354 | *retlen = 0; | ||
355 | if (!mtd->read_fact_prot_reg) | ||
356 | return -EOPNOTSUPP; | ||
357 | return mtd->read_fact_prot_reg(mtd, from, len, retlen, buf); | ||
358 | } | ||
359 | |||
360 | static inline int mtd_get_user_prot_info(struct mtd_info *mtd, | ||
361 | struct otp_info *buf, | ||
362 | size_t len) | ||
363 | { | ||
364 | if (!mtd->get_user_prot_info) | ||
365 | return -EOPNOTSUPP; | ||
366 | return mtd->get_user_prot_info(mtd, buf, len); | ||
367 | } | ||
368 | |||
369 | static inline int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, | ||
370 | size_t len, size_t *retlen, | ||
371 | u_char *buf) | ||
372 | { | ||
373 | *retlen = 0; | ||
374 | if (!mtd->read_user_prot_reg) | ||
375 | return -EOPNOTSUPP; | ||
376 | return mtd->read_user_prot_reg(mtd, from, len, retlen, buf); | ||
377 | } | ||
378 | |||
379 | static inline int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, | ||
380 | size_t len, size_t *retlen, | ||
381 | u_char *buf) | ||
382 | { | ||
383 | *retlen = 0; | ||
384 | if (!mtd->write_user_prot_reg) | ||
385 | return -EOPNOTSUPP; | ||
386 | return mtd->write_user_prot_reg(mtd, to, len, retlen, buf); | ||
387 | } | 277 | } |
388 | 278 | ||
389 | static inline int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, | 279 | int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, |
390 | size_t len) | 280 | size_t len); |
391 | { | 281 | int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, |
392 | if (!mtd->lock_user_prot_reg) | 282 | size_t *retlen, u_char *buf); |
393 | return -EOPNOTSUPP; | 283 | int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, |
394 | return mtd->lock_user_prot_reg(mtd, from, len); | 284 | size_t len); |
395 | } | 285 | int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, |
286 | size_t *retlen, u_char *buf); | ||
287 | int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, | ||
288 | size_t *retlen, u_char *buf); | ||
289 | int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); | ||
396 | 290 | ||
397 | int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, | 291 | int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, |
398 | unsigned long count, loff_t to, size_t *retlen); | 292 | unsigned long count, loff_t to, size_t *retlen); |
399 | 293 | ||
400 | static inline void mtd_sync(struct mtd_info *mtd) | 294 | static inline void mtd_sync(struct mtd_info *mtd) |
401 | { | 295 | { |
402 | if (mtd->sync) | 296 | if (mtd->_sync) |
403 | mtd->sync(mtd); | 297 | mtd->_sync(mtd); |
404 | } | ||
405 | |||
406 | /* Chip-supported device locking */ | ||
407 | static inline int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | ||
408 | { | ||
409 | if (!mtd->lock) | ||
410 | return -EOPNOTSUPP; | ||
411 | return mtd->lock(mtd, ofs, len); | ||
412 | } | 298 | } |
413 | 299 | ||
414 | static inline int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | 300 | int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
415 | { | 301 | int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
416 | if (!mtd->unlock) | 302 | int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
417 | return -EOPNOTSUPP; | 303 | int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); |
418 | return mtd->unlock(mtd, ofs, len); | 304 | int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); |
419 | } | ||
420 | |||
421 | static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) | ||
422 | { | ||
423 | if (!mtd->is_locked) | ||
424 | return -EOPNOTSUPP; | ||
425 | return mtd->is_locked(mtd, ofs, len); | ||
426 | } | ||
427 | 305 | ||
428 | static inline int mtd_suspend(struct mtd_info *mtd) | 306 | static inline int mtd_suspend(struct mtd_info *mtd) |
429 | { | 307 | { |
430 | return mtd->suspend ? mtd->suspend(mtd) : 0; | 308 | return mtd->_suspend ? mtd->_suspend(mtd) : 0; |
431 | } | 309 | } |
432 | 310 | ||
433 | static inline void mtd_resume(struct mtd_info *mtd) | 311 | static inline void mtd_resume(struct mtd_info *mtd) |
434 | { | 312 | { |
435 | if (mtd->resume) | 313 | if (mtd->_resume) |
436 | mtd->resume(mtd); | 314 | mtd->_resume(mtd); |
437 | } | ||
438 | |||
439 | static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) | ||
440 | { | ||
441 | if (!mtd->block_isbad) | ||
442 | return 0; | ||
443 | return mtd->block_isbad(mtd, ofs); | ||
444 | } | ||
445 | |||
446 | static inline int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) | ||
447 | { | ||
448 | if (!mtd->block_markbad) | ||
449 | return -EOPNOTSUPP; | ||
450 | return mtd->block_markbad(mtd, ofs); | ||
451 | } | 315 | } |
452 | 316 | ||
453 | static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) | 317 | static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) |
@@ -482,12 +346,12 @@ static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd) | |||
482 | 346 | ||
483 | static inline int mtd_has_oob(const struct mtd_info *mtd) | 347 | static inline int mtd_has_oob(const struct mtd_info *mtd) |
484 | { | 348 | { |
485 | return mtd->read_oob && mtd->write_oob; | 349 | return mtd->_read_oob && mtd->_write_oob; |
486 | } | 350 | } |
487 | 351 | ||
488 | static inline int mtd_can_have_bb(const struct mtd_info *mtd) | 352 | static inline int mtd_can_have_bb(const struct mtd_info *mtd) |
489 | { | 353 | { |
490 | return !!mtd->block_isbad; | 354 | return !!mtd->_block_isbad; |
491 | } | 355 | } |
492 | 356 | ||
493 | /* Kernel-side ioctl definitions */ | 357 | /* Kernel-side ioctl definitions */ |