From 70d5098a4b1551864dd7df43f67b7f606a1a6438 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 10 Jan 2012 13:26:58 +0100 Subject: mtd: mtdblock: call mtd_sync() only if opened for write Because it is useless to call it if the device is opened in R/O mode, and also harmful: on CFI NOR flash it may block for long time waiting for erase operations to complete is another partition with a R/W file-system on this chip. Artem Bityutskiy: write commit message, amend the patch to match the latest tree (we use mtd_sync(), not mtd->sync() nowadays). Signed-off-by: Alexander Stein Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/blktrans.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index 1bbd9f289245..ed270bd2e4df 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h @@ -47,6 +47,7 @@ struct mtd_blktrans_dev { struct request_queue *rq; spinlock_t queue_lock; void *priv; + fmode_t file_mode; }; struct mtd_blktrans_ops { -- cgit v1.2.3 From 661a08327d11bcc4cf649c5ae4bdf2db0a87b320 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 13 Jan 2012 18:11:50 -0800 Subject: mtd: nand: correct comment on nand_chip badblockbits The description for badblockbits is incorrect. I think someone just made up a false description on the spot to satisfy some kerneldoc warning. Signed-off-by: Brian Norris Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/nand.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 63b5a8b6dfbd..609868f3db42 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -448,8 +448,9 @@ struct nand_buffers { * will be copied to the appropriate nand_bbt_descr's. * @badblockpos: [INTERN] position of the bad block marker in the oob * area. - * @badblockbits: [INTERN] number of bits to left-shift the bad block - * number + * @badblockbits: [INTERN] minimum number of set bits in a good block's + * bad block marker position; i.e., BBM == 11110111b is + * not bad when badblockbits == 7 * @cellinfo: [INTERN] MLC/multichip data from chip ident * @numchips: [INTERN] number of physical chips * @chipsize: [INTERN] the size of one chip for multichip arrays -- cgit v1.2.3 From f18dbbb1bfe06ea3995b55c2f533057da9e9294a Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Thu, 12 Jan 2012 14:38:57 +0100 Subject: mtd: ST SPEAr: Add SMI driver for serial NOR flash SPEAr platforms (spear3xx/spear6xx/spear13xx) provide SMI (Serial Memory Interface) controller to access serial NOR flash. SMI provides a simple interface for SPI/serial NOR flashes and has certain inbuilt commands and features to support these flashes easily. It also makes it possible to map an address range in order to directly access (read/write) the SNOR over address bus. This patch intends to provide serial nor driver support for spear platforms which are accessed through SMI. Signed-off-by: Shiraz Hashim Signed-off-by: Viresh Kumar Signed-off-by: Stefan Roese Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/spear_smi.h | 60 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 include/linux/mtd/spear_smi.h (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/spear_smi.h b/include/linux/mtd/spear_smi.h new file mode 100644 index 000000000000..4e26b4e38da3 --- /dev/null +++ b/include/linux/mtd/spear_smi.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2010 ST Microelectronics + * Shiraz Hashim + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MTD_SPEAR_SMI_H +#define __MTD_SPEAR_SMI_H + +#include +#include +#include +#include + +/* macro to define partitions for flash devices */ +#define DEFINE_PARTS(n, of, s) \ +{ \ + .name = n, \ + .offset = of, \ + .size = s, \ +} + +/** + * struct spear_smi_flash_info - platform structure for passing flash + * information + * + * name: name of the serial nor flash for identification + * mem_base: the memory base on which the flash is mapped + * size: size of the flash in bytes + * partitions: parition details + * nr_partitions: number of partitions + * fast_mode: whether flash supports fast mode + */ + +struct spear_smi_flash_info { + char *name; + unsigned long mem_base; + unsigned long size; + struct mtd_partition *partitions; + int nr_partitions; + u8 fast_mode; +}; + +/** + * struct spear_smi_plat_data - platform structure for configuring smi + * + * clk_rate: clk rate at which SMI must operate + * num_flashes: number of flashes present on board + * board_flash_info: specific details of each flash present on board + */ +struct spear_smi_plat_data { + unsigned long clk_rate; + int num_flashes; + struct spear_smi_flash_info *board_flash_info; +}; + +#endif /* __MTD_SPEAR_SMI_H */ -- cgit v1.2.3 From 3c3c10bba1e4ccb75b41442e45c1a072f6cded19 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 30 Jan 2012 14:58:32 +0200 Subject: mtd: add leading underscore to all mtd functions This patch renames all MTD functions by adding a "_" prefix: mtd->erase -> mtd->_erase mtd->read_oob -> mtd->_read_oob ... The reason is that we are re-working the MTD API and from now on it is an error to use MTD function pointers directly - we have a corresponding API call for every pointer. By adding a leading "_" we achieve the following: 1. Make sure we convert every direct pointer users 2. A leading "_" suggests that this interface is internal and it becomes less likely that people will use them directly 3. Make sure all the out-of-tree modules stop compiling and the owners spot the big API change and amend them. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/mtd.h | 168 ++++++++++++++++++++++++------------------------ 1 file changed, 84 insertions(+), 84 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index d43dc25af82e..e2e545616b2a 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -174,52 +174,52 @@ struct mtd_info { * Do not call via these pointers, use corresponding mtd_*() * wrappers instead. */ - int (*erase) (struct mtd_info *mtd, struct erase_info *instr); - int (*point) (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, void **virt, resource_size_t *phys); - void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len); - unsigned long (*get_unmapped_area) (struct mtd_info *mtd, - unsigned long len, - unsigned long offset, - unsigned long flags); - int (*read) (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf); - int (*write) (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf); - int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf); - int (*read_oob) (struct mtd_info *mtd, loff_t from, - struct mtd_oob_ops *ops); - int (*write_oob) (struct mtd_info *mtd, loff_t to, + int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); + int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, void **virt, resource_size_t *phys); + void (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); + unsigned long (*_get_unmapped_area) (struct mtd_info *mtd, + unsigned long len, + unsigned long offset, + unsigned long flags); + int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); + int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); + int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); + int (*_read_oob) (struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); - int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, - size_t len); - int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, - size_t len, size_t *retlen, u_char *buf); - int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, - size_t len); - int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, - size_t len, size_t *retlen, u_char *buf); - int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, u_char *buf); - int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, - size_t len); - int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, + int (*_write_oob) (struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops); + int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, + size_t len); + int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf); + int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, + size_t len); + int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf); + int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, + size_t len, size_t *retlen, u_char *buf); + int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, + size_t len); + int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); - void (*sync) (struct mtd_info *mtd); - int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); - int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); - int (*is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); - int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); - int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); - int (*suspend) (struct mtd_info *mtd); - void (*resume) (struct mtd_info *mtd); + void (*_sync) (struct mtd_info *mtd); + int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); + int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); + int (*_suspend) (struct mtd_info *mtd); + void (*_resume) (struct mtd_info *mtd); /* * If the driver is something smart, like UBI, it may need to maintain * its own reference counting. The below functions are only for driver. */ - int (*get_device) (struct mtd_info *mtd); - void (*put_device) (struct mtd_info *mtd); + int (*_get_device) (struct mtd_info *mtd); + void (*_put_device) (struct mtd_info *mtd); /* Backing device capabilities for this device * - provides mmap capabilities @@ -249,7 +249,7 @@ struct mtd_info { */ static inline int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) { - return mtd->erase(mtd, instr); + return mtd->_erase(mtd, instr); } /* @@ -259,15 +259,15 @@ static inline int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, void **virt, resource_size_t *phys) { *retlen = 0; - if (!mtd->point) + if (!mtd->_point) return -EOPNOTSUPP; - return mtd->point(mtd, from, len, retlen, virt, phys); + return mtd->_point(mtd, from, len, retlen, virt, phys); } /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ static inline void mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len) { - return mtd->unpoint(mtd, from, len); + return mtd->_unpoint(mtd, from, len); } /* @@ -280,24 +280,24 @@ static inline unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long offset, unsigned long flags) { - if (!mtd->get_unmapped_area) + if (!mtd->_get_unmapped_area) return -EOPNOTSUPP; - return mtd->get_unmapped_area(mtd, len, offset, flags); + return mtd->_get_unmapped_area(mtd, len, offset, flags); } static inline int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - return mtd->read(mtd, from, len, retlen, buf); + return mtd->_read(mtd, from, len, retlen, buf); } static inline int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { *retlen = 0; - if (!mtd->write) + if (!mtd->_write) return -EROFS; - return mtd->write(mtd, to, len, retlen, buf); + return mtd->_write(mtd, to, len, retlen, buf); } /* @@ -311,27 +311,27 @@ static inline int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { *retlen = 0; - if (!mtd->panic_write) + if (!mtd->_panic_write) return -EOPNOTSUPP; - return mtd->panic_write(mtd, to, len, retlen, buf); + return mtd->_panic_write(mtd, to, len, retlen, buf); } static inline int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { ops->retlen = ops->oobretlen = 0; - if (!mtd->read_oob) + if (!mtd->_read_oob) return -EOPNOTSUPP; - return mtd->read_oob(mtd, from, ops); + return mtd->_read_oob(mtd, from, ops); } static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { ops->retlen = ops->oobretlen = 0; - if (!mtd->write_oob) + if (!mtd->_write_oob) return -EOPNOTSUPP; - return mtd->write_oob(mtd, to, ops); + return mtd->_write_oob(mtd, to, ops); } /* @@ -342,9 +342,9 @@ static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, static inline int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, size_t len) { - if (!mtd->get_fact_prot_info) + if (!mtd->_get_fact_prot_info) return -EOPNOTSUPP; - return mtd->get_fact_prot_info(mtd, buf, len); + return mtd->_get_fact_prot_info(mtd, buf, len); } static inline int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, @@ -352,18 +352,18 @@ static inline int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, u_char *buf) { *retlen = 0; - if (!mtd->read_fact_prot_reg) + if (!mtd->_read_fact_prot_reg) return -EOPNOTSUPP; - return mtd->read_fact_prot_reg(mtd, from, len, retlen, buf); + return mtd->_read_fact_prot_reg(mtd, from, len, retlen, buf); } static inline int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, size_t len) { - if (!mtd->get_user_prot_info) + if (!mtd->_get_user_prot_info) return -EOPNOTSUPP; - return mtd->get_user_prot_info(mtd, buf, len); + return mtd->_get_user_prot_info(mtd, buf, len); } static inline int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, @@ -371,9 +371,9 @@ static inline int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, u_char *buf) { *retlen = 0; - if (!mtd->read_user_prot_reg) + if (!mtd->_read_user_prot_reg) return -EOPNOTSUPP; - return mtd->read_user_prot_reg(mtd, from, len, retlen, buf); + return mtd->_read_user_prot_reg(mtd, from, len, retlen, buf); } static inline int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, @@ -381,17 +381,17 @@ static inline int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, u_char *buf) { *retlen = 0; - if (!mtd->write_user_prot_reg) + if (!mtd->_write_user_prot_reg) return -EOPNOTSUPP; - return mtd->write_user_prot_reg(mtd, to, len, retlen, buf); + return mtd->_write_user_prot_reg(mtd, to, len, retlen, buf); } static inline int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len) { - if (!mtd->lock_user_prot_reg) + if (!mtd->_lock_user_prot_reg) return -EOPNOTSUPP; - return mtd->lock_user_prot_reg(mtd, from, len); + return mtd->_lock_user_prot_reg(mtd, from, len); } int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, @@ -399,55 +399,55 @@ int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, static inline void mtd_sync(struct mtd_info *mtd) { - if (mtd->sync) - mtd->sync(mtd); + if (mtd->_sync) + mtd->_sync(mtd); } /* Chip-supported device locking */ static inline int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - if (!mtd->lock) + if (!mtd->_lock) return -EOPNOTSUPP; - return mtd->lock(mtd, ofs, len); + return mtd->_lock(mtd, ofs, len); } static inline int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - if (!mtd->unlock) + if (!mtd->_unlock) return -EOPNOTSUPP; - return mtd->unlock(mtd, ofs, len); + return mtd->_unlock(mtd, ofs, len); } static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - if (!mtd->is_locked) + if (!mtd->_is_locked) return -EOPNOTSUPP; - return mtd->is_locked(mtd, ofs, len); + return mtd->_is_locked(mtd, ofs, len); } static inline int mtd_suspend(struct mtd_info *mtd) { - return mtd->suspend ? mtd->suspend(mtd) : 0; + return mtd->_suspend ? mtd->_suspend(mtd) : 0; } static inline void mtd_resume(struct mtd_info *mtd) { - if (mtd->resume) - mtd->resume(mtd); + if (mtd->_resume) + mtd->_resume(mtd); } static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) { - if (!mtd->block_isbad) + if (!mtd->_block_isbad) return 0; - return mtd->block_isbad(mtd, ofs); + return mtd->_block_isbad(mtd, ofs); } static inline int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) { - if (!mtd->block_markbad) + if (!mtd->_block_markbad) return -EOPNOTSUPP; - return mtd->block_markbad(mtd, ofs); + return mtd->_block_markbad(mtd, ofs); } static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) @@ -482,12 +482,12 @@ static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd) static inline int mtd_has_oob(const struct mtd_info *mtd) { - return mtd->read_oob && mtd->write_oob; + return mtd->_read_oob && mtd->_write_oob; } static inline int mtd_can_have_bb(const struct mtd_info *mtd) { - return !!mtd->block_isbad; + return !!mtd->_block_isbad; } /* Kernel-side ioctl definitions */ -- cgit v1.2.3 From e2414f4c20bd4dc62186fbfd7bdec50bce6d2ead Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 6 Feb 2012 13:44:00 -0800 Subject: mtd: nand: write BBM to OOB even with flash-based BBT Currently, the flash-based BBT implementation writes bad block data only to its flash-based table and not to the OOB marker area. Then, as new bad blocks are marked over time, the OOB markers become incomplete and the flash-based table becomes the only source of current bad block information. This becomes an obvious problem when, for example: * bootloader cannot read the flash-based BBT format * BBT is corrupted and the flash must be rescanned for bad blocks; we want to remember bad blocks that were marked from Linux So to keep the bad block markers in sync with the flash-based BBT, this patch changes the default so that we write bad block markers to the proper OOB area on each block in addition to flash-based BBT. Comments are updated, expanded, and/or relocated as necessary. The new flash-based BBT procedure for marking bad blocks: (1) erase the affected block, to allow OOB marker to be written cleanly (2) update in-memory BBT (3) write bad block marker to OOB area of affected block (4) update flash-based BBT Note that we retain the first error encountered in (3) or (4), finish the procedures, and dump the error in the end. This should handle power cuts gracefully enough. (1) and (2) are mostly harmless (note that (1) will not erase an already-recognized bad block). The OOB and BBT may be "out of sync" if we experience power loss bewteen (3) and (4), but we can reasonably expect that on next boot, subsequent I/O operations will discover that the block should be marked bad again, thus re-syncing the OOB and BBT. Note that this is a change from the previous default flash-based BBT behavior. If your system cannot support writing bad block markers to OOB, use the new NAND_BBT_NO_OOB_BBM option (in combination with NAND_BBT_USE_FLASH and NAND_BBT_NO_OOB). Signed-off-by: Brian Norris Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/bbm.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index c4eec228eef9..650ef352f045 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h @@ -112,6 +112,11 @@ struct nand_bbt_descr { #define NAND_BBT_USE_FLASH 0x00020000 /* Do not store flash based bad block table in OOB area; store it in-band */ #define NAND_BBT_NO_OOB 0x00040000 +/* + * Do not write new bad block markers to OOB; useful, e.g., when ECC covers + * entire spare area. Must be used with NAND_BBT_USE_FLASH. + */ +#define NAND_BBT_NO_OOB_BBM 0x00080000 /* * Flag set by nand_create_default_bbt_descr(), marking that the nand_bbt_descr -- cgit v1.2.3 From 5e4e6e3fdf48c1b012e2b6e80ed1d7e99d4fa6d1 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 3 Feb 2012 13:20:43 +0200 Subject: mtd: return error code from mtd_unpoint The 'mtd_unpoint()' API function should be able to return an error code because it may fail if you specify incorrect offset. This patch changes this MTD API function and amends all the drivers correspondingly. Also return '-EOPNOTSUPP' from 'mtd_unpoint()' when the '->unpoint()' method is undefined. We do not really need this currently, but this just makes sense to be consistent with 'mtd_point()'. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/mtd.h | 6 ++++-- include/linux/mtd/pmc551.h | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index e2e545616b2a..8c243117c087 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -177,7 +177,7 @@ struct mtd_info { int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, void **virt, resource_size_t *phys); - void (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); + int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); unsigned long (*_get_unmapped_area) (struct mtd_info *mtd, unsigned long len, unsigned long offset, @@ -265,8 +265,10 @@ static inline int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, } /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ -static inline void mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len) +static inline int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len) { + if (!mtd->_point) + return -EOPNOTSUPP; return mtd->_unpoint(mtd, from, len); } diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h index 27ad40aed19f..da8b98d1b330 100644 --- a/include/linux/mtd/pmc551.h +++ b/include/linux/mtd/pmc551.h @@ -34,7 +34,6 @@ struct mypriv { * Function Prototypes */ static int pmc551_erase(struct mtd_info *, struct erase_info *); -static void pmc551_unpoint(struct mtd_info *, loff_t, size_t); static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, void **virt, resource_size_t *phys); static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); -- cgit v1.2.3 From 8273a0c911d8e068297ef70aa7241ee78db4c712 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 3 Feb 2012 14:34:14 +0200 Subject: mtd: add offset and length checks to the API function Add verification of the offset and length to MTD API functions and verify that MTD device offset and length are within MTD device size. The modified API functions are: 'mtd_erase()' 'mtd_point()' 'mtd_unpoint()' 'mtd_get_unmapped_area()' 'mtd_read()' 'mtd_write()' 'mtd_panic_write()' 'mtd_lock()' 'mtd_unlock()' 'mtd_is_locked()' 'mtd_block_isbad()' 'mtd_block_markbad()' This patch also uninlines these functions and exports in mtdcore.c because they are not performance-critical and do not have to be inlined. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/mtd.h | 129 +++++++----------------------------------------- 1 file changed, 17 insertions(+), 112 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 8c243117c087..317a80c4d54c 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -240,83 +240,18 @@ struct mtd_info { int usecount; }; -/* - * Erase is an asynchronous operation. Device drivers are supposed - * to call instr->callback() whenever the operation completes, even - * if it completes with a failure. - * Callers are supposed to pass a callback function and wait for it - * to be called before writing to the block. - */ -static inline int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - return mtd->_erase(mtd, instr); -} - -/* - * This stuff for eXecute-In-Place. phys is optional and may be set to NULL. - */ -static inline int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, void **virt, resource_size_t *phys) -{ - *retlen = 0; - if (!mtd->_point) - return -EOPNOTSUPP; - return mtd->_point(mtd, from, len, retlen, virt, phys); -} - -/* We probably shouldn't allow XIP if the unpoint isn't a NULL */ -static inline int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len) -{ - if (!mtd->_point) - return -EOPNOTSUPP; - return mtd->_unpoint(mtd, from, len); -} - -/* - * Allow NOMMU mmap() to directly map the device (if not NULL) - * - return the address to which the offset maps - * - return -ENOSYS to indicate refusal to do the mapping - */ -static inline unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, - unsigned long len, - unsigned long offset, - unsigned long flags) -{ - if (!mtd->_get_unmapped_area) - return -EOPNOTSUPP; - return mtd->_get_unmapped_area(mtd, len, offset, flags); -} - -static inline int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - return mtd->_read(mtd, from, len, retlen, buf); -} - -static inline int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - *retlen = 0; - if (!mtd->_write) - return -EROFS; - return mtd->_write(mtd, to, len, retlen, buf); -} - -/* - * In blackbox flight recorder like scenarios we want to make successful writes - * in interrupt context. panic_write() is only intended to be called when its - * known the kernel is about to panic and we need the write to succeed. Since - * the kernel is not going to be running for much longer, this function can - * break locks and delay to ensure the write succeeds (but not sleep). - */ -static inline int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - *retlen = 0; - if (!mtd->_panic_write) - return -EOPNOTSUPP; - return mtd->_panic_write(mtd, to, len, retlen, buf); -} +int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); +int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, + void **virt, resource_size_t *phys); +int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len); +unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, + unsigned long offset, unsigned long flags); +int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, + u_char *buf); +int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, + const u_char *buf); +int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, + const u_char *buf); static inline int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) @@ -405,27 +340,11 @@ static inline void mtd_sync(struct mtd_info *mtd) mtd->_sync(mtd); } -/* Chip-supported device locking */ -static inline int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -{ - if (!mtd->_lock) - return -EOPNOTSUPP; - return mtd->_lock(mtd, ofs, len); -} - -static inline int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -{ - if (!mtd->_unlock) - return -EOPNOTSUPP; - return mtd->_unlock(mtd, ofs, len); -} - -static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) -{ - if (!mtd->_is_locked) - return -EOPNOTSUPP; - return mtd->_is_locked(mtd, ofs, len); -} +int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); +int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); static inline int mtd_suspend(struct mtd_info *mtd) { @@ -438,20 +357,6 @@ static inline void mtd_resume(struct mtd_info *mtd) mtd->_resume(mtd); } -static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) -{ - if (!mtd->_block_isbad) - return 0; - return mtd->_block_isbad(mtd, ofs); -} - -static inline int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) -{ - if (!mtd->_block_markbad) - return -EOPNOTSUPP; - return mtd->_block_markbad(mtd, ofs); -} - static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) { if (mtd->erasesize_shift) -- cgit v1.2.3 From 664addc248d2fed68d013d26ff2fc796d7134259 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 3 Feb 2012 18:13:23 +0200 Subject: mtd: remove R/O checking duplication Many drivers check whether the partition is R/O and return -EROFS if yes. Let's stop having duplicated checks and move them to the API functions instead. And again a bit of noise - deleted few too sparse newlines, sorry. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/mtd.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 317a80c4d54c..fa20a8f0463a 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -268,6 +268,8 @@ static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, ops->retlen = ops->oobretlen = 0; if (!mtd->_write_oob) return -EOPNOTSUPP; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; return mtd->_write_oob(mtd, to, ops); } -- cgit v1.2.3 From c3faac4a74c2126e2b68f39d6e8791e88b5f7dbe Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 6 Feb 2012 13:44:27 +0200 Subject: mtd: remove junk pmc551.h This header is tiny and contains only pmc551-private stuff, so it should not live in 'include/linux' - let's just merge it with pmc551.c. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/pmc551.h | 77 ---------------------------------------------- 1 file changed, 77 deletions(-) delete mode 100644 include/linux/mtd/pmc551.h (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h deleted file mode 100644 index da8b98d1b330..000000000000 --- a/include/linux/mtd/pmc551.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * PMC551 PCI Mezzanine Ram Device - * - * Author: - * Mark Ferrell - * Copyright 1999,2000 Nortel Networks - * - * License: - * As part of this driver was derrived from the slram.c driver it falls - * under the same license, which is GNU General Public License v2 - */ - -#ifndef __MTD_PMC551_H__ -#define __MTD_PMC551_H__ - -#include - -#define PMC551_VERSION \ - "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n" - -/* - * Our personal and private information - */ -struct mypriv { - struct pci_dev *dev; - u_char *start; - u32 base_map0; - u32 curr_map0; - u32 asize; - struct mtd_info *nextpmc551; -}; - -/* - * Function Prototypes - */ -static int pmc551_erase(struct mtd_info *, struct erase_info *); -static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, void **virt, resource_size_t *phys); -static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); -static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); - - -/* - * Define the PCI ID's if the kernel doesn't define them for us - */ -#ifndef PCI_VENDOR_ID_V3_SEMI -#define PCI_VENDOR_ID_V3_SEMI 0x11b0 -#endif - -#ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC -#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200 -#endif - - -#define PMC551_PCI_MEM_MAP0 0x50 -#define PMC551_PCI_MEM_MAP1 0x54 -#define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000 -#define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0 -#define PMC551_PCI_MEM_MAP_REG_EN 0x00000002 -#define PMC551_PCI_MEM_MAP_ENABLE 0x00000001 - -#define PMC551_SDRAM_MA 0x60 -#define PMC551_SDRAM_CMD 0x62 -#define PMC551_DRAM_CFG 0x64 -#define PMC551_SYS_CTRL_REG 0x78 - -#define PMC551_DRAM_BLK0 0x68 -#define PMC551_DRAM_BLK1 0x6c -#define PMC551_DRAM_BLK2 0x70 -#define PMC551_DRAM_BLK3 0x74 -#define PMC551_DRAM_BLK_GET_SIZE(x) (524288<<((x>>4)&0x0f)) -#define PMC551_DRAM_BLK_SET_COL_MUX(x,v) (((x) & ~0x00007000) | (((v) & 0x7) << 12)) -#define PMC551_DRAM_BLK_SET_ROW_MUX(x,v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8)) - - -#endif /* __MTD_PMC551_H__ */ - -- cgit v1.2.3 From de3cac9357b5aa9f9f02520e5f2567b06f3f75a7 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 8 Feb 2012 16:37:14 +0200 Subject: mtd: check for zero length in OTP functions This patch changes all the OTP functions like 'mtd_get_fact_prot_info()' and makes them return zero immediately if the input 'len' parameter is 0. This is not really needed currently, but most of the other functions do this, and it is just consistent to do the same in the OTP functions. This patch also moves the OTP functions from the header file to mtdcore.c because they become a bit too big for being inlined. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/mtd.h | 70 ++++++++----------------------------------------- 1 file changed, 11 insertions(+), 59 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index fa20a8f0463a..726c2d1b2589 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -273,65 +273,17 @@ static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, return mtd->_write_oob(mtd, to, ops); } -/* - * Method to access the protection register area, present in some flash - * devices. The user data is one time programmable but the factory data is read - * only. - */ -static inline int mtd_get_fact_prot_info(struct mtd_info *mtd, - struct otp_info *buf, size_t len) -{ - if (!mtd->_get_fact_prot_info) - return -EOPNOTSUPP; - return mtd->_get_fact_prot_info(mtd, buf, len); -} - -static inline int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, - size_t len, size_t *retlen, - u_char *buf) -{ - *retlen = 0; - if (!mtd->_read_fact_prot_reg) - return -EOPNOTSUPP; - return mtd->_read_fact_prot_reg(mtd, from, len, retlen, buf); -} - -static inline int mtd_get_user_prot_info(struct mtd_info *mtd, - struct otp_info *buf, - size_t len) -{ - if (!mtd->_get_user_prot_info) - return -EOPNOTSUPP; - return mtd->_get_user_prot_info(mtd, buf, len); -} - -static inline int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, - size_t len, size_t *retlen, - u_char *buf) -{ - *retlen = 0; - if (!mtd->_read_user_prot_reg) - return -EOPNOTSUPP; - return mtd->_read_user_prot_reg(mtd, from, len, retlen, buf); -} - -static inline int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, - size_t len, size_t *retlen, - u_char *buf) -{ - *retlen = 0; - if (!mtd->_write_user_prot_reg) - return -EOPNOTSUPP; - return mtd->_write_user_prot_reg(mtd, to, len, retlen, buf); -} - -static inline int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, - size_t len) -{ - if (!mtd->_lock_user_prot_reg) - return -EOPNOTSUPP; - return mtd->_lock_user_prot_reg(mtd, from, len); -} +int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, + size_t len); +int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, + size_t len); +int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, u_char *buf); +int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); -- cgit v1.2.3 From b6a5588b27f21d74ae35709b56e969d536f1eed0 Mon Sep 17 00:00:00 2001 From: Bastian Hecht Date: Thu, 1 Mar 2012 10:48:35 +0100 Subject: mtd: sh_flctl: Expand FLCMNCR register bit field Add support for a new hardware generation. The meaning of some bits of the FLCMNCR register changed, so some new defines are added parallel to the existing ones to keep backward compatibility. The defines allow to choose an appropriate clocking scheme. Signed-off-by: Bastian Hecht Acked-by: Laurent Pinchart Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/sh_flctl.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h index 9cf4c4c79555..b66940593c82 100644 --- a/include/linux/mtd/sh_flctl.h +++ b/include/linux/mtd/sh_flctl.h @@ -67,6 +67,30 @@ #define CE0_ENABLE (0x1 << 3) /* Chip Enable 0 */ #define TYPESEL_SET (0x1 << 0) +/* + * Clock settings using the PULSEx registers from FLCMNCR + * + * Some hardware uses bits called PULSEx instead of FCKSEL_E and QTSEL_E + * to control the clock divider used between the High-Speed Peripheral Clock + * and the FLCTL internal clock. If so, use CLK_8_BIT_xxx for connecting 8 bit + * and CLK_16_BIT_xxx for connecting 16 bit bus bandwith NAND chips. For the 16 + * bit version the divider is seperate for the pulse width of high and low + * signals. + */ +#define PULSE3 (0x1 << 27) +#define PULSE2 (0x1 << 17) +#define PULSE1 (0x1 << 15) +#define PULSE0 (0x1 << 9) +#define CLK_8B_0_5 PULSE1 +#define CLK_8B_1 0x0 +#define CLK_8B_1_5 (PULSE1 | PULSE2) +#define CLK_8B_2 PULSE0 +#define CLK_8B_3 (PULSE0 | PULSE1 | PULSE2) +#define CLK_8B_4 (PULSE0 | PULSE2) +#define CLK_16B_6L_2H PULSE0 +#define CLK_16B_9L_3H (PULSE0 | PULSE1 | PULSE2) +#define CLK_16B_12L_4H (PULSE0 | PULSE2) + /* FLCMDCR control bits */ #define ADRCNT2_E (0x1 << 31) /* 5byte address enable */ #define ADRMD_E (0x1 << 26) /* Sector address access */ -- cgit v1.2.3 From 0b3f0d12eff1ed23496fcf4cf468e1d317516e53 Mon Sep 17 00:00:00 2001 From: Bastian Hecht Date: Thu, 1 Mar 2012 10:48:39 +0100 Subject: mtd: sh_flctl: Use cached register value for FLCMNCR Instead of reading out the register, use a cached value. This will make way for a proper runtime power management implementation. Signed-off-by: Bastian Hecht Acked-by: Laurent Pinchart Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/sh_flctl.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h index b66940593c82..c7082820703b 100644 --- a/include/linux/mtd/sh_flctl.h +++ b/include/linux/mtd/sh_flctl.h @@ -132,6 +132,7 @@ struct sh_flctl { int erase1_page_addr; /* page_addr in ERASE1 cmd */ uint32_t erase_ADRCNT; /* bits of FLCMDCR in ERASE1 cmd */ uint32_t rw_ADRCNT; /* bits of FLCMDCR in READ WRITE cmd */ + uint32_t flcmncr_base; /* base value of FLCMNCR */ int hwecc_cant_correct[4]; -- cgit v1.2.3 From 3f2e924b26989bbe1ad600a83fdc72a3056104d1 Mon Sep 17 00:00:00 2001 From: Bastian Hecht Date: Thu, 1 Mar 2012 10:48:40 +0100 Subject: mtd: sh_flctl: Add FLHOLDCR register Add a register used in new FLCTL hardware and a feature flag for it. Signed-off-by: Bastian Hecht Acked-by: Laurent Pinchart Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/sh_flctl.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h index c7082820703b..8bcf299cb9bf 100644 --- a/include/linux/mtd/sh_flctl.h +++ b/include/linux/mtd/sh_flctl.h @@ -38,6 +38,7 @@ #define FLDTFIFO(f) (f->reg + 0x24) #define FLECFIFO(f) (f->reg + 0x28) #define FLTRCR(f) (f->reg + 0x2C) +#define FLHOLDCR(f) (f->reg + 0x38) #define FL4ECCRESULT0(f) (f->reg + 0x80) #define FL4ECCRESULT1(f) (f->reg + 0x84) #define FL4ECCRESULT2(f) (f->reg + 0x88) @@ -109,6 +110,15 @@ #define TRSTRT (0x1 << 0) /* translation start */ #define TREND (0x1 << 1) /* translation end */ +/* + * FLHOLDCR control bits + * + * HOLDEN: Bus Occupancy Enable (inverted) + * Enable this bit when the external bus might be used in between transfers. + * If not set and the bus gets used by other modules, a deadlock occurs. + */ +#define HOLDEN (0x1 << 0) + /* FL4ECCCR control bits */ #define _4ECCFA (0x1 << 2) /* 4 symbols correct fault */ #define _4ECCEND (0x1 << 1) /* 4 symbols end */ @@ -138,6 +148,7 @@ struct sh_flctl { unsigned page_size:1; /* NAND page size (0 = 512, 1 = 2048) */ unsigned hwecc:1; /* Hardware ECC (0 = disabled, 1 = enabled) */ + unsigned holden:1; /* Hardware has FLHOLDCR and HOLDEN is set */ }; struct sh_flctl_platform_data { @@ -146,6 +157,7 @@ struct sh_flctl_platform_data { unsigned long flcmncr_val; unsigned has_hwecc:1; + unsigned use_holden:1; }; static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo) -- cgit v1.2.3 From b2acc92e144336dd29e30dc5d26439355be750b6 Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Wed, 7 Mar 2012 17:00:51 +0530 Subject: mtd: fsmc: use ALE and CLE offsets from platform data ALE and CLE offsets can be different on different devices. Let devices pass these offsets to the fsmc driver through platform data. Signed-off-by: Shiraz Hashim Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/fsmc.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index 6987995ad3cf..2cd655f06e05 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h @@ -151,6 +151,11 @@ struct fsmc_nand_platform_data { unsigned int options; unsigned int width; unsigned int bank; + + /* CLE, ALE offsets */ + unsigned long cle_off; + unsigned long ale_off; + void (*select_bank)(uint32_t bank, uint32_t busw); }; -- cgit v1.2.3 From 02bfc4ebbd2532440fadd78076f3a51e0ae89f7f Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Wed, 7 Mar 2012 17:00:52 +0530 Subject: mtd: fsmc: Move ALE, CLE defines to their respective platform Address Latch Enable (ALE) and Command Latch Enable (CLE) defines are platform specific and were wrongly put in driver specific fsmc.h file. Move such defines to their respective platform. Also instead of relying on fsmc driver, pass ALE, CLE offsets explicitly from individual platform. Signed-off-by: Shiraz Hashim Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/fsmc.h | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index 2cd655f06e05..e877325d9c51 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h @@ -26,19 +26,6 @@ #define FSMC_NAND_BW8 1 #define FSMC_NAND_BW16 2 -/* - * The placement of the Command Latch Enable (CLE) and - * Address Latch Enable (ALE) is twisted around in the - * SPEAR310 implementation. - */ -#if defined(CONFIG_MACH_SPEAR310) -#define PLAT_NAND_CLE (1 << 17) -#define PLAT_NAND_ALE (1 << 16) -#else -#define PLAT_NAND_CLE (1 << 16) -#define PLAT_NAND_ALE (1 << 17) -#endif - #define FSMC_MAX_NOR_BANKS 4 #define FSMC_MAX_NAND_BANKS 4 -- cgit v1.2.3 From cfe781946dac7f5ff42e23cd7054c75e7201fbdc Mon Sep 17 00:00:00 2001 From: Bastian Hecht Date: Sun, 18 Mar 2012 15:13:20 +0100 Subject: mtd: sh_flctl: Add power management with QoS request Adds power management code with fine granularity. Every flash control command is enclosed by runtime_put()/get()s. To make sure that no overhead is generated by too frequent power state switches, a quality of service request is issued. Signed-off-by: Bastian Hecht Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/sh_flctl.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h index 8bcf299cb9bf..a38e1fa8af01 100644 --- a/include/linux/mtd/sh_flctl.h +++ b/include/linux/mtd/sh_flctl.h @@ -23,6 +23,7 @@ #include #include #include +#include /* FLCTL registers */ #define FLCMNCR(f) (f->reg + 0x0) @@ -131,6 +132,7 @@ struct sh_flctl { struct mtd_info mtd; struct nand_chip chip; struct platform_device *pdev; + struct dev_pm_qos_request pm_qos; void __iomem *reg; uint8_t done_buff[2048 + 64]; /* max size 2048 + 64 */ @@ -149,6 +151,7 @@ struct sh_flctl { unsigned page_size:1; /* NAND page size (0 = 512, 1 = 2048) */ unsigned hwecc:1; /* Hardware ECC (0 = disabled, 1 = enabled) */ unsigned holden:1; /* Hardware has FLHOLDCR and HOLDEN is set */ + unsigned qos_request:1; /* QoS request to prevent deep power shutdown */ }; struct sh_flctl_platform_data { -- cgit v1.2.3 From 1d0b95b0834087ba3653f69c24483d63a26d51a7 Mon Sep 17 00:00:00 2001 From: Mike Dunn Date: Sun, 11 Mar 2012 14:21:10 -0700 Subject: mtd: add ecc_strength fields to mtd structs This adds 'ecc_strength' to struct mtd_info. This stores the maximum number of bit errors that can be corrected in one writesize region. For consistency with the nand code, 'strength' is similiarly added to struct nand_ecc_ctrl. This stores the maximum number of bit errors that can be corrected in one ecc step. Signed-off-by: Mike Dunn Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/mtd.h | 3 +++ include/linux/mtd/nand.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 726c2d1b2589..cf5ea8cdcf8e 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -164,6 +164,9 @@ struct mtd_info { /* ECC layout structure pointer - read only! */ struct nand_ecclayout *ecclayout; + /* max number of correctible bit errors per writesize */ + unsigned int ecc_strength; + /* Data for variable erase regions. If numeraseregions is zero, * it means that the whole device has erasesize as given above. */ diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 609868f3db42..1482340d3d9f 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -324,6 +324,7 @@ struct nand_hw_control { * @steps: number of ECC steps per page * @size: data bytes per ECC step * @bytes: ECC bytes per step + * @strength: max number of correctible bits per ECC step * @total: total number of ECC bytes per page * @prepad: padding information for syndrome based ECC generators * @postpad: padding information for syndrome based ECC generators @@ -351,6 +352,7 @@ struct nand_ecc_ctrl { int size; int bytes; int total; + int strength; int prepad; int postpad; struct nand_ecclayout *layout; -- cgit v1.2.3 From e2f6bce8d94d2c82d4f7ae9d94743963a3b10136 Mon Sep 17 00:00:00 2001 From: Vipin Kumar Date: Wed, 14 Mar 2012 11:47:14 +0530 Subject: mtd: nand/fsmc: Modify fsmc driver to accept nand timing parameters via platform FSMC controllers provide registers to program the required timing values for attached NAND device. The timing values used until now are relaxed and should work for all devices. Although, for read/write performance improvements, the fsmc nand driver should accept nand timings as a platform data and program the timing parameters into fsmc registers accordingly. This patch implements this modification. Additionally, it programs the default timing parameters if these are not passed via platform data. Signed-off-by: Vipin Kumar Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/fsmc.h | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index e877325d9c51..c4ac07a19691 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h @@ -90,17 +90,29 @@ struct fsmc_regs { #define FSMC_ECCEN (1 << 6) #define FSMC_ECCPLEN_512 (0 << 7) #define FSMC_ECCPLEN_256 (1 << 7) -#define FSMC_TCLR_1 (1 << 9) -#define FSMC_TAR_1 (1 << 13) +#define FSMC_TCLR_1 (1) +#define FSMC_TCLR_SHIFT (9) +#define FSMC_TCLR_MASK (0xF) +#define FSMC_TAR_1 (1) +#define FSMC_TAR_SHIFT (13) +#define FSMC_TAR_MASK (0xF) /* sts register definitions */ #define FSMC_CODE_RDY (1 << 15) /* comm register definitions */ -#define FSMC_TSET_0 (0 << 0) -#define FSMC_TWAIT_6 (6 << 8) -#define FSMC_THOLD_4 (4 << 16) -#define FSMC_THIZ_1 (1 << 24) +#define FSMC_TSET_0 0 +#define FSMC_TSET_SHIFT 0 +#define FSMC_TSET_MASK 0xFF +#define FSMC_TWAIT_6 6 +#define FSMC_TWAIT_SHIFT 8 +#define FSMC_TWAIT_MASK 0xFF +#define FSMC_THOLD_4 4 +#define FSMC_THOLD_SHIFT 16 +#define FSMC_THOLD_MASK 0xFF +#define FSMC_THIZ_1 1 +#define FSMC_THIZ_SHIFT 24 +#define FSMC_THIZ_MASK 0xFF /* * There are 13 bytes of ecc for every 512 byte block in FSMC version 8 @@ -120,6 +132,15 @@ struct fsmc_eccplace { struct fsmc_nand_eccplace eccplace[MAX_ECCPLACE_ENTRIES]; }; +struct fsmc_nand_timings { + uint8_t tclr; + uint8_t tar; + uint8_t thiz; + uint8_t thold; + uint8_t twait; + uint8_t tset; +}; + /** * fsmc_nand_platform_data - platform specific NAND controller config * @partitions: partition table for the platform, use a default fallback @@ -133,6 +154,7 @@ struct fsmc_eccplace { * this may be set to NULL */ struct fsmc_nand_platform_data { + struct fsmc_nand_timings *nand_timings; struct mtd_partition *partitions; unsigned int nr_partitions; unsigned int options; -- cgit v1.2.3 From 604e75444fa82cfdcba339e3bd4da1dfd6947539 Mon Sep 17 00:00:00 2001 From: Vipin Kumar Date: Wed, 14 Mar 2012 11:47:17 +0530 Subject: mtd: nand/fsmc: Access the NAND device word by word whenever possible The default way of accessing nand device is using the nand width. This means that 8bit devices are using u8 * and 16bit devices are accessed using u16 *. This results in a non-optimal performance since the FSMC is designed to translate the normal word accesses into device width based accesses. This patch implements read_buf and write_buf callbacks using word by word accesses. Signed-off-by: Vipin Kumar Reviewed-by: Viresh Kumar Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/fsmc.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index c4ac07a19691..1edd2b3ac38e 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h @@ -141,6 +141,11 @@ struct fsmc_nand_timings { uint8_t tset; }; +enum access_mode { + USE_DMA_ACCESS = 1, + USE_WORD_ACCESS, +}; + /** * fsmc_nand_platform_data - platform specific NAND controller config * @partitions: partition table for the platform, use a default fallback @@ -164,6 +169,7 @@ struct fsmc_nand_platform_data { /* CLE, ALE offsets */ unsigned long cle_off; unsigned long ale_off; + enum access_mode mode; void (*select_bank)(uint32_t bank, uint32_t busw); }; -- cgit v1.2.3 From 4774fb0a48aacfec206e6d54ecf58706f6a5320a Mon Sep 17 00:00:00 2001 From: Vipin Kumar Date: Wed, 14 Mar 2012 11:47:18 +0530 Subject: mtd: nand/fsmc: Add DMA support The fsmc_nand driver uses cpu to read/write onto the device. This is inefficient because of two reasons - the cpu gets locked on AHB bus while reading from NAND - the cpu is unnecessarily used when dma can do the job This patch adds the support for accessing the device through DMA Signed-off-by: Vipin Kumar Reviewed-by: Viresh Kumar Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/fsmc.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index 1edd2b3ac38e..18f9127a6631 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h @@ -172,6 +172,10 @@ struct fsmc_nand_platform_data { enum access_mode mode; void (*select_bank)(uint32_t bank, uint32_t busw); + + /* priv structures for dma accesses */ + void *read_dma_priv; + void *write_dma_priv; }; extern int __init fsmc_nor_init(struct platform_device *pdev, -- cgit v1.2.3 From 2a5dbead29a7c081a47133eb428440147a6d8d5a Mon Sep 17 00:00:00 2001 From: Vipin Kumar Date: Wed, 14 Mar 2012 11:47:19 +0530 Subject: mtd: nand/fsmc: Remove sparse warnings and errors This patch removes the sparse below warnings and errors for nand/fsmc driver /root/vipin/spear/kernel/3.3/linux-3.3/drivers/mtd/nand/fsmc_nand.c:363:31: warning: incorrect type in initializer (different address spaces) /root/vipin/spear/kernel/3.3/linux-3.3/drivers/mtd/nand/fsmc_nand.c:363:31: expected struct fsmc_regs *regs /root/vipin/spear/kernel/3.3/linux-3.3/drivers/mtd/nand/fsmc_nand.c:363:31: got void [noderef] *regs_va [...] Signed-off-by: Vipin Kumar Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/fsmc.h | 143 ++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 77 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index 18f9127a6631..823359c0f5a1 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h @@ -32,88 +32,77 @@ #define FSMC_FLASH_WIDTH8 1 #define FSMC_FLASH_WIDTH16 2 -struct fsmc_nor_bank_regs { - uint32_t ctrl; - uint32_t ctrl_tim; -}; - -/* ctrl register definitions */ -#define BANK_ENABLE (1 << 0) -#define MUXED (1 << 1) -#define NOR_DEV (2 << 2) -#define WIDTH_8 (0 << 4) -#define WIDTH_16 (1 << 4) -#define RSTPWRDWN (1 << 6) -#define WPROT (1 << 7) -#define WRT_ENABLE (1 << 12) -#define WAIT_ENB (1 << 13) - -/* ctrl_tim register definitions */ - -struct fsmc_nand_bank_regs { - uint32_t pc; - uint32_t sts; - uint32_t comm; - uint32_t attrib; - uint32_t ioata; - uint32_t ecc1; - uint32_t ecc2; - uint32_t ecc3; -}; - +/* fsmc controller registers for NOR flash */ +#define CTRL 0x0 + /* ctrl register definitions */ + #define BANK_ENABLE (1 << 0) + #define MUXED (1 << 1) + #define NOR_DEV (2 << 2) + #define WIDTH_8 (0 << 4) + #define WIDTH_16 (1 << 4) + #define RSTPWRDWN (1 << 6) + #define WPROT (1 << 7) + #define WRT_ENABLE (1 << 12) + #define WAIT_ENB (1 << 13) + +#define CTRL_TIM 0x4 + /* ctrl_tim register definitions */ + +#define FSMC_NOR_BANK_SZ 0x8 #define FSMC_NOR_REG_SIZE 0x40 -struct fsmc_regs { - struct fsmc_nor_bank_regs nor_bank_regs[FSMC_MAX_NOR_BANKS]; - uint8_t reserved_1[0x40 - 0x20]; - struct fsmc_nand_bank_regs bank_regs[FSMC_MAX_NAND_BANKS]; - uint8_t reserved_2[0xfe0 - 0xc0]; - uint32_t peripid0; /* 0xfe0 */ - uint32_t peripid1; /* 0xfe4 */ - uint32_t peripid2; /* 0xfe8 */ - uint32_t peripid3; /* 0xfec */ - uint32_t pcellid0; /* 0xff0 */ - uint32_t pcellid1; /* 0xff4 */ - uint32_t pcellid2; /* 0xff8 */ - uint32_t pcellid3; /* 0xffc */ -}; +#define FSMC_NOR_REG(base, bank, reg) (base + \ + FSMC_NOR_BANK_SZ * (bank) + \ + reg) + +/* fsmc controller registers for NAND flash */ +#define PC 0x00 + /* pc register definitions */ + #define FSMC_RESET (1 << 0) + #define FSMC_WAITON (1 << 1) + #define FSMC_ENABLE (1 << 2) + #define FSMC_DEVTYPE_NAND (1 << 3) + #define FSMC_DEVWID_8 (0 << 4) + #define FSMC_DEVWID_16 (1 << 4) + #define FSMC_ECCEN (1 << 6) + #define FSMC_ECCPLEN_512 (0 << 7) + #define FSMC_ECCPLEN_256 (1 << 7) + #define FSMC_TCLR_1 (1) + #define FSMC_TCLR_SHIFT (9) + #define FSMC_TCLR_MASK (0xF) + #define FSMC_TAR_1 (1) + #define FSMC_TAR_SHIFT (13) + #define FSMC_TAR_MASK (0xF) +#define STS 0x04 + /* sts register definitions */ + #define FSMC_CODE_RDY (1 << 15) +#define COMM 0x08 + /* comm register definitions */ + #define FSMC_TSET_0 0 + #define FSMC_TSET_SHIFT 0 + #define FSMC_TSET_MASK 0xFF + #define FSMC_TWAIT_6 6 + #define FSMC_TWAIT_SHIFT 8 + #define FSMC_TWAIT_MASK 0xFF + #define FSMC_THOLD_4 4 + #define FSMC_THOLD_SHIFT 16 + #define FSMC_THOLD_MASK 0xFF + #define FSMC_THIZ_1 1 + #define FSMC_THIZ_SHIFT 24 + #define FSMC_THIZ_MASK 0xFF +#define ATTRIB 0x0C +#define IOATA 0x10 +#define ECC1 0x14 +#define ECC2 0x18 +#define ECC3 0x1C +#define FSMC_NAND_BANK_SZ 0x20 + +#define FSMC_NAND_REG(base, bank, reg) (base + FSMC_NOR_REG_SIZE + \ + (FSMC_NAND_BANK_SZ * (bank)) + \ + reg) #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) -/* pc register definitions */ -#define FSMC_RESET (1 << 0) -#define FSMC_WAITON (1 << 1) -#define FSMC_ENABLE (1 << 2) -#define FSMC_DEVTYPE_NAND (1 << 3) -#define FSMC_DEVWID_8 (0 << 4) -#define FSMC_DEVWID_16 (1 << 4) -#define FSMC_ECCEN (1 << 6) -#define FSMC_ECCPLEN_512 (0 << 7) -#define FSMC_ECCPLEN_256 (1 << 7) -#define FSMC_TCLR_1 (1) -#define FSMC_TCLR_SHIFT (9) -#define FSMC_TCLR_MASK (0xF) -#define FSMC_TAR_1 (1) -#define FSMC_TAR_SHIFT (13) -#define FSMC_TAR_MASK (0xF) - -/* sts register definitions */ -#define FSMC_CODE_RDY (1 << 15) - -/* comm register definitions */ -#define FSMC_TSET_0 0 -#define FSMC_TSET_SHIFT 0 -#define FSMC_TSET_MASK 0xFF -#define FSMC_TWAIT_6 6 -#define FSMC_TWAIT_SHIFT 8 -#define FSMC_TWAIT_MASK 0xFF -#define FSMC_THOLD_4 4 -#define FSMC_THOLD_SHIFT 16 -#define FSMC_THOLD_MASK 0xFF -#define FSMC_THIZ_1 1 -#define FSMC_THIZ_SHIFT 24 -#define FSMC_THIZ_MASK 0xFF - /* * There are 13 bytes of ecc for every 512 byte block in FSMC version 8 * and it has to be read consecutively and immediately after the 512 -- cgit v1.2.3 From eea628199d5b12429c47db17035a954b0062e554 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 16 Mar 2012 10:19:31 +0100 Subject: mtd: Add device-tree support to fsmc_nand This patch adds support to configure the FSMC NAND driver (used amongst others on SPEAr platforms) via device-tree instead of platform_data. Signed-off-by: Stefan Roese Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/fsmc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index 823359c0f5a1..b20029221fb1 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h @@ -156,8 +156,8 @@ struct fsmc_nand_platform_data { unsigned int bank; /* CLE, ALE offsets */ - unsigned long cle_off; - unsigned long ale_off; + unsigned int cle_off; + unsigned int ale_off; enum access_mode mode; void (*select_bank)(uint32_t bank, uint32_t busw); -- cgit v1.2.3 From 6551ab5d30d6bf0cea0c6cb294686ce3c7fc6042 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 16 Mar 2012 11:42:11 +0100 Subject: mtd: add device-tree support to spear_smi This patch adds support to configure the SPEAr SMI driver via device-tree instead of platform_data. Signed-off-by: Stefan Roese Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- include/linux/mtd/spear_smi.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/spear_smi.h b/include/linux/mtd/spear_smi.h index 4e26b4e38da3..8ae1726044c3 100644 --- a/include/linux/mtd/spear_smi.h +++ b/include/linux/mtd/spear_smi.h @@ -14,6 +14,10 @@ #include #include #include +#include + +/* max possible slots for serial-nor flash chip in the SMI controller */ +#define MAX_NUM_FLASH_CHIP 4 /* macro to define partitions for flash devices */ #define DEFINE_PARTS(n, of, s) \ @@ -55,6 +59,7 @@ struct spear_smi_plat_data { unsigned long clk_rate; int num_flashes; struct spear_smi_flash_info *board_flash_info; + struct device_node *np[MAX_NUM_FLASH_CHIP]; }; #endif /* __MTD_SPEAR_SMI_H */ -- cgit v1.2.3