From 876f9a348779b348f44736254365bb574fea74eb Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 3 Jul 2015 10:36:14 +0200 Subject: UBI: Fastmap: Simplify expression There is no need to compute pnum again. Signed-off-by: Richard Weinberger Acked-by: Brian Norris --- drivers/mtd/ubi/fastmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 4aa2fd8..0e6bfaf 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -775,7 +775,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, for (j = 0; j < be32_to_cpu(fm_eba->reserved_pebs); j++) { int pnum = be32_to_cpu(fm_eba->pnum[j]); - if ((int)be32_to_cpu(fm_eba->pnum[j]) < 0) + if (pnum < 0) continue; aeb = NULL; -- cgit v1.1 From 4ebb4c9dcbe88a683b083f03176612ee8e87befb Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 3 Jul 2015 10:36:15 +0200 Subject: UBI: Fix typo in comment While we are here fix a s/beween/between typo. Signed-off-by: Richard Weinberger Acked-by: Brian Norris --- drivers/mtd/ubi/ubi-media.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index d0d072e..22ed3f6 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h @@ -500,7 +500,7 @@ struct ubi_fm_volhdr { /* struct ubi_fm_volhdr is followed by one struct ubi_fm_eba records */ /** - * struct ubi_fm_eba - denotes an association beween a PEB and LEB + * struct ubi_fm_eba - denotes an association between a PEB and LEB * @magic: EBA table magic number * @reserved_pebs: number of table entries * @pnum: PEB number of LEB (LEB is the index) -- cgit v1.1 From 5347417e56b68354faf315ca42c99cfb0c02f1dd Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 3 Jul 2015 10:36:16 +0200 Subject: UBI: Fix debug message We have to use j instead of i. i is the volume id and not the block. Reported-by: Alexander.Block@continental-corporation.com Signed-off-by: Richard Weinberger Acked-by: Brian Norris --- drivers/mtd/ubi/eba.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 51bca03..5b9834c 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -1358,7 +1358,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap, continue; ubi_err(ubi, "LEB:%i:%i is PEB:%i instead of %i!", - vol->vol_id, i, fm_eba[i][j], + vol->vol_id, j, fm_eba[i][j], scan_eba[i][j]); ubi_assert(0); } -- cgit v1.1 From 86f6e454e6371003caecee3b4aa55de3e8eacbdd Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 10 Aug 2015 12:02:09 +0100 Subject: UBI: Update comments to reflect UBI_METAONLY flag This patch trivially updates code comments to reflect the addition of the UBI_METAONLY flag - as discussed https://lkml.org/lkml/2014/10/29/764 Cc: Richard Weinberger Cc: trivial@kernel.org Signed-off-by: Andrew Murray Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/gluebi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index b93807b..cb7c075 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c @@ -112,8 +112,8 @@ static int gluebi_get_device(struct mtd_info *mtd) * The MTD device is already referenced and this is just one * more reference. MTD allows many users to open the same * volume simultaneously and do not distinguish between - * readers/writers/exclusive openers as UBI does. So we do not - * open the UBI volume again - just increase the reference + * readers/writers/exclusive/meta openers as UBI does. So we do + * not open the UBI volume again - just increase the reference * counter and return. */ gluebi->refcnt += 1; -- cgit v1.1 From f9a113d65fa56d8e8e662e37ec2fbeac0d52aa01 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 13 Sep 2015 14:15:16 +0200 Subject: UBI: drop null test before destroy functions Remove unneeded NULL test. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x; @@ -if (x != NULL) \(kmem_cache_destroy\|mempool_destroy\|dma_pool_destroy\)(x); // Signed-off-by: Julia Lawall Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/attach.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index 68eea5b..c1aaf03 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -1209,9 +1209,7 @@ static void destroy_ai(struct ubi_attach_info *ai) } } - if (ai->aeb_slab_cache) - kmem_cache_destroy(ai->aeb_slab_cache); - + kmem_cache_destroy(ai->aeb_slab_cache); kfree(ai); } -- cgit v1.1 From 1cb8f9776c7dcadc57885c6653943511d282633b Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 11 Aug 2015 23:27:44 +0200 Subject: ubi: fastmap: Implement produce_free_peb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If fastmap requests a free PEB for a pool and UBI is busy with erasing PEBs we need to offer a function to wait for one. We can reuse produce_free_peb() from the non-fastmap WL code but with different locking semantics. Cc: stable@vger.kernel.org # 4.1.x- Reported-and-tested-by: Jörg Krause Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap-wl.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c index b2a6653..30d3999 100644 --- a/drivers/mtd/ubi/fastmap-wl.c +++ b/drivers/mtd/ubi/fastmap-wl.c @@ -172,6 +172,30 @@ void ubi_refill_pools(struct ubi_device *ubi) } /** + * produce_free_peb - produce a free physical eraseblock. + * @ubi: UBI device description object + * + * This function tries to make a free PEB by means of synchronous execution of + * pending works. This may be needed if, for example the background thread is + * disabled. Returns zero in case of success and a negative error code in case + * of failure. + */ +static int produce_free_peb(struct ubi_device *ubi) +{ + int err; + + while (!ubi->free.rb_node && ubi->works_count) { + dbg_wl("do one work synchronously"); + err = do_work(ubi); + + if (err) + return err; + } + + return 0; +} + +/** * ubi_wl_get_peb - get a physical eraseblock. * @ubi: UBI device description object * @@ -213,6 +237,11 @@ again: } retried = 1; up_read(&ubi->fm_eba_sem); + ret = produce_free_peb(ubi); + if (ret < 0) { + down_read(&ubi->fm_eba_sem); + goto out; + } goto again; } -- cgit v1.1 From 2a130f1aa54c2fb35abfc4d66e0239c80d054210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Sat, 17 Oct 2015 14:55:55 -0300 Subject: UBI: Fastmap: Fix PEB array type The PEB array is an array of __be32, so let's fix the scan_pool() prototype accordingly. Signed-off-by: Ezequiel Garcia Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 0e6bfaf..263b439 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -450,7 +450,7 @@ static void unmap_peb(struct ubi_attach_info *ai, int pnum) * < 0 indicates an internal error. */ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, - int *pebs, int pool_size, unsigned long long *max_sqnum, + __be32 *pebs, int pool_size, unsigned long long *max_sqnum, struct list_head *free) { struct ubi_vid_hdr *vh; -- cgit v1.1 From a396ce4bd21dd67bcec2aabc05f81fd2fa14f820 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 19 Oct 2015 22:26:43 +0200 Subject: UBI: Remove in vain semicolon ...found while browsing. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index d16fccf..54e056d 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -949,7 +949,7 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd, if (!req) { err = -ENOMEM; break; - }; + } err = copy_from_user(req, argp, sizeof(struct ubi_rnvol_req)); if (err) { -- cgit v1.1 From d0164adc89f6bb374d304ffcc375c6d2652fe67d Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Fri, 6 Nov 2015 16:28:21 -0800 Subject: mm, page_alloc: distinguish between being unable to sleep, unwilling to sleep and avoiding waking kswapd __GFP_WAIT has been used to identify atomic context in callers that hold spinlocks or are in interrupts. They are expected to be high priority and have access one of two watermarks lower than "min" which can be referred to as the "atomic reserve". __GFP_HIGH users get access to the first lower watermark and can be called the "high priority reserve". Over time, callers had a requirement to not block when fallback options were available. Some have abused __GFP_WAIT leading to a situation where an optimisitic allocation with a fallback option can access atomic reserves. This patch uses __GFP_ATOMIC to identify callers that are truely atomic, cannot sleep and have no alternative. High priority users continue to use __GFP_HIGH. __GFP_DIRECT_RECLAIM identifies callers that can sleep and are willing to enter direct reclaim. __GFP_KSWAPD_RECLAIM to identify callers that want to wake kswapd for background reclaim. __GFP_WAIT is redefined as a caller that is willing to enter direct reclaim and wake kswapd for background reclaim. This patch then converts a number of sites o __GFP_ATOMIC is used by callers that are high priority and have memory pools for those requests. GFP_ATOMIC uses this flag. o Callers that have a limited mempool to guarantee forward progress clear __GFP_DIRECT_RECLAIM but keep __GFP_KSWAPD_RECLAIM. bio allocations fall into this category where kswapd will still be woken but atomic reserves are not used as there is a one-entry mempool to guarantee progress. o Callers that are checking if they are non-blocking should use the helper gfpflags_allow_blocking() where possible. This is because checking for __GFP_WAIT as was done historically now can trigger false positives. Some exceptions like dm-crypt.c exist where the code intent is clearer if __GFP_DIRECT_RECLAIM is used instead of the helper due to flag manipulations. o Callers that built their own GFP flags instead of starting with GFP_KERNEL and friends now also need to specify __GFP_KSWAPD_RECLAIM. The first key hazard to watch out for is callers that removed __GFP_WAIT and was depending on access to atomic reserves for inconspicuous reasons. In some cases it may be appropriate for them to use __GFP_HIGH. The second key hazard is callers that assembled their own combination of GFP flags instead of starting with something like GFP_KERNEL. They may now wish to specify __GFP_KSWAPD_RECLAIM. It's almost certainly harmless if it's missed in most cases as other activity will wake kswapd. Signed-off-by: Mel Gorman Acked-by: Vlastimil Babka Acked-by: Michal Hocko Acked-by: Johannes Weiner Cc: Christoph Lameter Cc: David Rientjes Cc: Vitaly Wool Cc: Rik van Riel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/mtdcore.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 8bbbb75..2dfb291 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1188,8 +1188,7 @@ EXPORT_SYMBOL_GPL(mtd_writev); */ void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size) { - gfp_t flags = __GFP_NOWARN | __GFP_WAIT | - __GFP_NORETRY | __GFP_NO_KSWAPD; + gfp_t flags = __GFP_NOWARN | __GFP_DIRECT_RECLAIM | __GFP_NORETRY; size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE); void *kbuf; -- cgit v1.1 From a486d11f5d71b88eb235fdfc035eebca5f35f120 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 15 Oct 2015 15:08:44 +0200 Subject: mtd: afs: rename structs and functions for v1 Since we're gonna add the v2 version of flash information structure and we want to avoid confusion, rename the old functions to *v1. Cut the word "structure" from the struct name, it is pretty obvious that it is a struct already from the keyword. Cc: Ryan Harkin Cc: Liviu Dudau Signed-off-by: Linus Walleij Signed-off-by: Brian Norris --- drivers/mtd/afs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c index 96a33e3f..9af0052 100644 --- a/drivers/mtd/afs.c +++ b/drivers/mtd/afs.c @@ -34,7 +34,7 @@ #include #include -struct footer_struct { +struct footer_v1 { u32 image_info_base; /* Address of first word of ImageFooter */ u32 image_start; /* Start of area reserved by this footer */ u32 signature; /* 'Magic' number proves it's a footer */ @@ -42,7 +42,7 @@ struct footer_struct { u32 checksum; /* Just this structure */ }; -struct image_info_struct { +struct image_info_v1 { u32 bootFlags; /* Boot flags, compression etc. */ u32 imageNumber; /* Unique number, selects for boot etc. */ u32 loadAddress; /* Address program should be loaded to */ @@ -67,10 +67,10 @@ static u32 word_sum(void *words, int num) } static int -afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, - u_int off, u_int mask) +afs_read_footer_v1(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, + u_int off, u_int mask) { - struct footer_struct fs; + struct footer_v1 fs; u_int ptr = off + mtd->erasesize - sizeof(fs); size_t sz; int ret; @@ -126,7 +126,7 @@ afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, } static int -afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr) +afs_read_iis_v1(struct mtd_info *mtd, struct image_info_v1 *iis, u_int ptr) { size_t sz; int ret, i; @@ -182,16 +182,16 @@ static int parse_afs_partitions(struct mtd_info *mtd, * the strings. */ for (idx = off = sz = 0; off < mtd->size; off += mtd->erasesize) { - struct image_info_struct iis; + struct image_info_v1 iis; u_int iis_ptr, img_ptr; - ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); + ret = afs_read_footer_v1(mtd, &img_ptr, &iis_ptr, off, mask); if (ret < 0) break; if (ret == 0) continue; - ret = afs_read_iis(mtd, &iis, iis_ptr); + ret = afs_read_iis_v1(mtd, &iis, iis_ptr); if (ret < 0) break; if (ret == 0) @@ -215,18 +215,18 @@ static int parse_afs_partitions(struct mtd_info *mtd, * Identify the partitions */ for (idx = off = 0; off < mtd->size; off += mtd->erasesize) { - struct image_info_struct iis; + struct image_info_v1 iis; u_int iis_ptr, img_ptr; /* Read the footer. */ - ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); + ret = afs_read_footer_v1(mtd, &img_ptr, &iis_ptr, off, mask); if (ret < 0) break; if (ret == 0) continue; /* Read the image info block */ - ret = afs_read_iis(mtd, &iis, iis_ptr); + ret = afs_read_iis_v1(mtd, &iis, iis_ptr); if (ret < 0) break; if (ret == 0) -- cgit v1.1 From 8cf980185d2bf672a5c1d03935f1f165836bb4b0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 15 Oct 2015 15:08:45 +0200 Subject: mtd: enable AFS selection for ARM64 ARM use their special partitions also on the ARM64 architecture reference designs, so enable this for ARM64. Cc: Ryan Harkin Cc: Liviu Dudau Signed-off-by: Linus Walleij Signed-off-by: Brian Norris --- drivers/mtd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index a03ad29..42cc953 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -112,7 +112,7 @@ config MTD_CMDLINE_PARTS config MTD_AFS_PARTS tristate "ARM Firmware Suite partition parsing" - depends on ARM + depends on (ARM || ARM64) ---help--- The ARM Firmware Suite allows the user to divide flash devices into multiple 'images'. Each such image has a header containing its name -- cgit v1.1 From 9498440fff21649cabe529f1d9d4e3bc668fc125 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 15 Oct 2015 15:08:46 +0200 Subject: mtd: afs: break out v1 footer magic to a define Break out the magic number to a #defined constant. Cc: Ryan Harkin Cc: Liviu Dudau Signed-off-by: Linus Walleij Signed-off-by: Brian Norris --- drivers/mtd/afs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c index 9af0052..d09280a 100644 --- a/drivers/mtd/afs.c +++ b/drivers/mtd/afs.c @@ -34,6 +34,8 @@ #include #include +#define AFSV1_FOOTER_MAGIC 0xA0FFFF9F + struct footer_v1 { u32 image_info_base; /* Address of first word of ImageFooter */ u32 image_start; /* Start of area reserved by this footer */ @@ -90,7 +92,7 @@ afs_read_footer_v1(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, /* * Does it contain the magic number? */ - if (fs.signature != 0xa0ffff9f) + if (fs.signature != AFSV1_FOOTER_MAGIC) ret = 0; /* -- cgit v1.1 From d2fd05bb6769d53ab98a11b080b3fb889276049d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 15 Oct 2015 15:08:47 +0200 Subject: mtd: afs: refactor v1 partition parsing Return immediately if we are not finding a valid v1 partition in afs_read_footer_v1(), invert scanning logic so we continue to read image information on v1 if we found a footer. This is needed for the logic we introduce to parse v2 footers. Cc: Ryan Harkin Cc: Liviu Dudau Signed-off-by: Linus Walleij Signed-off-by: Brian Norris --- drivers/mtd/afs.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c index d09280a..a1eea50 100644 --- a/drivers/mtd/afs.c +++ b/drivers/mtd/afs.c @@ -87,25 +87,23 @@ afs_read_footer_v1(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, return ret; } - ret = 1; - /* * Does it contain the magic number? */ if (fs.signature != AFSV1_FOOTER_MAGIC) - ret = 0; + return 0; /* * Check the checksum. */ if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff) - ret = 0; + return 0; /* * Don't touch the SIB. */ if (fs.type == 2) - ret = 0; + return 0; *iis_start = fs.image_info_base & mask; *img_start = fs.image_start & mask; @@ -115,16 +113,16 @@ afs_read_footer_v1(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, * be located after the footer structure. */ if (*iis_start >= ptr) - ret = 0; + return 0; /* * Check the start of this image. The image * data can not be located after this block. */ if (*img_start > off) - ret = 0; + return 0; - return ret; + return 1; } static int @@ -190,18 +188,17 @@ static int parse_afs_partitions(struct mtd_info *mtd, ret = afs_read_footer_v1(mtd, &img_ptr, &iis_ptr, off, mask); if (ret < 0) break; - if (ret == 0) - continue; - - ret = afs_read_iis_v1(mtd, &iis, iis_ptr); - if (ret < 0) - break; - if (ret == 0) - continue; - - sz += sizeof(struct mtd_partition); - sz += strlen(iis.name) + 1; - idx += 1; + if (ret) { + ret = afs_read_iis_v1(mtd, &iis, iis_ptr); + if (ret < 0) + break; + if (ret == 0) + continue; + + sz += sizeof(struct mtd_partition); + sz += strlen(iis.name) + 1; + idx += 1; + } } if (!sz) -- cgit v1.1 From 3b6521eab0386a4854d47b1a01947d7dc46ec98d Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:21 -0700 Subject: mtd: ofpart: grab device tree node directly from master device node It seems more logical to use a device node directly associated with the MTD master device (i.e., mtd->dev.of_node field) rather than requiring auxiliary partition parser information to be passed in by the driver in a separate struct. This patch supports the mtd->dev.of_node field and deprecates the parser data 'of_node' field Driver conversions may now follow. Additional side benefit to assigning mtd->dev.of_node rather than using parser data: the driver core will automatically create a device -> node symlink for us. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/ofpart.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 669c345..7bf996a 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -37,10 +37,11 @@ static int parse_ofpart_partitions(struct mtd_info *master, bool dedicated = true; - if (!data) - return 0; - - mtd_node = data->of_node; + /* + * of_node can be provided through auxiliary parser data or (preferred) + * by assigning the master device node + */ + mtd_node = data && data->of_node ? data->of_node : mtd_get_of_node(master); if (!mtd_node) return 0; @@ -149,10 +150,11 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, } *part; const char *names; - if (!data) - return 0; - - dp = data->of_node; + /* + * of_node can be provided through auxiliary parser data or (preferred) + * by assigning the master device node + */ + dp = data && data->of_node ? data->of_node : mtd_get_of_node(master); if (!dp) return 0; -- cgit v1.1 From 3e63b26bdd4069c3df2cd7ce7217a21d06801b41 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:22 -0700 Subject: mtd: {nand,spi-nor}: assign MTD of_node We should pass along our flash DT node to the MTD layer, so it can set up ofpart for us. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 3 +++ drivers/mtd/spi-nor/spi-nor.c | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index cc74142..939ab3d 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3990,6 +3990,9 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, int ret; if (chip->flash_node) { + /* MTD can automatically handle DT partitions, etc. */ + mtd_set_of_node(mtd, chip->flash_node); + ret = nand_dt_init(mtd, chip, chip->flash_node); if (ret) return ret; diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 4988390..1d3107c 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1258,6 +1258,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) mtd->flags |= MTD_NO_ERASE; mtd->dev.parent = dev; + mtd_set_of_node(mtd, np); nor->page_size = info->page_size; mtd->writebufsize = nor->page_size; -- cgit v1.1 From 6375219951a66047805ed977b674615d152001ee Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:23 -0700 Subject: mtd: nand: convert to nand_set_flash_node() Used semantic patch with 'make coccicheck MODE=patch COCCI=script.cocci': ---8<---- virtual patch @@ struct nand_chip *c; struct device_node *d; @@ -(c)->flash_node = (d) +nand_set_flash_node(c, d) ---8<---- Signed-off-by: Brian Norris Reviewed-by: Marek Vasut Reviewed-by: Boris Brezillon --- drivers/mtd/nand/brcmnand/brcmnand.c | 2 +- drivers/mtd/nand/fsmc_nand.c | 2 +- drivers/mtd/nand/sunxi_nand.c | 2 +- drivers/mtd/nand/vf610_nfc.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 12c6190..7bd4102 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -1925,7 +1925,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host) mtd = &host->mtd; chip = &host->chip; - chip->flash_node = dn; + nand_set_flash_node(chip, dn); chip->priv = host; mtd->priv = chip; mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d", diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 07af3dc..6f9e422 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -1033,7 +1033,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) nand->options = pdata->options; nand->select_chip = fsmc_select_chip; nand->badblockbits = 7; - nand->flash_node = np; + nand_set_flash_node(nand, np); if (pdata->width == FSMC_NAND_BW16) nand->options |= NAND_BUSWIDTH_16; diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 8247118..0775ae4 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1330,7 +1330,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, * in the DT. */ nand->ecc.mode = NAND_ECC_HW; - nand->flash_node = np; + nand_set_flash_node(nand, np); nand->select_chip = sunxi_nfc_select_chip; nand->cmd_ctrl = sunxi_nfc_cmd_ctrl; nand->read_buf = sunxi_nfc_read_buf; diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 8805d63..7b952ab 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -714,7 +714,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) goto error; } - chip->flash_node = child; + nand_set_flash_node(chip, child); } } -- cgit v1.1 From 9c7d787508be6d68a6ec66de3c3466b24e820c71 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:24 -0700 Subject: mtd: spi-nor: convert to spi_nor_{get, set}_flash_node() Used semantic patch with 'make coccicheck MODE=patch COCCI=script.cocci': ---8<---- virtual patch @@ struct spi_nor b; struct spi_nor *c; expression d; @@ ( -(b).flash_node = (d) +spi_nor_set_flash_node(&b, d) | -(c)->flash_node = (d) +spi_nor_set_flash_node(c, d) ) ---8<---- And a manual conversion for the one use of spi_nor_get_flash_node(). Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/devices/m25p80.c | 2 +- drivers/mtd/spi-nor/fsl-quadspi.c | 2 +- drivers/mtd/spi-nor/nxp-spifi.c | 2 +- drivers/mtd/spi-nor/spi-nor.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 4b5d7a4..556b455 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -199,7 +199,7 @@ static int m25p_probe(struct spi_device *spi) nor->read_reg = m25p80_read_reg; nor->dev = &spi->dev; - nor->flash_node = spi->dev.of_node; + spi_nor_set_flash_node(nor, spi->dev.of_node); nor->priv = flash; spi_set_drvdata(spi, flash); diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 7b10ed4..8f4d920 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -1013,7 +1013,7 @@ static int fsl_qspi_probe(struct platform_device *pdev) mtd = &nor->mtd; nor->dev = dev; - nor->flash_node = np; + spi_nor_set_flash_node(nor, np); nor->priv = q; /* fill the hooks */ diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/nxp-spifi.c index 9e82098..4524b28 100644 --- a/drivers/mtd/spi-nor/nxp-spifi.c +++ b/drivers/mtd/spi-nor/nxp-spifi.c @@ -330,7 +330,7 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi, writel(ctrl, spifi->io_base + SPIFI_CTRL); spifi->nor.dev = spifi->dev; - spifi->nor.flash_node = np; + spi_nor_set_flash_node(&spifi->nor, np); spifi->nor.priv = spifi; spifi->nor.read = nxp_spifi_read; spifi->nor.write = nxp_spifi_write; diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 1d3107c..924d455 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1151,7 +1151,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) const struct flash_info *info = NULL; struct device *dev = nor->dev; struct mtd_info *mtd = &nor->mtd; - struct device_node *np = nor->flash_node; + struct device_node *np = spi_nor_get_flash_node(nor); int ret; int i; -- cgit v1.1 From a61ae81a1907af1987ad4c77300508327bc48b23 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:25 -0700 Subject: mtd: nand: drop unnecessary partition parser data All of these drivers set up a parser data struct just to communicate DT partition data. This field has been deprecated and is instead supported by telling nand_scan_ident() about the 'flash_node'. This patch: * sets chip->flash_node for those drivers that didn't already (but used OF partitioning) * drops the parser data * switches to the simpler mtd_device_register() where possible, now that we've eliminated one of the auxiliary parameters Now that we've assigned chip->flash_node for these drivers, we can probably rely on nand_dt_init() to do more of the DT parsing for us, but for now, I don't want to fiddle with each of these drivers. The parsing is done in duplicate for now on some drivers. I don't think this should break things. (Famous last words.) (Rolled in some changes by Boris Brezillon) Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/nand/atmel_nand.c | 7 +++---- drivers/mtd/nand/brcmnand/brcmnand.c | 3 +-- drivers/mtd/nand/davinci_nand.c | 10 +++------- drivers/mtd/nand/fsl_elbc_nand.c | 5 ++--- drivers/mtd/nand/fsl_ifc_nand.c | 5 ++--- drivers/mtd/nand/fsl_upm.c | 5 ++--- drivers/mtd/nand/fsmc_nand.c | 7 +++---- drivers/mtd/nand/gpio.c | 8 +++----- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 5 ++--- drivers/mtd/nand/hisi504_nand.c | 5 ++--- drivers/mtd/nand/lpc32xx_mlc.c | 7 +++---- drivers/mtd/nand/lpc32xx_slc.c | 7 +++---- drivers/mtd/nand/mpc5121_nfc.c | 5 ++--- drivers/mtd/nand/mxc_nand.c | 5 ++--- drivers/mtd/nand/ndfc.c | 5 ++--- drivers/mtd/nand/omap2.c | 6 ++---- drivers/mtd/nand/orion_nand.c | 6 ++---- drivers/mtd/nand/plat_nand.c | 5 ++--- drivers/mtd/nand/pxa3xx_nand.c | 10 +++++----- drivers/mtd/nand/sh_flctl.c | 6 ++---- drivers/mtd/nand/socrates_nand.c | 5 ++--- drivers/mtd/nand/sunxi_nand.c | 4 +--- drivers/mtd/nand/vf610_nfc.c | 6 +----- 23 files changed, 52 insertions(+), 85 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 583cdd9..6ecc1c1 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -2093,7 +2093,6 @@ static int atmel_nand_probe(struct platform_device *pdev) struct mtd_info *mtd; struct nand_chip *nand_chip; struct resource *mem; - struct mtd_part_parser_data ppdata = {}; int res, irq; /* Allocate memory for the device structure (and zero it) */ @@ -2117,6 +2116,7 @@ static int atmel_nand_probe(struct platform_device *pdev) nand_chip = &host->nand_chip; host->dev = &pdev->dev; if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { + nand_set_flash_node(nand_chip, pdev->dev.of_node); /* Only when CONFIG_OF is enabled of_node can be parsed */ res = atmel_of_init_port(host, pdev->dev.of_node); if (res) @@ -2259,9 +2259,8 @@ static int atmel_nand_probe(struct platform_device *pdev) } mtd->name = "atmel_nand"; - ppdata.of_node = pdev->dev.of_node; - res = mtd_device_parse_register(mtd, NULL, &ppdata, - host->board.parts, host->board.num_parts); + res = mtd_device_register(mtd, host->board.parts, + host->board.num_parts); if (!res) return res; diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 7bd4102..a37659d 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -1914,7 +1914,6 @@ static int brcmnand_init_cs(struct brcmnand_host *host) struct nand_chip *chip; int ret; u16 cfg_offs; - struct mtd_part_parser_data ppdata = { .of_node = dn }; ret = of_property_read_u32(dn, "reg", &host->cs); if (ret) { @@ -1993,7 +1992,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host) if (nand_scan_tail(mtd)) return -ENXIO; - return mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + return mtd_device_register(mtd, NULL, 0); } static void brcmnand_save_restore_cs_config(struct brcmnand_host *host, diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index c72313d..8e351af 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -684,6 +684,7 @@ static int nand_davinci_probe(struct platform_device *pdev) info->mtd.priv = &info->chip; info->mtd.dev.parent = &pdev->dev; + nand_set_flash_node(&info->chip, pdev->dev.of_node); info->chip.IO_ADDR_R = vaddr; info->chip.IO_ADDR_W = vaddr; @@ -839,13 +840,8 @@ syndrome_done: if (pdata->parts) ret = mtd_device_parse_register(&info->mtd, NULL, NULL, pdata->parts, pdata->nr_parts); - else { - struct mtd_part_parser_data ppdata; - - ppdata.of_node = pdev->dev.of_node; - ret = mtd_device_parse_register(&info->mtd, NULL, &ppdata, - NULL, 0); - } + else + ret = mtd_device_register(&info->mtd, NULL, 0); if (ret < 0) goto err; diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index dcb1f7f..bd6d493 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -748,6 +748,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) /* Fill in fsl_elbc_mtd structure */ priv->mtd.priv = chip; priv->mtd.dev.parent = priv->dev; + nand_set_flash_node(chip, priv->dev->of_node); /* set timeout to maximum */ priv->fmr = 15 << FMR_CWTO_SHIFT; @@ -823,9 +824,7 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev) int bank; struct device *dev; struct device_node *node = pdev->dev.of_node; - struct mtd_part_parser_data ppdata; - ppdata.of_node = pdev->dev.of_node; if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) return -ENODEV; lbc = fsl_lbc_ctrl_dev->regs; @@ -911,7 +910,7 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev) /* First look for RedBoot table or partitions on the command * line, these take precedence over device tree information */ - mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata, + mtd_device_parse_register(&priv->mtd, part_probe_types, NULL, NULL, 0); printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n", diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 7f4ac8c..f260831 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -883,6 +883,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) /* Fill in fsl_ifc_mtd structure */ priv->mtd.priv = chip; priv->mtd.dev.parent = priv->dev; + nand_set_flash_node(chip, priv->dev->of_node); /* fill in nand_chip structure */ /* set up function call table */ @@ -1030,9 +1031,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) int ret; int bank; struct device_node *node = dev->dev.of_node; - struct mtd_part_parser_data ppdata; - ppdata.of_node = dev->dev.of_node; if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) return -ENODEV; ifc = fsl_ifc_ctrl_dev->regs; @@ -1128,7 +1127,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) /* First look for RedBoot table or partitions on the command * line, these take precedence over device tree information */ - mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata, + mtd_device_parse_register(&priv->mtd, part_probe_types, NULL, NULL, 0); dev_info(priv->dev, "IFC NAND device at 0x%llx, bank %d\n", diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index d326369..b3f4a01 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -159,7 +159,6 @@ static int fun_chip_init(struct fsl_upm_nand *fun, { int ret; struct device_node *flash_np; - struct mtd_part_parser_data ppdata; fun->chip.IO_ADDR_R = fun->io_base; fun->chip.IO_ADDR_W = fun->io_base; @@ -182,6 +181,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, if (!flash_np) return -ENODEV; + nand_set_flash_node(&fun->chip, flash_np); fun->mtd.name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start, flash_np->name); if (!fun->mtd.name) { @@ -193,8 +193,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, if (ret) goto err; - ppdata.of_node = flash_np; - ret = mtd_device_parse_register(&fun->mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_register(&fun->mtd, NULL, 0); err: of_node_put(flash_np); if (ret) diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 6f9e422..59fc6d0 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -926,7 +926,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) { struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device_node __maybe_unused *np = pdev->dev.of_node; - struct mtd_part_parser_data ppdata = {}; struct fsmc_nand_data *host; struct mtd_info *mtd; struct nand_chip *nand; @@ -1016,6 +1015,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) nand = &host->nand; mtd->priv = nand; nand->priv = host; + nand_set_flash_node(nand, np); host->mtd.dev.parent = &pdev->dev; nand->IO_ADDR_R = host->data_va; @@ -1175,9 +1175,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) * Check for partition info passed */ host->mtd.name = "nand"; - ppdata.of_node = np; - ret = mtd_device_parse_register(&host->mtd, NULL, &ppdata, - host->partitions, host->nr_partitions); + ret = mtd_device_register(&host->mtd, host->partitions, + host->nr_partitions); if (ret) goto err_probe; diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index 9ab97f9..d57a07a 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c @@ -209,7 +209,6 @@ static int gpio_nand_probe(struct platform_device *pdev) struct gpiomtd *gpiomtd; struct nand_chip *chip; struct resource *res; - struct mtd_part_parser_data ppdata = {}; int ret = 0; if (!pdev->dev.of_node && !dev_get_platdata(&pdev->dev)) @@ -268,6 +267,7 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->dev_ready = gpio_nand_devready; } + nand_set_flash_node(chip, pdev->dev.of_node); chip->IO_ADDR_W = chip->IO_ADDR_R; chip->ecc.mode = NAND_ECC_SOFT; chip->options = gpiomtd->plat.options; @@ -291,10 +291,8 @@ static int gpio_nand_probe(struct platform_device *pdev) gpiomtd->plat.adjust_parts(&gpiomtd->plat, gpiomtd->mtd_info.size); - ppdata.of_node = pdev->dev.of_node; - ret = mtd_device_parse_register(&gpiomtd->mtd_info, NULL, &ppdata, - gpiomtd->plat.parts, - gpiomtd->plat.num_parts); + ret = mtd_device_register(&gpiomtd->mtd_info, gpiomtd->plat.parts, + gpiomtd->plat.num_parts); if (!ret) return 0; diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 2064ada..5a9b696 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -1888,7 +1888,6 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) { struct mtd_info *mtd = &this->mtd; struct nand_chip *chip = &this->nand; - struct mtd_part_parser_data ppdata = {}; int ret; /* init current chip */ @@ -1901,6 +1900,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) /* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */ chip->priv = this; + nand_set_flash_node(chip, this->pdev->dev.of_node); chip->select_chip = gpmi_select_chip; chip->cmd_ctrl = gpmi_cmd_ctrl; chip->dev_ready = gpmi_dev_ready; @@ -1954,8 +1954,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) if (ret) goto err_out; - ppdata.of_node = this->pdev->dev.of_node; - ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_register(mtd, NULL, 0); if (ret) goto err_out; return 0; diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c index 0cb2e88..0aad4ac 100644 --- a/drivers/mtd/nand/hisi504_nand.c +++ b/drivers/mtd/nand/hisi504_nand.c @@ -704,7 +704,6 @@ static int hisi_nfc_probe(struct platform_device *pdev) struct mtd_info *mtd; struct resource *res; struct device_node *np = dev->of_node; - struct mtd_part_parser_data ppdata; host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); if (!host) @@ -742,6 +741,7 @@ static int hisi_nfc_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; chip->priv = host; + nand_set_flash_node(chip, np); chip->cmdfunc = hisi_nfc_cmdfunc; chip->select_chip = hisi_nfc_select_chip; chip->read_byte = hisi_nfc_read_byte; @@ -805,8 +805,7 @@ static int hisi_nfc_probe(struct platform_device *pdev) goto err_res; } - ppdata.of_node = np; - ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_register(mtd, NULL, 0); if (ret) { dev_err(dev, "Err MTD partition=%d\n", ret); goto err_mtd; diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index 3475109..57c4b71 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -647,7 +647,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) struct nand_chip *nand_chip; struct resource *rc; int res; - struct mtd_part_parser_data ppdata = {}; /* Allocate memory for the device structure (and zero it) */ host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); @@ -682,6 +681,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) host->pdata = dev_get_platdata(&pdev->dev); nand_chip->priv = host; /* link the private data structures */ + nand_set_flash_node(nand_chip, pdev->dev.of_node); mtd->priv = nand_chip; mtd->dev.parent = &pdev->dev; @@ -786,9 +786,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) mtd->name = DRV_NAME; - ppdata.of_node = pdev->dev.of_node; - res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts, - host->ncfg->num_parts); + res = mtd_device_register(mtd, host->ncfg->parts, + host->ncfg->num_parts); if (!res) return res; diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index 4f3d4eb..277626e 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c @@ -763,7 +763,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) struct mtd_info *mtd; struct nand_chip *chip; struct resource *rc; - struct mtd_part_parser_data ppdata = {}; int res; rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -803,6 +802,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) mtd = &host->mtd; chip = &host->nand_chip; chip->priv = host; + nand_set_flash_node(chip, pdev->dev.of_node); mtd->priv = chip; mtd->owner = THIS_MODULE; mtd->dev.parent = &pdev->dev; @@ -908,9 +908,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) } mtd->name = "nxp_lpc3220_slc"; - ppdata.of_node = pdev->dev.of_node; - res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts, - host->ncfg->num_parts); + res = mtd_device_register(mtd, host->ncfg->parts, + host->ncfg->num_parts); if (!res) return res; diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index d6bbde4..0fdfc42 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -639,7 +639,6 @@ static int mpc5121_nfc_probe(struct platform_device *op) int resettime = 0; int retval = 0; int rev, len; - struct mtd_part_parser_data ppdata; /* * Check SoC revision. This driver supports only NFC @@ -661,6 +660,7 @@ static int mpc5121_nfc_probe(struct platform_device *op) mtd->priv = chip; mtd->dev.parent = dev; chip->priv = prv; + nand_set_flash_node(chip, dn); prv->dev = dev; /* Read NFC configuration from Reset Config Word */ @@ -703,7 +703,6 @@ static int mpc5121_nfc_probe(struct platform_device *op) } mtd->name = "MPC5121 NAND"; - ppdata.of_node = dn; chip->dev_ready = mpc5121_nfc_dev_ready; chip->cmdfunc = mpc5121_nfc_command; chip->read_byte = mpc5121_nfc_read_byte; @@ -815,7 +814,7 @@ static int mpc5121_nfc_probe(struct platform_device *op) dev_set_drvdata(dev, mtd); /* Register device in MTD */ - retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + retval = mtd_device_register(mtd, NULL, 0); if (retval) { dev_err(dev, "Error adding MTD device!\n"); goto error; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 136e73a..7922d31 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -1524,6 +1524,7 @@ static int mxcnd_probe(struct platform_device *pdev) this->chip_delay = 5; this->priv = host; + nand_set_flash_node(this, pdev->dev.of_node), this->dev_ready = mxc_nand_dev_ready; this->cmdfunc = mxc_nand_command; this->read_byte = mxc_nand_read_byte; @@ -1683,9 +1684,7 @@ static int mxcnd_probe(struct platform_device *pdev) /* Register the partitions */ mtd_device_parse_register(mtd, part_probes, - &(struct mtd_part_parser_data){ - .of_node = pdev->dev.of_node, - }, + NULL, host->pdata.parts, host->pdata.nr_parts); diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 4f0d62f..6965858 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -147,7 +147,6 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, { struct device_node *flash_np; struct nand_chip *chip = &ndfc->chip; - struct mtd_part_parser_data ppdata; int ret; chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; @@ -174,8 +173,8 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, flash_np = of_get_next_child(node, NULL); if (!flash_np) return -ENODEV; + nand_set_flash_node(chip, flash_np); - ppdata.of_node = flash_np; ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s", dev_name(&ndfc->ofdev->dev), flash_np->name); if (!ndfc->mtd.name) { @@ -187,7 +186,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, if (ret) goto err; - ret = mtd_device_parse_register(&ndfc->mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_register(&ndfc->mtd, NULL, 0); err: of_node_put(flash_np); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 93f664c..e307576 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1663,7 +1663,6 @@ static int omap_nand_probe(struct platform_device *pdev) unsigned sig; unsigned oob_index; struct resource *res; - struct mtd_part_parser_data ppdata = {}; pdata = dev_get_platdata(&pdev->dev); if (pdata == NULL) { @@ -1688,6 +1687,7 @@ static int omap_nand_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; nand_chip = &info->nand; nand_chip->ecc.priv = NULL; + nand_set_flash_node(nand_chip, pdata->of_node); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); @@ -2037,9 +2037,7 @@ scan_tail: goto return_error; } - ppdata.of_node = pdata->of_node; - mtd_device_parse_register(mtd, NULL, &ppdata, pdata->parts, - pdata->nr_parts); + mtd_device_register(mtd, pdata->parts, pdata->nr_parts); platform_set_drvdata(pdev, mtd); diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index ee83749..5c21416 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -76,7 +76,6 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static int __init orion_nand_probe(struct platform_device *pdev) { struct mtd_info *mtd; - struct mtd_part_parser_data ppdata = {}; struct nand_chip *nc; struct orion_nand_data *board; struct resource *res; @@ -127,6 +126,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; nc->priv = board; + nand_set_flash_node(nc, pdev->dev.of_node); nc->IO_ADDR_R = nc->IO_ADDR_W = io_base; nc->cmd_ctrl = orion_nand_cmd_ctrl; nc->read_buf = orion_nand_read_buf; @@ -161,9 +161,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) } mtd->name = "orion_nand"; - ppdata.of_node = pdev->dev.of_node; - ret = mtd_device_parse_register(mtd, NULL, &ppdata, - board->parts, board->nr_parts); + ret = mtd_device_register(mtd, board->parts, board->nr_parts); if (ret) { nand_release(mtd); goto no_dev; diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 65b9dbbe..06ac6c6 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -30,7 +30,6 @@ struct plat_nand_data { static int plat_nand_probe(struct platform_device *pdev) { struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); - struct mtd_part_parser_data ppdata; struct plat_nand_data *data; struct resource *res; const char **part_types; @@ -58,6 +57,7 @@ static int plat_nand_probe(struct platform_device *pdev) return PTR_ERR(data->io_base); data->chip.priv = &data; + nand_set_flash_node(&data->chip, pdev->dev.of_node); data->mtd.priv = &data->chip; data->mtd.dev.parent = &pdev->dev; @@ -94,8 +94,7 @@ static int plat_nand_probe(struct platform_device *pdev) part_types = pdata->chip.part_probe_types; - ppdata.of_node = pdev->dev.of_node; - err = mtd_device_parse_register(&data->mtd, part_types, &ppdata, + err = mtd_device_parse_register(&data->mtd, part_types, NULL, pdata->chip.partitions, pdata->chip.nr_partitions); diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index e453ae9..37df51d 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1697,6 +1697,7 @@ KEEP_CONFIG: static int alloc_nand_resource(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct pxa3xx_nand_platform_data *pdata; struct pxa3xx_nand_info *info; struct pxa3xx_nand_host *host; @@ -1725,6 +1726,8 @@ static int alloc_nand_resource(struct platform_device *pdev) host->info_data = info; mtd->priv = host; mtd->dev.parent = &pdev->dev; + /* FIXME: all chips use the same device tree partitions */ + nand_set_flash_node(chip, np); chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; @@ -1886,7 +1889,6 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev) static int pxa3xx_nand_probe(struct platform_device *pdev) { struct pxa3xx_nand_platform_data *pdata; - struct mtd_part_parser_data ppdata = {}; struct pxa3xx_nand_info *info; int ret, cs, probe_success, dma_available; @@ -1933,10 +1935,8 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) continue; } - ppdata.of_node = pdev->dev.of_node; - ret = mtd_device_parse_register(mtd, NULL, - &ppdata, pdata->parts[cs], - pdata->nr_parts[cs]); + ret = mtd_device_register(mtd, pdata->parts[cs], + pdata->nr_parts[cs]); if (!ret) probe_success = 1; } diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index bcba1a9..57dc525 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -1086,7 +1086,6 @@ static int flctl_probe(struct platform_device *pdev) struct sh_flctl_platform_data *pdata; int ret; int irq; - struct mtd_part_parser_data ppdata = {}; flctl = devm_kzalloc(&pdev->dev, sizeof(struct sh_flctl), GFP_KERNEL); if (!flctl) @@ -1123,6 +1122,7 @@ static int flctl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, flctl); flctl_mtd = &flctl->mtd; nand = &flctl->chip; + nand_set_flash_node(nand, pdev->dev.of_node); flctl_mtd->priv = nand; flctl_mtd->dev.parent = &pdev->dev; flctl->pdev = pdev; @@ -1163,9 +1163,7 @@ static int flctl_probe(struct platform_device *pdev) if (ret) goto err_chip; - ppdata.of_node = pdev->dev.of_node; - ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts, - pdata->nr_parts); + ret = mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts); return 0; diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index b94f534..bde4043 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -147,7 +147,6 @@ static int socrates_nand_probe(struct platform_device *ofdev) struct mtd_info *mtd; struct nand_chip *nand_chip; int res; - struct mtd_part_parser_data ppdata; /* Allocate memory for the device structure (and zero it) */ host = devm_kzalloc(&ofdev->dev, sizeof(*host), GFP_KERNEL); @@ -165,10 +164,10 @@ static int socrates_nand_probe(struct platform_device *ofdev) host->dev = &ofdev->dev; nand_chip->priv = host; /* link the private data structures */ + nand_set_flash_node(nand_chip, ofdev->dev.of_node); mtd->priv = nand_chip; mtd->name = "socrates_nand"; mtd->dev.parent = &ofdev->dev; - ppdata.of_node = ofdev->dev.of_node; /*should never be accessed directly */ nand_chip->IO_ADDR_R = (void *)0xdeadbeef; @@ -200,7 +199,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) goto out; } - res = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + res = mtd_device_register(mtd, NULL, 0); if (!res) return res; diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 0775ae4..2ed52e4 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1232,7 +1232,6 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, { const struct nand_sdr_timings *timings; struct sunxi_nand_chip *chip; - struct mtd_part_parser_data ppdata; struct mtd_info *mtd; struct nand_chip *nand; int nsels; @@ -1366,8 +1365,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, return ret; } - ppdata.of_node = np; - ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_register(mtd, NULL, 0); if (ret) { dev_err(dev, "failed to register mtd device: %d\n", ret); nand_release(mtd); diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 7b952ab..b6df4c6 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -811,11 +811,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mtd); /* Register device in MTD */ - return mtd_device_parse_register(mtd, NULL, - &(struct mtd_part_parser_data){ - .of_node = chip->flash_node, - }, - NULL, 0); + return mtd_device_register(mtd, NULL, 0); error: of_node_put(chip->flash_node); -- cgit v1.1 From df02c885f8697546da41665f28dde5e30ce99674 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:26 -0700 Subject: mtd: spi-nor: drop unnecessary partition parser data Now that the SPI-NOR/MTD framework pass the 'flash_node' through to the partition parsing code, we don't have to do it ourselves. Also convert to mtd_device_register(), since we don't need the 2nd and 3rd parameters anymore. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/devices/m25p80.c | 8 ++------ drivers/mtd/spi-nor/fsl-quadspi.c | 4 +--- drivers/mtd/spi-nor/nxp-spifi.c | 4 +--- 3 files changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 556b455..6dbf783 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -175,7 +175,6 @@ static int m25p80_erase(struct spi_nor *nor, loff_t offset) */ static int m25p_probe(struct spi_device *spi) { - struct mtd_part_parser_data ppdata; struct flash_platform_data *data; struct m25p *flash; struct spi_nor *nor; @@ -227,11 +226,8 @@ static int m25p_probe(struct spi_device *spi) if (ret) return ret; - ppdata.of_node = spi->dev.of_node; - - return mtd_device_parse_register(&nor->mtd, NULL, &ppdata, - data ? data->parts : NULL, - data ? data->nr_parts : 0); + return mtd_device_register(&nor->mtd, data ? data->parts : NULL, + data ? data->nr_parts : 0); } diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 8f4d920..9e7f657 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -927,7 +927,6 @@ static void fsl_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops) static int fsl_qspi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct mtd_part_parser_data ppdata; struct device *dev = &pdev->dev; struct fsl_qspi *q; struct resource *res; @@ -1038,8 +1037,7 @@ static int fsl_qspi_probe(struct platform_device *pdev) if (ret) goto mutex_failed; - ppdata.of_node = np; - ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_register(mtd, NULL, 0); if (ret) goto mutex_failed; diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/nxp-spifi.c index 4524b28..ae428cb 100644 --- a/drivers/mtd/spi-nor/nxp-spifi.c +++ b/drivers/mtd/spi-nor/nxp-spifi.c @@ -271,7 +271,6 @@ static void nxp_spifi_dummy_id_read(struct spi_nor *nor) static int nxp_spifi_setup_flash(struct nxp_spifi *spifi, struct device_node *np) { - struct mtd_part_parser_data ppdata; enum read_mode flash_read; u32 ctrl, property; u16 mode = 0; @@ -361,8 +360,7 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi, return ret; } - ppdata.of_node = np; - ret = mtd_device_parse_register(&spifi->nor.mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_register(&spifi->nor.mtd, NULL, 0); if (ret) { dev_err(spifi->dev, "mtd device parse failed\n"); return ret; -- cgit v1.1 From 30069af7348b56eb8c5e1dda7788a531c5f24ca2 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:27 -0700 Subject: mtd: spi-nor: drop flash_node field We can just alias to the MTD of_node. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 924d455..12041e1 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1258,7 +1258,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) mtd->flags |= MTD_NO_ERASE; mtd->dev.parent = dev; - mtd_set_of_node(mtd, np); nor->page_size = info->page_size; mtd->writebufsize = nor->page_size; -- cgit v1.1 From 004b5e6031f4e9fd90d565fb213b74cd06d03718 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:28 -0700 Subject: mtd: drop unnecessary partition parser data We should assign the MTD dev.of_node instead of the parser data field. This gets us the equivalent partition parser behavior with fewer special fields and parameter passing. Also convert several of these to mtd_device_register(), since we don't need the 2nd and 3rd parameters anymore. Signed-off-by: Brian Norris Reviewed-by: Marek Vasut Reviewed-by: Boris Brezillon --- drivers/mtd/devices/mtd_dataflash.c | 5 ++--- drivers/mtd/devices/spear_smi.c | 6 ++---- drivers/mtd/devices/st_spi_fsm.c | 5 ++--- drivers/mtd/maps/lantiq-flash.c | 5 ++--- drivers/mtd/maps/physmap_of.c | 5 ++--- drivers/mtd/onenand/omap2.c | 8 +++----- 6 files changed, 13 insertions(+), 21 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 39666d5..0ada3ed 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -624,7 +624,6 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages, { struct dataflash *priv; struct mtd_info *device; - struct mtd_part_parser_data ppdata; struct flash_platform_data *pdata = dev_get_platdata(&spi->dev); char *otp_tag = ""; int err = 0; @@ -656,6 +655,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages, device->priv = priv; device->dev.parent = &spi->dev; + mtd_set_of_node(device, spi->dev.of_node); if (revision >= 'c') otp_tag = otp_setup(device, revision); @@ -665,8 +665,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages, pagesize, otp_tag); spi_set_drvdata(spi, priv); - ppdata.of_node = spi->dev.of_node; - err = mtd_device_parse_register(device, NULL, &ppdata, + err = mtd_device_register(device, pdata ? pdata->parts : NULL, pdata ? pdata->nr_parts : 0); diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index 64c7458..dd50698 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c @@ -810,7 +810,6 @@ static int spear_smi_setup_banks(struct platform_device *pdev, u32 bank, struct device_node *np) { struct spear_smi *dev = platform_get_drvdata(pdev); - struct mtd_part_parser_data ppdata = {}; struct spear_smi_flash_info *flash_info; struct spear_smi_plat_data *pdata; struct spear_snor_flash *flash; @@ -855,6 +854,7 @@ static int spear_smi_setup_banks(struct platform_device *pdev, flash->mtd.name = flash_devices[flash_index].name; flash->mtd.dev.parent = &pdev->dev; + mtd_set_of_node(&flash->mtd, np); flash->mtd.type = MTD_NORFLASH; flash->mtd.writesize = 1; flash->mtd.flags = MTD_CAP_NORFLASH; @@ -881,10 +881,8 @@ static int spear_smi_setup_banks(struct platform_device *pdev, count = flash_info->nr_partitions; } #endif - ppdata.of_node = np; - ret = mtd_device_parse_register(&flash->mtd, NULL, &ppdata, parts, - count); + ret = mtd_device_register(&flash->mtd, parts, count); if (ret) { dev_err(&dev->pdev->dev, "Err MTD partition=%d\n", ret); return ret; diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 3060025..5454b41 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -2025,7 +2025,6 @@ boot_device_fail: static int stfsm_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct mtd_part_parser_data ppdata; struct flash_info *info; struct resource *res; struct stfsm *fsm; @@ -2035,7 +2034,6 @@ static int stfsm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "No DT found\n"); return -EINVAL; } - ppdata.of_node = np; fsm = devm_kzalloc(&pdev->dev, sizeof(*fsm), GFP_KERNEL); if (!fsm) @@ -2106,6 +2104,7 @@ static int stfsm_probe(struct platform_device *pdev) fsm->mtd.name = info->name; fsm->mtd.dev.parent = &pdev->dev; + mtd_set_of_node(&fsm->mtd, np); fsm->mtd.type = MTD_NORFLASH; fsm->mtd.writesize = 4; fsm->mtd.writebufsize = fsm->mtd.writesize; @@ -2124,7 +2123,7 @@ static int stfsm_probe(struct platform_device *pdev) (long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20), fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10)); - return mtd_device_parse_register(&fsm->mtd, NULL, &ppdata, NULL, 0); + return mtd_device_register(&fsm->mtd, NULL, 0); } static int stfsm_remove(struct platform_device *pdev) diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c index 9385205..c8febb3 100644 --- a/drivers/mtd/maps/lantiq-flash.c +++ b/drivers/mtd/maps/lantiq-flash.c @@ -110,7 +110,6 @@ ltq_copy_to(struct map_info *map, unsigned long to, static int ltq_mtd_probe(struct platform_device *pdev) { - struct mtd_part_parser_data ppdata; struct ltq_mtd *ltq_mtd; struct cfi_private *cfi; int err; @@ -161,13 +160,13 @@ ltq_mtd_probe(struct platform_device *pdev) } ltq_mtd->mtd->dev.parent = &pdev->dev; + mtd_set_of_node(ltq_mtd->mtd, pdev->dev.of_node); cfi = ltq_mtd->map->fldrv_priv; cfi->addr_unlock1 ^= 1; cfi->addr_unlock2 ^= 1; - ppdata.of_node = pdev->dev.of_node; - err = mtd_device_parse_register(ltq_mtd->mtd, NULL, &ppdata, NULL, 0); + err = mtd_device_register(ltq_mtd->mtd, NULL, 0); if (err) { dev_err(&pdev->dev, "failed to add partitions\n"); goto err_destroy; diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index e46b4e9..b782656 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -166,7 +166,6 @@ static int of_flash_probe(struct platform_device *dev) int reg_tuple_size; struct mtd_info **mtd_list = NULL; resource_size_t res_size; - struct mtd_part_parser_data ppdata; bool map_indirect; const char *mtd_name = NULL; @@ -310,13 +309,13 @@ static int of_flash_probe(struct platform_device *dev) if (err) goto err_out; - ppdata.of_node = dp; + mtd_set_of_node(info->cmtd, dp); part_probe_types = of_get_probes(dp); if (!part_probe_types) { err = -ENOMEM; goto err_out; } - mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata, + mtd_device_parse_register(info->cmtd, part_probe_types, NULL, NULL, 0); of_free_probes(part_probe_types); diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 3e02856..0aacf12 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -614,7 +614,6 @@ static int omap2_onenand_probe(struct platform_device *pdev) struct onenand_chip *this; int r; struct resource *res; - struct mtd_part_parser_data ppdata = {}; pdata = dev_get_platdata(&pdev->dev); if (pdata == NULL) { @@ -713,6 +712,7 @@ static int omap2_onenand_probe(struct platform_device *pdev) c->mtd.priv = &c->onenand; c->mtd.dev.parent = &pdev->dev; + mtd_set_of_node(&c->mtd, pdata->of_node); this = &c->onenand; if (c->dma_channel >= 0) { @@ -743,10 +743,8 @@ static int omap2_onenand_probe(struct platform_device *pdev) if ((r = onenand_scan(&c->mtd, 1)) < 0) goto err_release_regulator; - ppdata.of_node = pdata->of_node; - r = mtd_device_parse_register(&c->mtd, NULL, &ppdata, - pdata ? pdata->parts : NULL, - pdata ? pdata->nr_parts : 0); + r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL, + pdata ? pdata->nr_parts : 0); if (r) goto err_release_onenand; -- cgit v1.1 From e270bca531b40cd0a143176eb093d173b9c6f418 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:29 -0700 Subject: mtd: ofpart: drop 'of_node' partition parser data This field is no longer used anywhere, as it is superseded by mtd->dev.of_node. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/ofpart.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 7bf996a..f78d2ae 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -37,11 +37,8 @@ static int parse_ofpart_partitions(struct mtd_info *master, bool dedicated = true; - /* - * of_node can be provided through auxiliary parser data or (preferred) - * by assigning the master device node - */ - mtd_node = data && data->of_node ? data->of_node : mtd_get_of_node(master); + /* Pull of_node from the master device node */ + mtd_node = mtd_get_of_node(master); if (!mtd_node) return 0; @@ -150,11 +147,8 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, } *part; const char *names; - /* - * of_node can be provided through auxiliary parser data or (preferred) - * by assigning the master device node - */ - dp = data && data->of_node ? data->of_node : mtd_get_of_node(master); + /* Pull of_node from the master device node */ + dp = mtd_get_of_node(master); if (!dp) return 0; -- cgit v1.1 From 8361a9b8cb6a9c71b7cf884a87b2532d8367c185 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 20:33:30 -0700 Subject: mtd: physmap_of: assign parent for the concatenated MTD If there is more than one map region for this device, then the concatenated MTD will not have a parent device assigned to it -- only the sub-devices (which are not actually registered with the framework) will have their parents assigned. Let's assign the concatenated device correctly. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/maps/physmap_of.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index b782656..70c4531 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -309,6 +309,7 @@ static int of_flash_probe(struct platform_device *dev) if (err) goto err_out; + info->cmtd->dev.parent = &dev->dev; mtd_set_of_node(info->cmtd, dp); part_probe_types = of_get_probes(dp); if (!part_probe_types) { -- cgit v1.1 From 44ec23c9ecd95d13ec9dd8d0b0dc9e82bd3258ff Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 2 Nov 2015 00:03:38 +0100 Subject: mtd: nand: convert to nand_get_flash_node() Used semantic patch with 'make coccicheck MODE=patch COCCI=script.cocci': ---8<---- virtual patch @@ struct nand_chip c; struct nand_chip *cp; @@ ( -(cp)->flash_node +nand_get_flash_node(cp) | -(c).flash_node +nand_get_flash_node(&c) ) ---8<---- Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.c | 2 +- drivers/mtd/nand/nand_base.c | 6 +++--- drivers/mtd/nand/vf610_nfc.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index a37659d..2a437c7 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -1816,7 +1816,7 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) memset(cfg, 0, sizeof(*cfg)); - ret = of_property_read_u32(chip->flash_node, + ret = of_property_read_u32(nand_get_flash_node(chip), "brcm,nand-oob-sector-size", &oob_sector); if (ret) { diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 939ab3d..4ac4efe 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3989,11 +3989,11 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, struct nand_flash_dev *type; int ret; - if (chip->flash_node) { + if (nand_get_flash_node(chip)) { /* MTD can automatically handle DT partitions, etc. */ - mtd_set_of_node(mtd, chip->flash_node); + mtd_set_of_node(mtd, nand_get_flash_node(chip)); - ret = nand_dt_init(mtd, chip, chip->flash_node); + ret = nand_dt_init(mtd, chip, nand_get_flash_node(chip)); if (ret) return ret; } diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index b6df4c6..1c86c6b 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -707,7 +707,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) for_each_available_child_of_node(nfc->dev->of_node, child) { if (of_device_is_compatible(child, "fsl,vf610-nfc-nandcs")) { - if (chip->flash_node) { + if (nand_get_flash_node(chip)) { dev_err(nfc->dev, "Only one NAND chip supported!\n"); err = -EINVAL; @@ -718,7 +718,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) } } - if (!chip->flash_node) { + if (!nand_get_flash_node(chip)) { dev_err(nfc->dev, "NAND chip sub-node missing!\n"); err = -ENODEV; goto err_clk; @@ -814,7 +814,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) return mtd_device_register(mtd, NULL, 0); error: - of_node_put(chip->flash_node); + of_node_put(nand_get_flash_node(chip)); err_clk: clk_disable_unprepare(nfc->clk); return err; -- cgit v1.1 From 215a02fd30871d0d888d27a3154588b66f5dbec2 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 11 Nov 2015 16:26:04 -0800 Subject: mtd: grab a reference to the MTD of_node before registering it We now stick the device node representing the current MTD (if any) into sysfs, so let's make sure we have a reference to it before doing that. Suggested-by: Boris Brezillon Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/mtdcore.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index a91cee9..c393a11 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -454,6 +455,7 @@ int add_mtd_device(struct mtd_info *mtd) mtd->dev.devt = MTD_DEVT(i); dev_set_name(&mtd->dev, "mtd%d", i); dev_set_drvdata(&mtd->dev, mtd); + of_node_get(mtd_get_of_node(mtd)); error = device_register(&mtd->dev); if (error) goto fail_added; @@ -476,6 +478,7 @@ int add_mtd_device(struct mtd_info *mtd) return 0; fail_added: + of_node_put(mtd_get_of_node(mtd)); idr_remove(&mtd_idr, i); fail_locked: mutex_unlock(&mtd_table_mutex); @@ -517,6 +520,7 @@ int del_mtd_device(struct mtd_info *mtd) device_unregister(&mtd->dev); idr_remove(&mtd_idr, mtd->index); + of_node_put(mtd_get_of_node(mtd)); module_put(THIS_MODULE); ret = 0; -- cgit v1.1 From 938672338991ac8bef5cb025b187ab8d6230ac6c Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 11 Nov 2015 16:47:52 -0800 Subject: mtd: zero out mtd_partition struct before using it It's easier to guarantee we've cleared out all unused fields with memset() than by manually initializing each field. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/mtdpart.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index f8ba153..46dfbf5 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -596,11 +596,10 @@ int mtd_add_partition(struct mtd_info *master, const char *name, if (length <= 0) return -EINVAL; + memset(&part, 0, sizeof(part)); part.name = name; part.size = length; part.offset = offset; - part.mask_flags = 0; - part.ecclayout = NULL; new = allocate_partition(master, &part, -1, offset); if (IS_ERR(new)) -- cgit v1.1 From 96dd922c198286681fbbc15100e196e0f629e2fb Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 11 Nov 2015 15:36:16 -0800 Subject: mtd: jz4740_nand: fix build on jz4740 after removing gpio.h Fallout from commit 832f5dacfa0b ("MIPS: Remove all the uses of custom gpio.h") We see errors like this: drivers/mtd/nand/jz4740_nand.c: In function 'jz_nand_detect_bank': drivers/mtd/nand/jz4740_nand.c:340:9: error: 'JZ_GPIO_MEM_CS0' undeclared (first use in this function) drivers/mtd/nand/jz4740_nand.c:340:9: note: each undeclared identifier is reported only once for each function it appears in drivers/mtd/nand/jz4740_nand.c:359:2: error: implicit declaration of function 'jz_gpio_set_function' [-Werror=implicit-function-declaration] drivers/mtd/nand/jz4740_nand.c:359:29: error: 'JZ_GPIO_FUNC_MEM_CS0' undeclared (first use in this function) drivers/mtd/nand/jz4740_nand.c:399:29: error: 'JZ_GPIO_FUNC_NONE' undeclared (first use in this function) drivers/mtd/nand/jz4740_nand.c: In function 'jz_nand_probe': drivers/mtd/nand/jz4740_nand.c:528:13: error: 'JZ_GPIO_MEM_CS0' undeclared (first use in this function) drivers/mtd/nand/jz4740_nand.c: In function 'jz_nand_remove': drivers/mtd/nand/jz4740_nand.c:555:14: error: 'JZ_GPIO_MEM_CS0' undeclared (first use in this function) Patched similarly to: https://patchwork.linux-mips.org/patch/11089/ Fixes: 832f5dacfa0b ("MIPS: Remove all the uses of custom gpio.h") Signed-off-by: Brian Norris --- drivers/mtd/nand/jz4740_nand.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index dc4e844..5a99a93 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -25,6 +25,7 @@ #include +#include #include #define JZ_REG_NAND_CTRL 0x50 -- cgit v1.1 From 9ca641b0f02a3a1eedbc8c296e695326da9bbaf9 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 9 Nov 2015 16:37:28 -0800 Subject: mtd: nand: fix shutdown/reboot for multi-chip systems If multiple NAND chips are registered to the same controller, then when rebooting the system, the first one will grab the controller lock, while the second will wait forever for the first one to release it. i.e., a classic deadlock. This problem was solved for a similar case (suspend/resume) back in commit 6b0d9a841249 ("mtd: nand: fix multi-chip suspend problem"), and the shutdown state really isn't much different for us, so rather than adding a new special case to nand_get_device(), we can just overload the FL_PM_SUSPENDED state. Now, multiple chips can "get" the same controller lock (preventing further I/O), while we still allow other chips to pass through nand_shutdown(). Original report: http://thread.gmane.org/gmane.linux.drivers.mtd/59726 http://lists.infradead.org/pipermail/linux-mtd/2015-July/059992.html Fixes: 72ea403669c7 ("mtd: nand: added nand_shutdown") Reported-by: Andrew E. Mileski Signed-off-by: Brian Norris Cc: Scott Branden Cc: Andrew E. Mileski Acked-by: Scott Branden Reviewed-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index cc74142..ece544e 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3110,7 +3110,7 @@ static void nand_resume(struct mtd_info *mtd) */ static void nand_shutdown(struct mtd_info *mtd) { - nand_get_device(mtd, FL_SHUTDOWN); + nand_get_device(mtd, FL_PM_SUSPENDED); } /* Set default functions */ -- cgit v1.1 From c7f00c29aa846b00c70bc99ddb6b1cc7e17c47d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 4 Nov 2015 13:13:41 -0300 Subject: mtd: pxa3xx_nand: Increase the initial chunk size The chunk size represents the size of the data chunks, which is used by the controllers that allow to split transfered data. However, the initial chunk size is used in a non-splitted way, during device identification. Therefore, it must be large enough for all the NAND commands issued during device identification. This includes NAND_CMD_PARAM which was recently changed to transfer up to 2048 bytes (for the redundant parameter pages). Thus, the initial chunk size should be 2048 as well. On Armada 370/XP platforms (NFCv2) booted without the keep-config devicetree property, this commit fixes a timeout on the NAND_CMD_PARAM command: [..] pxa3xx-nand f10d0000.nand: This platform can't do DMA on this device pxa3xx-nand f10d0000.nand: Wait time out!!! nand: device found, Manufacturer ID: 0x2c, Chip ID: 0x38 nand: Micron MT29F8G08ABABAWP nand: 1024 MiB, SLC, erase size: 512 KiB, page size: 4096, OOB size: 224 Signed-off-by: Ezequiel Garcia Acked-by: Robert Jarzmik Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 37df51d..d3da5ef 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1592,7 +1592,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) goto KEEP_CONFIG; /* Set a default chunk size */ - info->chunk_size = 512; + info->chunk_size = PAGE_CHUNK_SIZE; ret = pxa3xx_nand_config_flash(info); if (ret) -- cgit v1.1 From 66e8e47eae658dc884e65695a597fdda7a109448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 4 Nov 2015 13:13:42 -0300 Subject: mtd: pxa3xx_nand: Fix initial controller configuration The Data Flash Control Register (NDCR) contains two types of parameters: those that are needed for device identification, and those that can only be set after device identification. Therefore, the driver can't set them all at once and instead needs to configure the first group before nand_scan_ident() and the second group later. Let's split pxa3xx_nand_config in two halves, and set the parameters that depend on the device geometry once this is known. Signed-off-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index d3da5ef..54512ce 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1387,34 +1387,43 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) return NAND_STATUS_READY; } -static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_config_ident(struct pxa3xx_nand_info *info) { struct platform_device *pdev = info->pdev; struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct pxa3xx_nand_host *host = info->host[info->cs]; - struct mtd_info *mtd = host->mtd; - struct nand_chip *chip = mtd->priv; - /* configure default flash values */ + /* Configure default flash values */ + info->chunk_size = PAGE_CHUNK_SIZE; info->reg_ndcr = 0x0; /* enable all interrupts */ info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; info->reg_ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES); - info->reg_ndcr |= NDCR_SPARE_EN; /* enable spare by default */ + info->reg_ndcr |= NDCR_SPARE_EN; + + return 0; +} + +static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info) +{ + struct pxa3xx_nand_host *host = info->host[info->cs]; + struct mtd_info *mtd = host->mtd; + struct nand_chip *chip = mtd->priv; + info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0; info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0; info->reg_ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0; - - return 0; } static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) { + struct platform_device *pdev = info->pdev; + struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); uint32_t ndcr = nand_readl(info, NDCR); /* Set an initial chunk size */ info->chunk_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; info->reg_ndcr = ndcr & ~(NDCR_INT_MASK | NDCR_ND_ARB_EN | NFCV1_NDCR_ARB_CNTL); + info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; info->ndtr0cs0 = nand_readl(info, NDTR0CS0); info->ndtr1cs0 = nand_readl(info, NDTR1CS0); return 0; @@ -1591,10 +1600,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) goto KEEP_CONFIG; - /* Set a default chunk size */ - info->chunk_size = PAGE_CHUNK_SIZE; - - ret = pxa3xx_nand_config_flash(info); + ret = pxa3xx_nand_config_ident(info); if (ret) return ret; @@ -1607,7 +1613,6 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) } KEEP_CONFIG: - info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; if (info->reg_ndcr & NDCR_DWIDTH_M) chip->options |= NAND_BUSWIDTH_16; @@ -1692,6 +1697,10 @@ KEEP_CONFIG: host->row_addr_cycles = 3; else host->row_addr_cycles = 2; + + if (!pdata->keep_config) + pxa3xx_nand_config_tail(info); + return nand_scan_tail(mtd); } -- cgit v1.1 From 154f50fbde539c20bbf74854461d932ebdace4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 4 Nov 2015 13:13:43 -0300 Subject: mtd: pxa3xx_nand: Simplify pxa3xx_nand_scan This commit simplifies the initial configuration performed by pxa3xx_nand_scan. No functionality change is intended. Signed-off-by: Ezequiel Garcia Acked-by: Robert Jarzmik Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 54512ce..002f1cc 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1413,7 +1413,7 @@ static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info) info->reg_ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0; } -static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) +static void pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) { struct platform_device *pdev = info->pdev; struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -1426,7 +1426,6 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; info->ndtr0cs0 = nand_readl(info, NDTR0CS0); info->ndtr1cs0 = nand_readl(info, NDTR1CS0); - return 0; } static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) @@ -1597,22 +1596,21 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) int ret; uint16_t ecc_strength, ecc_step; - if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) - goto KEEP_CONFIG; - - ret = pxa3xx_nand_config_ident(info); - if (ret) - return ret; - - ret = pxa3xx_nand_sensing(host); - if (ret) { - dev_info(&info->pdev->dev, "There is no chip on cs %d!\n", - info->cs); - - return ret; + if (pdata->keep_config) { + pxa3xx_nand_detect_config(info); + } else { + ret = pxa3xx_nand_config_ident(info); + if (ret) + return ret; + ret = pxa3xx_nand_sensing(host); + if (ret) { + dev_info(&info->pdev->dev, + "There is no chip on cs %d!\n", + info->cs); + return ret; + } } -KEEP_CONFIG: if (info->reg_ndcr & NDCR_DWIDTH_M) chip->options |= NAND_BUSWIDTH_16; -- cgit v1.1 From b1e485779c06d3e43a1818f1065874dd2504b5ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 4 Nov 2015 13:13:44 -0300 Subject: mtd: pxa3xx_nand: Remove redundant NAND sensing Currently, the driver is trying to detect the presence of a chip by issuing a RESET command before nand_scan_ident. This seems completely redundant, and is also a layering violation as nand_scan_ident is in charge of device detection. This commit removes the RESET command use, and moves the initial timing configuration to pxa3xx_nand_config_ident. Signed-off-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 002f1cc..bf1b2ac 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1389,8 +1389,10 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) static int pxa3xx_nand_config_ident(struct pxa3xx_nand_info *info) { + struct pxa3xx_nand_host *host = info->host[info->cs]; struct platform_device *pdev = info->pdev; struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); + const struct nand_sdr_timings *timings; /* Configure default flash values */ info->chunk_size = PAGE_CHUNK_SIZE; @@ -1399,6 +1401,12 @@ static int pxa3xx_nand_config_ident(struct pxa3xx_nand_info *info) info->reg_ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES); info->reg_ndcr |= NDCR_SPARE_EN; + /* use the common timing to make a try */ + timings = onfi_async_timing_mode_to_sdr_timings(0); + if (IS_ERR(timings)) + return PTR_ERR(timings); + + pxa3xx_nand_set_sdr_timing(host, timings); return 0; } @@ -1491,32 +1499,6 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) kfree(info->data_buff); } -static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host) -{ - struct pxa3xx_nand_info *info = host->info_data; - struct mtd_info *mtd; - struct nand_chip *chip; - const struct nand_sdr_timings *timings; - int ret; - - mtd = info->host[info->cs]->mtd; - chip = mtd->priv; - - /* use the common timing to make a try */ - timings = onfi_async_timing_mode_to_sdr_timings(0); - if (IS_ERR(timings)) - return PTR_ERR(timings); - - pxa3xx_nand_set_sdr_timing(host, timings); - - chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); - ret = chip->waitfunc(mtd, chip); - if (ret & NAND_STATUS_FAIL) - return -ENODEV; - - return 0; -} - static int pxa_ecc_init(struct pxa3xx_nand_info *info, struct nand_ecc_ctrl *ecc, int strength, int ecc_stepsize, int page_size) @@ -1602,13 +1584,6 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) ret = pxa3xx_nand_config_ident(info); if (ret) return ret; - ret = pxa3xx_nand_sensing(host); - if (ret) { - dev_info(&info->pdev->dev, - "There is no chip on cs %d!\n", - info->cs); - return ret; - } } if (info->reg_ndcr & NDCR_DWIDTH_M) -- cgit v1.1 From f3028c840867d2235886a6a5c97865fc9d91bafd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 4 Nov 2015 13:13:45 -0300 Subject: mtd: pxa3xx_nand: Remove dead code This macro is not used anymore, so it's just dead code. Remove it. Signed-off-by: Ezequiel Garcia Acked-by: Robert Jarzmik Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index bf1b2ac..2f337ea 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -30,11 +30,6 @@ #include #include #include - -#if defined(CONFIG_ARM) && (defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)) -#define ARCH_HAS_DMA -#endif - #include #define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200) -- cgit v1.1 From d55d31a6b8f65bb13e1912043a66295cc928967c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 4 Nov 2015 13:13:46 -0300 Subject: mtd: pxa3xx_nand: Gate/ungate the NAND clock in suspend/resume paths The NAND clock can be disabled on suspend and enabled on resume. Signed-off-by: Ezequiel Garcia Acked-by: Robert Jarzmik Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 2f337ea..2bb9732 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1936,12 +1936,18 @@ static int pxa3xx_nand_suspend(struct device *dev) return -EAGAIN; } + clk_disable(info->clk); return 0; } static int pxa3xx_nand_resume(struct device *dev) { struct pxa3xx_nand_info *info = dev_get_drvdata(dev); + int ret; + + ret = clk_enable(info->clk); + if (ret < 0) + return ret; /* We don't want to handle interrupt without calling mtd routine */ disable_int(info, NDCR_INT_MASK); -- cgit v1.1 From 2b2462d5928379b8f43ffe19d72d069bfb89d316 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 4 Nov 2015 15:21:21 -0500 Subject: mtd: sm_ftl: fix wrong do_div() usage do_div() is meant to be used with an unsigned dividend. Signed-off-by: Nicolas Pitre Signed-off-by: Brian Norris --- drivers/mtd/sm_ftl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index c23184a..b096f8b 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -206,9 +206,10 @@ static loff_t sm_mkoffset(struct sm_ftl *ftl, int zone, int block, int boffset) } /* Breaks offset into parts */ -static void sm_break_offset(struct sm_ftl *ftl, loff_t offset, +static void sm_break_offset(struct sm_ftl *ftl, loff_t loffset, int *zone, int *block, int *boffset) { + u64 offset = loffset; *boffset = do_div(offset, ftl->block_size); *block = do_div(offset, ftl->max_lba); *zone = offset >= ftl->zone_count ? -1 : offset; -- cgit v1.1 From 20625dfe0384676e3ee244091c4f09544d080798 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 30 Oct 2015 12:56:22 -0700 Subject: mtd: spi-nor: remove unnecessary leading space from dbg print As Cyrille noted [1], this line is wrong. [1] http://lists.infradead.org/pipermail/linux-mtd/2015-September/061725.html Signed-off-by: Brian Norris Cc: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 12041e1..16c9f55 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -856,7 +856,7 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); if (tmp < 0) { - dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); + dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp); return ERR_PTR(tmp); } -- cgit v1.1 From 1b15b1f5a01019524815a9ce5c575f3b2068e7f8 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 17 Nov 2015 13:58:50 -0200 Subject: mtd: mxc_nand: Remove bit-or operation with zero Doing a bit-or operation with zero is pointless. Remove this unneeded bit-or. Signed-off-by: Fabio Estevam Signed-off-by: Brian Norris --- drivers/mtd/nand/mxc_nand.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 7922d31..f507d36 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -1067,8 +1067,7 @@ static void preset_v3(struct mtd_info *mtd) /* Blocks to be unlocked */ for (i = 0; i < NAND_MAX_CHIPS; i++) - writel(0x0 | (0xffff << 16), - NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2)); + writel(0xffff << 16, NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2)); writel(0, NFC_V3_IPC); -- cgit v1.1 From c98f71d1c05601cff0f302889933798020e08869 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 16 Nov 2015 10:45:30 -0800 Subject: mtd: fsl-quadspi: possible NULL dereference It is theoretically possible to probe this driver without a matching device tree, so let's guard against this. Also, use the of_device_get_match_data() helper to make this a bit simpler. Coverity complained about this one. Signed-off-by: Brian Norris Acked-by: Han xu --- drivers/mtd/spi-nor/fsl-quadspi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 9e7f657..54640f1 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -269,7 +269,7 @@ struct fsl_qspi { struct clk *clk, *clk_en; struct device *dev; struct completion c; - struct fsl_qspi_devtype_data *devtype_data; + const struct fsl_qspi_devtype_data *devtype_data; u32 nor_size; u32 nor_num; u32 clk_rate; @@ -933,8 +933,6 @@ static int fsl_qspi_probe(struct platform_device *pdev) struct spi_nor *nor; struct mtd_info *mtd; int ret, i = 0; - const struct of_device_id *of_id = - of_match_device(fsl_qspi_dt_ids, &pdev->dev); q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); if (!q) @@ -945,7 +943,9 @@ static int fsl_qspi_probe(struct platform_device *pdev) return -ENODEV; q->dev = dev; - q->devtype_data = (struct fsl_qspi_devtype_data *)of_id->data; + q->devtype_data = of_device_get_match_data(dev); + if (!q->devtype_data) + return -ENODEV; platform_set_drvdata(pdev, q); /* find the resources */ -- cgit v1.1 From d618baf94c62eb63b5b7f6159fb6aee5550a2e10 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 16 Nov 2015 16:56:13 -0800 Subject: mtd: brcmnand: clean up flash cache for parameter pages The read_byte() handling for accessing the flash cache has some awkward swapping being done in the read_byte() function. Let's just make this a byte array, and do the swapping with the word-level macros during the initial buffer copy. This is just a refactoring patch, with no (intended) functional change. Signed-off-by: Brian Norris Cc: Clay McClure Cc: Ray Jui Cc: Scott Branden Cc: Tested-by: Clay McClure --- drivers/mtd/nand/brcmnand/brcmnand.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 2a437c7..0f43bc9 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -134,7 +134,7 @@ struct brcmnand_controller { dma_addr_t dma_pa; /* in-memory cache of the FLASH_CACHE, used only for some commands */ - u32 flash_cache[FC_WORDS]; + u8 flash_cache[FC_BYTES]; /* Controller revision details */ const u16 *reg_offsets; @@ -1188,6 +1188,8 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, if (native_cmd == CMD_PARAMETER_READ || native_cmd == CMD_PARAMETER_CHANGE_COL) { + /* Copy flash cache word-wise */ + u32 *flash_cache = (u32 *)ctrl->flash_cache; int i; brcmnand_soc_data_bus_prepare(ctrl->soc); @@ -1197,7 +1199,11 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, * SECTOR_SIZE_1K may invalidate it */ for (i = 0; i < FC_WORDS; i++) - ctrl->flash_cache[i] = brcmnand_read_fc(ctrl, i); + /* + * Flash cache is big endian for parameter pages, at + * least on STB SoCs + */ + flash_cache[i] = be32_to_cpu(brcmnand_read_fc(ctrl, i)); brcmnand_soc_data_bus_unprepare(ctrl->soc); @@ -1250,8 +1256,7 @@ static uint8_t brcmnand_read_byte(struct mtd_info *mtd) if (host->last_byte > 0 && offs == 0) chip->cmdfunc(mtd, NAND_CMD_RNDOUT, addr, -1); - ret = ctrl->flash_cache[offs >> 2] >> - (24 - ((offs & 0x03) << 3)); + ret = ctrl->flash_cache[offs]; break; case NAND_CMD_GET_FEATURES: if (host->last_byte >= ONFI_SUBFEATURE_PARAM_LEN) { -- cgit v1.1 From 064f462632c2294f9b7fb51a7697392fedeea12e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 16 Nov 2015 17:04:08 -0800 Subject: mtd: brcmnand: drop unused subpage_read() support AFAIR this driver was never tested with subpage read support, and this code is currently unused because we don't set the NAND_SUBPAGE_READ flag. It can be resurrected if someone tests it properly. Signed-off-by: Brian Norris Tested-by: Ray Jui --- drivers/mtd/nand/brcmnand/brcmnand.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 0f43bc9..626a80e 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -1551,16 +1551,6 @@ static int brcmnand_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, return 0; } -static int brcmnand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, - uint32_t data_offs, uint32_t readlen, - uint8_t *bufpoi, int page) -{ - struct brcmnand_host *host = chip->priv; - - return brcmnand_read(mtd, chip, host->last_addr + data_offs, - readlen >> FC_SHIFT, (u32 *)bufpoi, NULL); -} - static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, u64 addr, const u32 *buf, u8 *oob) { @@ -1949,7 +1939,6 @@ static int brcmnand_init_cs(struct brcmnand_host *host) chip->ecc.mode = NAND_ECC_HW; chip->ecc.read_page = brcmnand_read_page; - chip->ecc.read_subpage = brcmnand_read_subpage; chip->ecc.write_page = brcmnand_write_page; chip->ecc.read_page_raw = brcmnand_read_page_raw; chip->ecc.write_page_raw = brcmnand_write_page_raw; -- cgit v1.1 From 1d8d8b5c852b6c7ae860ddc647ebb3ed3493c9a8 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 16 Nov 2015 14:37:34 +0100 Subject: mtd: nand: fix drivers abusing mtd->priv The ->priv field of the mtd_info object attached to a nand_chip device should point to the nand_chip device. The pxa and cafe drivers are assigning this field their own private structure, which works fine as long as the nand_chip field is the first one in the driver private struct but seems a bit fragile. Fix that by setting mtd->priv to point the nand_chip field and assigning chip->priv to the private structure head. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/cafe_nand.c | 34 ++++++++++++++++++++++------------ drivers/mtd/nand/pxa3xx_nand.c | 30 +++++++++++++++++++----------- 2 files changed, 41 insertions(+), 23 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 9de78d2..cce3ac4 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -101,7 +101,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; static int cafe_device_ready(struct mtd_info *mtd) { - struct cafe_priv *cafe = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct cafe_priv *cafe = chip->priv; int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000); uint32_t irqs = cafe_readl(cafe, NAND_IRQ); @@ -117,7 +118,8 @@ static int cafe_device_ready(struct mtd_info *mtd) static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct cafe_priv *cafe = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct cafe_priv *cafe = chip->priv; if (usedma) memcpy(cafe->dmabuf + cafe->datalen, buf, len); @@ -132,7 +134,8 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct cafe_priv *cafe = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct cafe_priv *cafe = chip->priv; if (usedma) memcpy(buf, cafe->dmabuf + cafe->datalen, len); @@ -146,7 +149,8 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static uint8_t cafe_read_byte(struct mtd_info *mtd) { - struct cafe_priv *cafe = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct cafe_priv *cafe = chip->priv; uint8_t d; cafe_read_buf(mtd, &d, 1); @@ -158,7 +162,8 @@ static uint8_t cafe_read_byte(struct mtd_info *mtd) static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct cafe_priv *cafe = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct cafe_priv *cafe = chip->priv; int adrbytes = 0; uint32_t ctl1; uint32_t doneint = 0x80000000; @@ -313,7 +318,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, static void cafe_select_chip(struct mtd_info *mtd, int chipnr) { - struct cafe_priv *cafe = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct cafe_priv *cafe = chip->priv; cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); @@ -328,7 +334,8 @@ static void cafe_select_chip(struct mtd_info *mtd, int chipnr) static irqreturn_t cafe_nand_interrupt(int irq, void *id) { struct mtd_info *mtd = id; - struct cafe_priv *cafe = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct cafe_priv *cafe = chip->priv; uint32_t irqs = cafe_readl(cafe, NAND_IRQ); cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ); if (!irqs) @@ -377,7 +384,7 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct cafe_priv *cafe = mtd->priv; + struct cafe_priv *cafe = chip->priv; unsigned int max_bitflips = 0; cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", @@ -519,7 +526,7 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd, const uint8_t *buf, int oob_required, int page) { - struct cafe_priv *cafe = mtd->priv; + struct cafe_priv *cafe = chip->priv; chip->write_buf(mtd, buf, mtd->writesize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -604,7 +611,8 @@ static int cafe_nand_probe(struct pci_dev *pdev, cafe = (void *)(&mtd[1]); mtd->dev.parent = &pdev->dev; - mtd->priv = cafe; + mtd->priv = &cafe->nand; + cafe->nand.priv = cafe; cafe->pdev = pdev; cafe->mmio = pci_iomap(pdev, 0, 0); @@ -792,7 +800,8 @@ static int cafe_nand_probe(struct pci_dev *pdev, static void cafe_nand_remove(struct pci_dev *pdev) { struct mtd_info *mtd = pci_get_drvdata(pdev); - struct cafe_priv *cafe = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct cafe_priv *cafe = chip->priv; /* Disable NAND IRQ in global IRQ mask register */ cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); @@ -819,7 +828,8 @@ static int cafe_nand_resume(struct pci_dev *pdev) { uint32_t ctrl; struct mtd_info *mtd = pci_get_drvdata(pdev); - struct cafe_priv *cafe = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct cafe_priv *cafe = chip->priv; /* Start off by resetting the NAND controller completely */ cafe_writel(cafe, 1, NAND_RESET); diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 2bb9732..bdbc2c2 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1113,7 +1113,8 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, static void nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct pxa3xx_nand_host *host = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; int exec_cmd; @@ -1161,7 +1162,8 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, const unsigned command, int column, int page_addr) { - struct pxa3xx_nand_host *host = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; int exec_cmd, ext_cmd_type; @@ -1281,7 +1283,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct pxa3xx_nand_host *host = mtd->priv; + struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; chip->read_buf(mtd, buf, mtd->writesize); @@ -1307,7 +1309,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) { - struct pxa3xx_nand_host *host = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; char retval = 0xFF; @@ -1320,7 +1323,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) { - struct pxa3xx_nand_host *host = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; u16 retval = 0xFFFF; @@ -1333,7 +1337,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct pxa3xx_nand_host *host = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; int real_len = min_t(size_t, len, info->buf_count - info->buf_start); @@ -1344,7 +1349,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void pxa3xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct pxa3xx_nand_host *host = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; int real_len = min_t(size_t, len, info->buf_count - info->buf_start); @@ -1359,7 +1365,8 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip) static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { - struct pxa3xx_nand_host *host = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; if (info->need_wait) { @@ -1565,11 +1572,11 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, static int pxa3xx_nand_scan(struct mtd_info *mtd) { - struct pxa3xx_nand_host *host = mtd->priv; + struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; struct platform_device *pdev = info->pdev; struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct nand_chip *chip = mtd->priv; int ret; uint16_t ecc_strength, ecc_step; @@ -1701,11 +1708,12 @@ static int alloc_nand_resource(struct platform_device *pdev) host->mtd = mtd; host->cs = cs; host->info_data = info; - mtd->priv = host; + mtd->priv = chip; mtd->dev.parent = &pdev->dev; /* FIXME: all chips use the same device tree partitions */ nand_set_flash_node(chip, np); + chip->priv = host; chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; chip->controller = &info->controller; -- cgit v1.1 From c67cbb839da9cc2757eabfa128556db6a2baf160 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 10 Nov 2015 12:15:27 -0800 Subject: mtd: spi-nor: provide default erase_sector implementation Some spi-nor drivers perform sector erase by duplicating their write_reg() command. Let's not require that the driver fill this out, and provide a default instead. Tested on m25p80.c and Medatek's MT8173 SPI NOR flash driver. Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/spi-nor.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 16c9f55..a38ec01 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -38,6 +38,7 @@ #define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ) #define SPI_NOR_MAX_ID_LEN 6 +#define SPI_NOR_MAX_ADDR_WIDTH 4 struct flash_info { char *name; @@ -313,6 +314,29 @@ static void spi_nor_unlock_and_unprep(struct spi_nor *nor, enum spi_nor_ops ops) } /* + * Initiate the erasure of a single sector + */ +static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) +{ + u8 buf[SPI_NOR_MAX_ADDR_WIDTH]; + int i; + + if (nor->erase) + return nor->erase(nor, addr); + + /* + * Default implementation, if driver doesn't have a specialized HW + * control + */ + for (i = nor->addr_width - 1; i >= 0; i--) { + buf[i] = addr & 0xff; + addr >>= 8; + } + + return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); +} + +/* * Erase an address range on the nor chip. The address range may extend * one or more erase sectors. Return an error is there is a problem erasing. */ @@ -371,10 +395,9 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) while (len) { write_enable(nor); - if (nor->erase(nor, addr)) { - ret = -EIO; + ret = spi_nor_erase_sector(nor, addr); + if (ret) goto erase_err; - } addr += mtd->erasesize; len -= mtd->erasesize; @@ -1138,7 +1161,7 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) static int spi_nor_check(struct spi_nor *nor) { if (!nor->dev || !nor->read || !nor->write || - !nor->read_reg || !nor->write_reg || !nor->erase) { + !nor->read_reg || !nor->write_reg) { pr_err("spi-nor: please fill all the necessary fields!\n"); return -EINVAL; } @@ -1340,6 +1363,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) nor->addr_width = 3; } + if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) { + dev_err(dev, "address width is too large: %u\n", + nor->addr_width); + return -EINVAL; + } + nor->read_dummy = spi_nor_read_dummy_cycles(nor); dev_info(dev, "%s (%lld Kbytes)\n", info->name, -- cgit v1.1 From cd78ea02dc82eb26be8c2fc1cf05adbf94ea8727 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 10 Nov 2015 12:15:28 -0800 Subject: mtd: m25p80: drop erase() callback Just use the spi-nor default instead. Signed-off-by: Brian Norris --- drivers/mtd/devices/m25p80.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index f002a8f..6077c4a 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -152,22 +152,6 @@ static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len, return 0; } -static int m25p80_erase(struct spi_nor *nor, loff_t offset) -{ - struct m25p *flash = nor->priv; - - dev_dbg(nor->dev, "%dKiB at 0x%08x\n", - flash->spi_nor.mtd.erasesize / 1024, (u32)offset); - - /* Set up command buffer. */ - flash->command[0] = nor->erase_opcode; - m25p_addr2cmd(nor, offset, flash->command); - - spi_write(flash->spi, flash->command, m25p_cmdsz(nor)); - - return 0; -} - /* * board specific setup should have ensured the SPI clock used here * matches what the READ command supports, at least until this driver @@ -193,7 +177,6 @@ static int m25p_probe(struct spi_device *spi) /* install the hooks */ nor->read = m25p80_read; nor->write = m25p80_write; - nor->erase = m25p80_erase; nor->write_reg = m25p80_write_reg; nor->read_reg = m25p80_read_reg; -- cgit v1.1 From 0501f2e5ff28a02295e42fc9e7164a20ef4c30d5 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 5 Nov 2015 10:04:23 +0100 Subject: mtd: spi-nor: mx25l3205d/mx25l6405d: append SECT_4K according datasheet both chips can erase 4kByte sectors individually Signed-off-by: Andreas Fenkart Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/spi-nor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index a38ec01..b7c038c 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -738,9 +738,9 @@ static const struct flash_info spi_nor_ids[] = { { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, - { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, + { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) }, { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, - { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, + { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) }, { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, -- cgit v1.1 From de57732da86288cae9a84bd6ce7cf1d1e21f8329 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 16 Nov 2015 14:34:50 -0800 Subject: mtd: m25p80: fix module autoloading for "jedec, spi-nor" and "spi-nor" Commit 43163022927b ("mtd: m25p80: allow arbitrary OF matching for "jedec,spi-nor"") moved the "jedec,spi-nor" handling from the spi_device_id table to the of_match_table, to better handle matching complex device tree compatible strings. With that patch, device tree support works as expected when m25p80.c is built into the kernel. However, that commit ignored the fact that: (1) (non-DT) platform devices might want to use the "spi-nor" string for matching with this driver, rather than picking an arbitrary one like "m25p80" (2) the core SPI uevent/modalias code doesn't yet support kernel module autoloading via of_match_table strings; so for DT-based devices, it will only report (part of) the first compatible string used Problem (1) has been reported previously, and I forgot to patch it up afterward. Problem (2) was noticed recently here: http://lists.infradead.org/pipermail/linux-mtd/2015-October/062369.html https://lkml.org/lkml/2015/11/12/574 Specifically, this patch fixes m25p80.ko module autoloading for cases like this: flash@xxx { compatible = "jedec,spi-nor"; ... }; because modalias of "spi:spi-nor" (the only module loading info provided by the SPI core for this device) will now be listed as an alias in m25p80.ko. Notably, it does *not* help cases like this: flash@xxx { compatible = "vendor,shiny-new-device", "jedec,spi-nor"; ... }; unless we also list "shiny-new-device" in m25p_ids[]. There has been discussion on future work for this issue here: https://lkml.org/lkml/2015/11/12/574 Cc: Heiner Kallweit Signed-off-by: Brian Norris Reviewed-by: Javier Martinez Canillas --- drivers/mtd/devices/m25p80.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 6077c4a..1275357 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -163,7 +163,7 @@ static int m25p_probe(struct spi_device *spi) struct m25p *flash; struct spi_nor *nor; enum read_mode mode = SPI_NOR_NORMAL; - char *flash_name = NULL; + char *flash_name; int ret; data = dev_get_platdata(&spi->dev); @@ -202,6 +202,8 @@ static int m25p_probe(struct spi_device *spi) */ if (data && data->type) flash_name = data->type; + else if (!strcmp(spi->modalias, "spi-nor")) + flash_name = NULL; /* auto-detect */ else flash_name = spi->modalias; @@ -236,6 +238,13 @@ static int m25p_remove(struct spi_device *spi) */ static const struct spi_device_id m25p_ids[] = { /* + * Allow non-DT platform devices to bind to the "spi-nor" modalias, and + * hack around the fact that the SPI core does not provide uevent + * matching for .of_match_table + */ + {"spi-nor"}, + + /* * Entries not used in DTs that should be safe to drop after replacing * them with "nor-jedec" in platform data. */ -- cgit v1.1 From c1711b297f6e2270c1cb17de512985ef500e0de9 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 16 Nov 2015 14:34:51 -0800 Subject: mtd: m25p80: replace leftover "nor-jedec" with "spi-nor" in comments I overlooked a few comments in commit 8947e396a829 ("Documentation: dt: mtd: replace "nor-jedec" binding with "jedec, spi-nor""). Fix these up now. Suggested-by: Javier Martinez Canillas Signed-off-by: Brian Norris Reviewed-by: Javier Martinez Canillas --- drivers/mtd/devices/m25p80.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 1275357..c9c3b7f 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -246,13 +246,13 @@ static const struct spi_device_id m25p_ids[] = { /* * Entries not used in DTs that should be safe to drop after replacing - * them with "nor-jedec" in platform data. + * them with "spi-nor" in platform data. */ {"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"}, /* - * Entries that were used in DTs without "nor-jedec" fallback and should - * be kept for backward compatibility. + * Entries that were used in DTs without "jedec,spi-nor" fallback and + * should be kept for backward compatibility. */ {"at25df321a"}, {"at25df641"}, {"at26df081a"}, {"mr25h256"}, -- cgit v1.1 From b9eab01125bf3cb6f5fbab1811402d16c9fcf4ec Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 11 Nov 2015 19:13:29 -0800 Subject: mtd: partitions: add module_mtd_part_parser() helper This can help eliminate some boilerplate by generating the module_init() and module_exit() functions, and by automatically assigning the module owner. Signed-off-by: Brian Norris --- drivers/mtd/mtdpart.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 46dfbf5..1fa3ca9 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -703,13 +703,17 @@ static struct mtd_part_parser *get_partition_parser(const char *name) #define put_partition_parser(p) do { module_put((p)->owner); } while (0) -void register_mtd_parser(struct mtd_part_parser *p) +int __register_mtd_parser(struct mtd_part_parser *p, struct module *owner) { + p->owner = owner; + spin_lock(&part_parser_lock); list_add(&p->list, &part_parsers); spin_unlock(&part_parser_lock); + + return 0; } -EXPORT_SYMBOL_GPL(register_mtd_parser); +EXPORT_SYMBOL_GPL(__register_mtd_parser); void deregister_mtd_parser(struct mtd_part_parser *p) { -- cgit v1.1 From b8f70badb8cd7c928f7e076b6143aeb66fe13c8b Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 11 Nov 2015 19:13:30 -0800 Subject: mtd: kill off MTD partition parser boilerplate Most parsers can be handled with our new boilerplate-reducing macro. There are a few that can't be (cmdlineparts and ofpart). Also kill off the owner assignments, since register_mtd_parser() now takes care of that. Signed-off-by: Brian Norris --- drivers/mtd/afs.c | 17 +---------------- drivers/mtd/ar7part.c | 16 +--------------- drivers/mtd/bcm47xxpart.c | 16 +--------------- drivers/mtd/bcm63xxpart.c | 16 +--------------- drivers/mtd/cmdlinepart.c | 1 - drivers/mtd/ofpart.c | 2 -- drivers/mtd/redboot.c | 17 +---------------- 7 files changed, 5 insertions(+), 80 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c index a1eea50..e02dae3 100644 --- a/drivers/mtd/afs.c +++ b/drivers/mtd/afs.c @@ -256,25 +256,10 @@ static int parse_afs_partitions(struct mtd_info *mtd, } static struct mtd_part_parser afs_parser = { - .owner = THIS_MODULE, .parse_fn = parse_afs_partitions, .name = "afs", }; - -static int __init afs_parser_init(void) -{ - register_mtd_parser(&afs_parser); - return 0; -} - -static void __exit afs_parser_exit(void) -{ - deregister_mtd_parser(&afs_parser); -} - -module_init(afs_parser_init); -module_exit(afs_parser_exit); - +module_mtd_part_parser(afs_parser); MODULE_AUTHOR("ARM Ltd"); MODULE_DESCRIPTION("ARM Firmware Suite partition parser"); diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c index 7c9172a..9203b96 100644 --- a/drivers/mtd/ar7part.c +++ b/drivers/mtd/ar7part.c @@ -132,24 +132,10 @@ static int create_mtd_partitions(struct mtd_info *master, } static struct mtd_part_parser ar7_parser = { - .owner = THIS_MODULE, .parse_fn = create_mtd_partitions, .name = "ar7part", }; - -static int __init ar7_parser_init(void) -{ - register_mtd_parser(&ar7_parser); - return 0; -} - -static void __exit ar7_parser_exit(void) -{ - deregister_mtd_parser(&ar7_parser); -} - -module_init(ar7_parser_init); -module_exit(ar7_parser_exit); +module_mtd_part_parser(ar7_parser); MODULE_LICENSE("GPL"); MODULE_AUTHOR( "Felix Fietkau , " diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index c0720c1..92a6dd1 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c @@ -313,24 +313,10 @@ static int bcm47xxpart_parse(struct mtd_info *master, }; static struct mtd_part_parser bcm47xxpart_mtd_parser = { - .owner = THIS_MODULE, .parse_fn = bcm47xxpart_parse, .name = "bcm47xxpart", }; - -static int __init bcm47xxpart_init(void) -{ - register_mtd_parser(&bcm47xxpart_mtd_parser); - return 0; -} - -static void __exit bcm47xxpart_exit(void) -{ - deregister_mtd_parser(&bcm47xxpart_mtd_parser); -} - -module_init(bcm47xxpart_init); -module_exit(bcm47xxpart_exit); +module_mtd_part_parser(bcm47xxpart_mtd_parser); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("MTD partitioning for BCM47XX flash memories"); diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index b2443f7..cf02135 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -214,24 +214,10 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, }; static struct mtd_part_parser bcm63xx_cfe_parser = { - .owner = THIS_MODULE, .parse_fn = bcm63xx_parse_cfe_partitions, .name = "bcm63xxpart", }; - -static int __init bcm63xx_cfe_parser_init(void) -{ - register_mtd_parser(&bcm63xx_cfe_parser); - return 0; -} - -static void __exit bcm63xx_cfe_parser_exit(void) -{ - deregister_mtd_parser(&bcm63xx_cfe_parser); -} - -module_init(bcm63xx_cfe_parser_init); -module_exit(bcm63xx_cfe_parser_exit); +module_mtd_part_parser(bcm63xx_cfe_parser); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Daniel Dickinson "); diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 08f6298..4204898 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -382,7 +382,6 @@ static int __init mtdpart_setup(char *s) __setup("mtdparts=", mtdpart_setup); static struct mtd_part_parser cmdline_parser = { - .owner = THIS_MODULE, .parse_fn = parse_cmdline_partitions, .name = "cmdlinepart", }; diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index f78d2ae..4785381 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -131,7 +131,6 @@ ofpart_none: } static struct mtd_part_parser ofpart_parser = { - .owner = THIS_MODULE, .parse_fn = parse_ofpart_partitions, .name = "ofpart", }; @@ -191,7 +190,6 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, } static struct mtd_part_parser ofoldpart_parser = { - .owner = THIS_MODULE, .parse_fn = parse_ofoldpart_partitions, .name = "ofoldpart", }; diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 5da911e..11c3447 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c @@ -290,28 +290,13 @@ static int parse_redboot_partitions(struct mtd_info *master, } static struct mtd_part_parser redboot_parser = { - .owner = THIS_MODULE, .parse_fn = parse_redboot_partitions, .name = "RedBoot", }; +module_mtd_part_parser(redboot_parser); /* mtd parsers will request the module by parser name */ MODULE_ALIAS("RedBoot"); - -static int __init redboot_parser_init(void) -{ - register_mtd_parser(&redboot_parser); - return 0; -} - -static void __exit redboot_parser_exit(void) -{ - deregister_mtd_parser(&redboot_parser); -} - -module_init(redboot_parser_init); -module_exit(redboot_parser_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse "); MODULE_DESCRIPTION("Parsing code for RedBoot Flash Image System (FIS) tables"); -- cgit v1.1 From 72eaec21b0cf106dbb284cc855aef3df2dcc9cf6 Mon Sep 17 00:00:00 2001 From: LABBE Corentin Date: Fri, 20 Nov 2015 08:45:16 +0100 Subject: mtd: nand: atmel_nand: constify atmel_nand_caps structures All atmel_nand_caps are never modified, consitify them. Signed-off-by: LABBE Corentin Acked-by: Josh Wu Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 6ecc1c1..f4e1f91 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -128,7 +128,7 @@ struct atmel_nand_host { struct atmel_nfc *nfc; - struct atmel_nand_caps *caps; + const struct atmel_nand_caps *caps; bool has_pmecc; u8 pmecc_corr_cap; u16 pmecc_sector_size; @@ -2303,11 +2303,11 @@ static int atmel_nand_remove(struct platform_device *pdev) return 0; } -static struct atmel_nand_caps at91rm9200_caps = { +static const struct atmel_nand_caps at91rm9200_caps = { .pmecc_correct_erase_page = false, }; -static struct atmel_nand_caps sama5d4_caps = { +static const struct atmel_nand_caps sama5d4_caps = { .pmecc_correct_erase_page = true, }; -- cgit v1.1 From 3ce351b5354a206e92ccd2d7f30df9c8b7ae5ed1 Mon Sep 17 00:00:00 2001 From: Bayi Cheng Date: Wed, 18 Nov 2015 11:30:02 +0800 Subject: mtd: mtk-nor: new Mediatek serial flash controller driver Add spi nor flash driver for mediatek controller Signed-off-by: Bayi Cheng Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/Kconfig | 7 + drivers/mtd/spi-nor/Makefile | 1 + drivers/mtd/spi-nor/mtk-quadspi.c | 486 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 494 insertions(+) create mode 100644 drivers/mtd/spi-nor/mtk-quadspi.c (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index 2fe2a7e..0dc9275 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -7,6 +7,13 @@ menuconfig MTD_SPI_NOR if MTD_SPI_NOR +config MTD_MT81xx_NOR + tristate "Mediatek MT81xx SPI NOR flash controller" + help + This enables access to SPI NOR flash, using MT81xx SPI NOR flash + controller. This controller does not support generic SPI BUS, it only + supports SPI NOR Flash. + config MTD_SPI_NOR_USE_4K_SECTORS bool "Use small 4096 B erase sectors" default y diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile index e53333e..0bf3a7f8 100644 --- a/drivers/mtd/spi-nor/Makefile +++ b/drivers/mtd/spi-nor/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o +obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c new file mode 100644 index 0000000..dd269650 --- /dev/null +++ b/drivers/mtd/spi-nor/mtk-quadspi.c @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * Author: Bayi Cheng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MTK_NOR_CMD_REG 0x00 +#define MTK_NOR_CNT_REG 0x04 +#define MTK_NOR_RDSR_REG 0x08 +#define MTK_NOR_RDATA_REG 0x0c +#define MTK_NOR_RADR0_REG 0x10 +#define MTK_NOR_RADR1_REG 0x14 +#define MTK_NOR_RADR2_REG 0x18 +#define MTK_NOR_WDATA_REG 0x1c +#define MTK_NOR_PRGDATA0_REG 0x20 +#define MTK_NOR_PRGDATA1_REG 0x24 +#define MTK_NOR_PRGDATA2_REG 0x28 +#define MTK_NOR_PRGDATA3_REG 0x2c +#define MTK_NOR_PRGDATA4_REG 0x30 +#define MTK_NOR_PRGDATA5_REG 0x34 +#define MTK_NOR_SHREG0_REG 0x38 +#define MTK_NOR_SHREG1_REG 0x3c +#define MTK_NOR_SHREG2_REG 0x40 +#define MTK_NOR_SHREG3_REG 0x44 +#define MTK_NOR_SHREG4_REG 0x48 +#define MTK_NOR_SHREG5_REG 0x4c +#define MTK_NOR_SHREG6_REG 0x50 +#define MTK_NOR_SHREG7_REG 0x54 +#define MTK_NOR_SHREG8_REG 0x58 +#define MTK_NOR_SHREG9_REG 0x5c +#define MTK_NOR_CFG1_REG 0x60 +#define MTK_NOR_CFG2_REG 0x64 +#define MTK_NOR_CFG3_REG 0x68 +#define MTK_NOR_STATUS0_REG 0x70 +#define MTK_NOR_STATUS1_REG 0x74 +#define MTK_NOR_STATUS2_REG 0x78 +#define MTK_NOR_STATUS3_REG 0x7c +#define MTK_NOR_FLHCFG_REG 0x84 +#define MTK_NOR_TIME_REG 0x94 +#define MTK_NOR_PP_DATA_REG 0x98 +#define MTK_NOR_PREBUF_STUS_REG 0x9c +#define MTK_NOR_DELSEL0_REG 0xa0 +#define MTK_NOR_DELSEL1_REG 0xa4 +#define MTK_NOR_INTRSTUS_REG 0xa8 +#define MTK_NOR_INTREN_REG 0xac +#define MTK_NOR_CHKSUM_CTL_REG 0xb8 +#define MTK_NOR_CHKSUM_REG 0xbc +#define MTK_NOR_CMD2_REG 0xc0 +#define MTK_NOR_WRPROT_REG 0xc4 +#define MTK_NOR_RADR3_REG 0xc8 +#define MTK_NOR_DUAL_REG 0xcc +#define MTK_NOR_DELSEL2_REG 0xd0 +#define MTK_NOR_DELSEL3_REG 0xd4 +#define MTK_NOR_DELSEL4_REG 0xd8 + +/* commands for mtk nor controller */ +#define MTK_NOR_READ_CMD 0x0 +#define MTK_NOR_RDSR_CMD 0x2 +#define MTK_NOR_PRG_CMD 0x4 +#define MTK_NOR_WR_CMD 0x10 +#define MTK_NOR_PIO_WR_CMD 0x90 +#define MTK_NOR_WRSR_CMD 0x20 +#define MTK_NOR_PIO_READ_CMD 0x81 +#define MTK_NOR_WR_BUF_ENABLE 0x1 +#define MTK_NOR_WR_BUF_DISABLE 0x0 +#define MTK_NOR_ENABLE_SF_CMD 0x30 +#define MTK_NOR_DUAD_ADDR_EN 0x8 +#define MTK_NOR_QUAD_READ_EN 0x4 +#define MTK_NOR_DUAL_ADDR_EN 0x2 +#define MTK_NOR_DUAL_READ_EN 0x1 +#define MTK_NOR_DUAL_DISABLE 0x0 +#define MTK_NOR_FAST_READ 0x1 + +#define SFLASH_WRBUF_SIZE 128 + +/* Can shift up to 48 bits (6 bytes) of TX/RX */ +#define MTK_NOR_MAX_RX_TX_SHIFT 6 +/* can shift up to 56 bits (7 bytes) transfer by MTK_NOR_PRG_CMD */ +#define MTK_NOR_MAX_SHIFT 7 + +/* Helpers for accessing the program data / shift data registers */ +#define MTK_NOR_PRG_REG(n) (MTK_NOR_PRGDATA0_REG + 4 * (n)) +#define MTK_NOR_SHREG(n) (MTK_NOR_SHREG0_REG + 4 * (n)) + +struct mt8173_nor { + struct spi_nor nor; + struct device *dev; + void __iomem *base; /* nor flash base address */ + struct clk *spi_clk; + struct clk *nor_clk; +}; + +static void mt8173_nor_set_read_mode(struct mt8173_nor *mt8173_nor) +{ + struct spi_nor *nor = &mt8173_nor->nor; + + switch (nor->flash_read) { + case SPI_NOR_FAST: + writeb(nor->read_opcode, mt8173_nor->base + + MTK_NOR_PRGDATA3_REG); + writeb(MTK_NOR_FAST_READ, mt8173_nor->base + + MTK_NOR_CFG1_REG); + break; + case SPI_NOR_DUAL: + writeb(nor->read_opcode, mt8173_nor->base + + MTK_NOR_PRGDATA3_REG); + writeb(MTK_NOR_DUAL_READ_EN, mt8173_nor->base + + MTK_NOR_DUAL_REG); + break; + case SPI_NOR_QUAD: + writeb(nor->read_opcode, mt8173_nor->base + + MTK_NOR_PRGDATA4_REG); + writeb(MTK_NOR_QUAD_READ_EN, mt8173_nor->base + + MTK_NOR_DUAL_REG); + break; + default: + writeb(MTK_NOR_DUAL_DISABLE, mt8173_nor->base + + MTK_NOR_DUAL_REG); + break; + } +} + +static int mt8173_nor_execute_cmd(struct mt8173_nor *mt8173_nor, u8 cmdval) +{ + int reg; + u8 val = cmdval & 0x1f; + + writeb(cmdval, mt8173_nor->base + MTK_NOR_CMD_REG); + return readl_poll_timeout(mt8173_nor->base + MTK_NOR_CMD_REG, reg, + !(reg & val), 100, 10000); +} + +static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op, + u8 *tx, int txlen, u8 *rx, int rxlen) +{ + int len = 1 + txlen + rxlen; + int i, ret, idx; + + if (len > MTK_NOR_MAX_SHIFT) + return -EINVAL; + + writeb(len * 8, mt8173_nor->base + MTK_NOR_CNT_REG); + + /* start at PRGDATA5, go down to PRGDATA0 */ + idx = MTK_NOR_MAX_RX_TX_SHIFT - 1; + + /* opcode */ + writeb(op, mt8173_nor->base + MTK_NOR_PRG_REG(idx)); + idx--; + + /* program TX data */ + for (i = 0; i < txlen; i++, idx--) + writeb(tx[i], mt8173_nor->base + MTK_NOR_PRG_REG(idx)); + + /* clear out rest of TX registers */ + while (idx >= 0) { + writeb(0, mt8173_nor->base + MTK_NOR_PRG_REG(idx)); + idx--; + } + + ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PRG_CMD); + if (ret) + return ret; + + /* restart at first RX byte */ + idx = rxlen - 1; + + /* read out RX data */ + for (i = 0; i < rxlen; i++, idx--) + rx[i] = readb(mt8173_nor->base + MTK_NOR_SHREG(idx)); + + return 0; +} + +/* Do a WRSR (Write Status Register) command */ +static int mt8173_nor_wr_sr(struct mt8173_nor *mt8173_nor, u8 sr) +{ + writeb(sr, mt8173_nor->base + MTK_NOR_PRGDATA5_REG); + writeb(8, mt8173_nor->base + MTK_NOR_CNT_REG); + return mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_WRSR_CMD); +} + +static int mt8173_nor_write_buffer_enable(struct mt8173_nor *mt8173_nor) +{ + u8 reg; + + /* the bit0 of MTK_NOR_CFG2_REG is pre-fetch buffer + * 0: pre-fetch buffer use for read + * 1: pre-fetch buffer use for page program + */ + writel(MTK_NOR_WR_BUF_ENABLE, mt8173_nor->base + MTK_NOR_CFG2_REG); + return readb_poll_timeout(mt8173_nor->base + MTK_NOR_CFG2_REG, reg, + 0x01 == (reg & 0x01), 100, 10000); +} + +static int mt8173_nor_write_buffer_disable(struct mt8173_nor *mt8173_nor) +{ + u8 reg; + + writel(MTK_NOR_WR_BUF_DISABLE, mt8173_nor->base + MTK_NOR_CFG2_REG); + return readb_poll_timeout(mt8173_nor->base + MTK_NOR_CFG2_REG, reg, + MTK_NOR_WR_BUF_DISABLE == (reg & 0x1), 100, + 10000); +} + +static void mt8173_nor_set_addr(struct mt8173_nor *mt8173_nor, u32 addr) +{ + int i; + + for (i = 0; i < 3; i++) { + writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR0_REG + i * 4); + addr >>= 8; + } + /* Last register is non-contiguous */ + writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR3_REG); +} + +static int mt8173_nor_read(struct spi_nor *nor, loff_t from, size_t length, + size_t *retlen, u_char *buffer) +{ + int i, ret; + int addr = (int)from; + u8 *buf = (u8 *)buffer; + struct mt8173_nor *mt8173_nor = nor->priv; + + /* set mode for fast read mode ,dual mode or quad mode */ + mt8173_nor_set_read_mode(mt8173_nor); + mt8173_nor_set_addr(mt8173_nor, addr); + + for (i = 0; i < length; i++, (*retlen)++) { + ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PIO_READ_CMD); + if (ret < 0) + return ret; + buf[i] = readb(mt8173_nor->base + MTK_NOR_RDATA_REG); + } + return 0; +} + +static int mt8173_nor_write_single_byte(struct mt8173_nor *mt8173_nor, + int addr, int length, u8 *data) +{ + int i, ret; + + mt8173_nor_set_addr(mt8173_nor, addr); + + for (i = 0; i < length; i++) { + ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PIO_WR_CMD); + if (ret < 0) + return ret; + writeb(*data++, mt8173_nor->base + MTK_NOR_WDATA_REG); + } + return 0; +} + +static int mt8173_nor_write_buffer(struct mt8173_nor *mt8173_nor, int addr, + const u8 *buf) +{ + int i, bufidx, data; + + mt8173_nor_set_addr(mt8173_nor, addr); + + bufidx = 0; + for (i = 0; i < SFLASH_WRBUF_SIZE; i += 4) { + data = buf[bufidx + 3]<<24 | buf[bufidx + 2]<<16 | + buf[bufidx + 1]<<8 | buf[bufidx]; + bufidx += 4; + writel(data, mt8173_nor->base + MTK_NOR_PP_DATA_REG); + } + return mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_WR_CMD); +} + +static void mt8173_nor_write(struct spi_nor *nor, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + int ret; + struct mt8173_nor *mt8173_nor = nor->priv; + + ret = mt8173_nor_write_buffer_enable(mt8173_nor); + if (ret < 0) + dev_warn(mt8173_nor->dev, "write buffer enable failed!\n"); + + while (len >= SFLASH_WRBUF_SIZE) { + ret = mt8173_nor_write_buffer(mt8173_nor, to, buf); + if (ret < 0) + dev_err(mt8173_nor->dev, "write buffer failed!\n"); + len -= SFLASH_WRBUF_SIZE; + to += SFLASH_WRBUF_SIZE; + buf += SFLASH_WRBUF_SIZE; + (*retlen) += SFLASH_WRBUF_SIZE; + } + ret = mt8173_nor_write_buffer_disable(mt8173_nor); + if (ret < 0) + dev_warn(mt8173_nor->dev, "write buffer disable failed!\n"); + + if (len) { + ret = mt8173_nor_write_single_byte(mt8173_nor, to, (int)len, + (u8 *)buf); + if (ret < 0) + dev_err(mt8173_nor->dev, "write single byte failed!\n"); + (*retlen) += len; + } +} + +static int mt8173_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) +{ + int ret; + struct mt8173_nor *mt8173_nor = nor->priv; + + switch (opcode) { + case SPINOR_OP_RDSR: + ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_RDSR_CMD); + if (ret < 0) + return ret; + if (len == 1) + *buf = readb(mt8173_nor->base + MTK_NOR_RDSR_REG); + else + dev_err(mt8173_nor->dev, "len should be 1 for read status!\n"); + break; + default: + ret = mt8173_nor_do_tx_rx(mt8173_nor, opcode, NULL, 0, buf, len); + break; + } + return ret; +} + +static int mt8173_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, + int len) +{ + int ret; + struct mt8173_nor *mt8173_nor = nor->priv; + + switch (opcode) { + case SPINOR_OP_WRSR: + /* We only handle 1 byte */ + ret = mt8173_nor_wr_sr(mt8173_nor, *buf); + break; + default: + ret = mt8173_nor_do_tx_rx(mt8173_nor, opcode, buf, len, NULL, 0); + if (ret) + dev_warn(mt8173_nor->dev, "write reg failure!\n"); + break; + } + return ret; +} + +static int __init mtk_nor_init(struct mt8173_nor *mt8173_nor, + struct device_node *flash_node) +{ + int ret; + struct spi_nor *nor; + + /* initialize controller to accept commands */ + writel(MTK_NOR_ENABLE_SF_CMD, mt8173_nor->base + MTK_NOR_WRPROT_REG); + + nor = &mt8173_nor->nor; + nor->dev = mt8173_nor->dev; + nor->priv = mt8173_nor; + spi_nor_set_flash_node(nor, flash_node); + + /* fill the hooks to spi nor */ + nor->read = mt8173_nor_read; + nor->read_reg = mt8173_nor_read_reg; + nor->write = mt8173_nor_write; + nor->write_reg = mt8173_nor_write_reg; + nor->mtd.owner = THIS_MODULE; + nor->mtd.name = "mtk_nor"; + /* initialized with NULL */ + ret = spi_nor_scan(nor, NULL, SPI_NOR_DUAL); + if (ret) + return ret; + + return mtd_device_register(&nor->mtd, NULL, 0); +} + +static int mtk_nor_drv_probe(struct platform_device *pdev) +{ + struct device_node *flash_np; + struct resource *res; + int ret; + struct mt8173_nor *mt8173_nor; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "No DT found\n"); + return -EINVAL; + } + + mt8173_nor = devm_kzalloc(&pdev->dev, sizeof(*mt8173_nor), GFP_KERNEL); + if (!mt8173_nor) + return -ENOMEM; + platform_set_drvdata(pdev, mt8173_nor); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mt8173_nor->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mt8173_nor->base)) + return PTR_ERR(mt8173_nor->base); + + mt8173_nor->spi_clk = devm_clk_get(&pdev->dev, "spi"); + if (IS_ERR(mt8173_nor->spi_clk)) + return PTR_ERR(mt8173_nor->spi_clk); + + mt8173_nor->nor_clk = devm_clk_get(&pdev->dev, "sf"); + if (IS_ERR(mt8173_nor->nor_clk)) + return PTR_ERR(mt8173_nor->nor_clk); + + mt8173_nor->dev = &pdev->dev; + ret = clk_prepare_enable(mt8173_nor->spi_clk); + if (ret) + return ret; + + ret = clk_prepare_enable(mt8173_nor->nor_clk); + if (ret) { + clk_disable_unprepare(mt8173_nor->spi_clk); + return ret; + } + /* only support one attached flash */ + flash_np = of_get_next_available_child(pdev->dev.of_node, NULL); + if (!flash_np) { + dev_err(&pdev->dev, "no SPI flash device to configure\n"); + ret = -ENODEV; + goto nor_free; + } + ret = mtk_nor_init(mt8173_nor, flash_np); + +nor_free: + if (ret) { + clk_disable_unprepare(mt8173_nor->spi_clk); + clk_disable_unprepare(mt8173_nor->nor_clk); + } + return ret; +} + +static int mtk_nor_drv_remove(struct platform_device *pdev) +{ + struct mt8173_nor *mt8173_nor = platform_get_drvdata(pdev); + + clk_disable_unprepare(mt8173_nor->spi_clk); + clk_disable_unprepare(mt8173_nor->nor_clk); + return 0; +} + +static const struct of_device_id mtk_nor_of_ids[] = { + { .compatible = "mediatek,mt8173-nor"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mtk_nor_of_ids); + +static struct platform_driver mtk_nor_driver = { + .probe = mtk_nor_drv_probe, + .remove = mtk_nor_drv_remove, + .driver = { + .name = "mtk-nor", + .of_match_table = mtk_nor_of_ids, + }, +}; + +module_platform_driver(mtk_nor_driver); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MediaTek SPI NOR Flash Driver"); -- cgit v1.1 From f5f92b36fbbb8ac7d70ff5fa39ec2637cce3094c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 23 Nov 2015 14:39:33 +0100 Subject: mtd: cfi: enforce valid geometry configuration MTD allows compile-time configuration of the possible CFI geometry settings that are allowed by the kernel, but that includes a couple of invalid configurations, where no bank width or no interleave setting is allowed. These are then caught with a compile-time warning: include/linux/mtd/cfi.h:76:2: warning: #warning No CONFIG_MTD_CFI_Ix selected. No NOR chip support can work. include/linux/mtd/map.h:145:2: warning: #warning "No CONFIG_MTD_MAP_BANK_WIDTH_xx selected. No NOR chip support can work" This is a bit annoying for randconfig tests, and can be avoided if we change the Kconfig logic to always select the simplest configuration when no other one is enabled. Signed-off-by: Arnd Bergmann Signed-off-by: Brian Norris --- drivers/mtd/chips/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 54479c4..3b3dabc 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig @@ -67,6 +67,10 @@ endchoice config MTD_CFI_GEOMETRY bool "Specific CFI Flash geometry selection" depends on MTD_CFI_ADV_OPTIONS + select MTD_MAP_BANK_WIDTH_1 if !(MTD_MAP_BANK_WIDTH_2 || \ + MTD_MAP_BANK_WIDTH_4 || MTD_MAP_BANK_WIDTH_8 || \ + MTD_MAP_BANK_WIDTH_16 || MTD_MAP_BANK_WIDTH_32) + select MTD_CFI_I1 if !(MTD_CFI_I2 || MTD_CFI_I4 || MTD_CFI_I8) help This option does not affect the code directly, but will enable some other configuration options which would allow you to reduce -- cgit v1.1 From 0401669797488feb055521cade69b1d0e81669db Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Mon, 16 Nov 2015 22:05:39 +0000 Subject: brcmnand: Clear EXT_ADDR error registers in PIO mode If an error occurs in flash above 4GB in PIO mode then the EXT_ADDR registers will be set to the location of the error and never cleared. Reset them to 0 before reading. Signed-off-by: Simon Arlott Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 626a80e..8feee1e 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -1405,6 +1405,8 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, /* Clear error addresses */ brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0); brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0); + brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0); + brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0); brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS, (host->cs << 16) | ((addr >> 32) & 0xffff)); -- cgit v1.1 From 081976bcc0cbc84f5164fb7aa0e5cf597df6de9e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 19 Nov 2015 22:32:15 +0100 Subject: mtd: brcmnand: improve memory management This patch addresses two related memory management issues in the probe function: 1. for_each_available_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root,e; local idexpression child; @@ for_each_available_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // 2. The devm_kzalloc'd data is not used if brcmnand_init_cs fails. Free it immediately, using devm_kfree in this case, instead of waiting for the remove function. Signed-off-by: Julia Lawall Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 8feee1e..ad756f6 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -2233,15 +2233,19 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) struct brcmnand_host *host; host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); - if (!host) + if (!host) { + of_node_put(child); return -ENOMEM; + } host->pdev = pdev; host->ctrl = ctrl; host->of_node = child; ret = brcmnand_init_cs(host); - if (ret) + if (ret) { + devm_kfree(dev, host); continue; /* Try all chip-selects */ + } list_add_tail(&host->node, &ctrl->host_list); } -- cgit v1.1 From a81c0f07b4a7559eecebf77bcc1956d9d777b006 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 18 Nov 2015 23:04:12 +0100 Subject: mtd: nand: sunxi: add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root,e; local idexpression child; @@ for_each_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // Signed-off-by: Julia Lawall Acked-by: Chen-Yu Tsai Acked-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/sunxi_nand.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 2ed52e4..1bbcc0c 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1391,8 +1391,10 @@ static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc) for_each_child_of_node(np, nand_np) { ret = sunxi_nand_chip_init(dev, nfc, nand_np); - if (ret) + if (ret) { + of_node_put(nand_np); return ret; + } } return 0; -- cgit v1.1 From 9b9f1033da9166617c4a5cadfc12b23b465fb596 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Mon, 30 Nov 2015 20:41:17 +0100 Subject: mtd: spi-nor: Fix error message with unrecognized JEDEC The error message was: m25p80 spi32766.0: unrecognized JEDEC id bytes: 00, 0, 0 The new error message: m25p80 spi32766.0: unrecognized JEDEC id bytes: 00, 00, 00 Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/spi-nor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index b7c038c..f8a9b77 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -890,7 +890,7 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) return &spi_nor_ids[tmp]; } } - dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %2x, %2x\n", + dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", id[0], id[1], id[2]); return ERR_PTR(-ENODEV); } -- cgit v1.1 From d121b66d25adfa8b631dc59511ebc1d600ad5111 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 30 Nov 2015 18:01:27 -0800 Subject: mtd: brcmnand: drop brcmnand_host::of_node field We don't actually need to stash a copy of this device_node indefinitely; we only need it in brcmnand_init_cs(). Signed-off-by: Brian Norris Cc: Cc: Kamal Dasu Acked-by: Scott Branden Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index ad756f6..35d78f7 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -176,7 +176,6 @@ struct brcmnand_cfg { struct brcmnand_host { struct list_head node; - struct device_node *of_node; struct nand_chip chip; struct mtd_info mtd; @@ -1902,10 +1901,9 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) return 0; } -static int brcmnand_init_cs(struct brcmnand_host *host) +static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) { struct brcmnand_controller *ctrl = host->ctrl; - struct device_node *dn = host->of_node; struct platform_device *pdev = host->pdev; struct mtd_info *mtd; struct nand_chip *chip; @@ -2239,9 +2237,8 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) } host->pdev = pdev; host->ctrl = ctrl; - host->of_node = child; - ret = brcmnand_init_cs(host); + ret = brcmnand_init_cs(host, child); if (ret) { devm_kfree(dev, host); continue; /* Try all chip-selects */ -- cgit v1.1 From 8c62b4e118cfa7a3c906c01d4ba2c78a5bd97531 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 3 Dec 2015 14:26:52 -0800 Subject: mtd: ofpart: don't complain about missing 'partitions' node too loudly The ofpart partition parser might be run on DT-enabled systems that don't have any "ofpart" partition subnodes at all, since "ofpart" is in the default parser list. So don't complain loudly on every boot. Example: using m25p80.c with no intent to use ofpart: &spi2 { status = "okay"; flash@0 { compatible = "jedec,spi-nor"; reg = <0>; }; }; I see this warning: [ 0.588471] m25p80 spi2.0: gd25q32 (4096 Kbytes) [ 0.593091] spi2.0: 'partitions' subnode not found on /spi@ff130000/flash@0. Trying to parse direct subnodes as partitions. Cc: Michal Suchanek Signed-off-by: Brian Norris --- drivers/mtd/ofpart.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 669c345..3e9c585 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -46,8 +46,13 @@ static int parse_ofpart_partitions(struct mtd_info *master, ofpart_node = of_get_child_by_name(mtd_node, "partitions"); if (!ofpart_node) { - pr_warn("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n", - master->name, mtd_node->full_name); + /* + * We might get here even when ofpart isn't used at all (e.g., + * when using another parser), so don't be louder than + * KERN_DEBUG + */ + pr_debug("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n", + master->name, mtd_node->full_name); ofpart_node = mtd_node; dedicated = false; } -- cgit v1.1 From 2524534dbb2372a666f30e0da2f97cd7f0d7f76c Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 19 Nov 2015 19:28:39 -0800 Subject: mtd: partitions: turn PART() macro into inline function We can guard against reorganization of struct mtd_part by using container_of(). We can also make sure we're using the right pointer types by making this a static inline function instead of a macro. Signed-off-by: Brian Norris --- drivers/mtd/mtdpart.c | 63 +++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 30 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 1fa3ca9..c32b127 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -48,9 +48,12 @@ struct mtd_part { /* * Given a pointer to the MTD object in the mtd_part structure, we can retrieve - * the pointer to that structure with this macro. + * the pointer to that structure. */ -#define PART(x) ((struct mtd_part *)(x)) +static inline struct mtd_part *mtd_to_part(const struct mtd_info *mtd) +{ + return container_of(mtd, struct mtd_part, mtd); +} /* @@ -61,7 +64,7 @@ struct mtd_part { static int part_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); struct mtd_ecc_stats stats; int res; @@ -80,7 +83,7 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len, static int part_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, void **virt, resource_size_t *phys) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_point(part->master, from + part->offset, len, retlen, virt, phys); @@ -88,7 +91,7 @@ static int part_point(struct mtd_info *mtd, loff_t from, size_t len, static int part_unpoint(struct mtd_info *mtd, loff_t from, size_t len) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_unpoint(part->master, from + part->offset, len); } @@ -98,7 +101,7 @@ static unsigned long part_get_unmapped_area(struct mtd_info *mtd, unsigned long offset, unsigned long flags) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); offset += part->offset; return part->master->_get_unmapped_area(part->master, len, offset, @@ -108,7 +111,7 @@ static unsigned long part_get_unmapped_area(struct mtd_info *mtd, static int part_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); int res; if (from >= mtd->size) @@ -146,7 +149,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from, static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_read_user_prot_reg(part->master, from, len, retlen, buf); } @@ -154,7 +157,7 @@ static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from, static int part_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, struct otp_info *buf) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_get_user_prot_info(part->master, len, retlen, buf); } @@ -162,7 +165,7 @@ static int part_get_user_prot_info(struct mtd_info *mtd, size_t len, static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_read_fact_prot_reg(part->master, from, len, retlen, buf); } @@ -170,7 +173,7 @@ static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, static int part_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, struct otp_info *buf) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_get_fact_prot_info(part->master, len, retlen, buf); } @@ -178,7 +181,7 @@ static int part_get_fact_prot_info(struct mtd_info *mtd, size_t len, static int part_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_write(part->master, to + part->offset, len, retlen, buf); } @@ -186,7 +189,7 @@ static int part_write(struct mtd_info *mtd, loff_t to, size_t len, static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_panic_write(part->master, to + part->offset, len, retlen, buf); } @@ -194,7 +197,7 @@ static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len, static int part_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); if (to >= mtd->size) return -EINVAL; @@ -206,7 +209,7 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to, static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_write_user_prot_reg(part->master, from, len, retlen, buf); } @@ -214,21 +217,21 @@ static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from, static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_lock_user_prot_reg(part->master, from, len); } static int part_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_writev(part->master, vecs, count, to + part->offset, retlen); } static int part_erase(struct mtd_info *mtd, struct erase_info *instr) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); int ret; instr->addr += part->offset; @@ -244,7 +247,7 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr) void mtd_erase_callback(struct erase_info *instr) { if (instr->mtd->_erase == part_erase) { - struct mtd_part *part = PART(instr->mtd); + struct mtd_part *part = mtd_to_part(instr->mtd); if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) instr->fail_addr -= part->offset; @@ -257,57 +260,57 @@ EXPORT_SYMBOL_GPL(mtd_erase_callback); static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_lock(part->master, ofs + part->offset, len); } static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_unlock(part->master, ofs + part->offset, len); } static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_is_locked(part->master, ofs + part->offset, len); } static void part_sync(struct mtd_info *mtd) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); part->master->_sync(part->master); } static int part_suspend(struct mtd_info *mtd) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return part->master->_suspend(part->master); } static void part_resume(struct mtd_info *mtd) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); part->master->_resume(part->master); } static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); ofs += part->offset; return part->master->_block_isreserved(part->master, ofs); } static int part_block_isbad(struct mtd_info *mtd, loff_t ofs) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); ofs += part->offset; return part->master->_block_isbad(part->master, ofs); } static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) { - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); int res; ofs += part->offset; @@ -558,7 +561,7 @@ static ssize_t mtd_partition_offset_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - struct mtd_part *part = PART(mtd); + struct mtd_part *part = mtd_to_part(mtd); return snprintf(buf, PAGE_SIZE, "%lld\n", part->offset); } @@ -814,6 +817,6 @@ uint64_t mtd_get_device_size(const struct mtd_info *mtd) if (!mtd_is_partition(mtd)) return mtd->size; - return PART(mtd)->master->size; + return mtd_to_part(mtd)->master->size; } EXPORT_SYMBOL_GPL(mtd_get_device_size); -- cgit v1.1 From 0f6d3f4097d2746925986af5e34b864c5f6b2682 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 20 Nov 2015 17:38:33 -0800 Subject: mtd: mtk-quadspi: drop unnecessary .owner assignment As of commit 807f16d4db95 ("mtd: core: set some defaults when dev.parent is set"), the MTD core will set this for us. Signed-off-by: Brian Norris Cc: Bayi Cheng --- drivers/mtd/spi-nor/mtk-quadspi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c index dd269650..e1dd9fd 100644 --- a/drivers/mtd/spi-nor/mtk-quadspi.c +++ b/drivers/mtd/spi-nor/mtk-quadspi.c @@ -390,7 +390,6 @@ static int __init mtk_nor_init(struct mt8173_nor *mt8173_nor, nor->read_reg = mt8173_nor_read_reg; nor->write = mt8173_nor_write; nor->write_reg = mt8173_nor_write_reg; - nor->mtd.owner = THIS_MODULE; nor->mtd.name = "mtk_nor"; /* initialized with NULL */ ret = spi_nor_scan(nor, NULL, SPI_NOR_DUAL); -- cgit v1.1 From d6af26944a02e6d325b82160d52e08dc4e315396 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 17 Nov 2015 20:18:54 +0100 Subject: mtd: spi-nor: fix error handling in spi_nor_erase The documenting comment of mtd_erase in mtdcore.c states: Device drivers are supposed to call instr->callback() whenever the operation completes, even if it completes with a failure. Currently the callback isn't called in case of failure. Fix this. Signed-off-by: Heiner Kallweit Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/spi-nor.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index f8a9b77..3b2460e 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -410,17 +410,13 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) write_disable(nor); +erase_err: spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); - instr->state = MTD_ERASE_DONE; + instr->state = ret ? MTD_ERASE_FAILED : MTD_ERASE_DONE; mtd_erase_callback(instr); return ret; - -erase_err: - spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); - instr->state = MTD_ERASE_FAILED; - return ret; } static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, -- cgit v1.1 From 41849d49d7d5307d7399314b59fb16d1c39ce0f0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 21 Nov 2015 12:14:44 +0100 Subject: mtd: nand: r852: Remove unnecessary synchronize_irq() before free_irq() Calling synchronize_irq() right before free_irq() is quite useless. On one hand the IRQ can easily fire again before free_irq() is entered, on the other hand free_irq() itself calls synchronize_irq() internally (in a race condition free way), before any state associated with the IRQ is freed. Patch was generated using the following semantic patch: // @@ expression irq; @@ -synchronize_irq(irq); free_irq(irq, ...); // Signed-off-by: Lars-Peter Clausen Signed-off-by: Brian Norris --- drivers/mtd/nand/r852.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index d8bb2be..be28cdd 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -980,7 +980,6 @@ static void r852_remove(struct pci_dev *pci_dev) /* Stop interrupts */ r852_disable_irqs(dev); - synchronize_irq(dev->irq); free_irq(dev->irq, dev); /* Cleanup */ -- cgit v1.1 From 862eba519e79c48fb6ee276081ddb98fe6926f02 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Tue, 1 Dec 2015 12:03:03 +0100 Subject: mtd: nand: make use of mtd_to_nand() in NAND core code mtd_to_nand() was recently introduced to avoid direct access to the mtd->priv field. Update core code to use mtd_to_nand(). Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 84 ++++++++++++++++++++++---------------------- drivers/mtd/nand/nand_bbt.c | 32 ++++++++--------- drivers/mtd/nand/nand_bch.c | 4 +-- drivers/mtd/nand/nand_ecc.c | 4 +-- drivers/mtd/nand/nandsim.c | 18 +++++----- 5 files changed, 71 insertions(+), 71 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 0748a13..5aec154 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -106,7 +106,7 @@ DEFINE_LED_TRIGGER(nand_led_trigger); static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int ret = 0; /* Start address must align on block boundary */ @@ -132,7 +132,7 @@ static int check_offs_len(struct mtd_info *mtd, */ static void nand_release_device(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); /* Release the controller and the chip */ spin_lock(&chip->controller->lock); @@ -150,7 +150,7 @@ static void nand_release_device(struct mtd_info *mtd) */ static uint8_t nand_read_byte(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); return readb(chip->IO_ADDR_R); } @@ -163,7 +163,7 @@ static uint8_t nand_read_byte(struct mtd_info *mtd) */ static uint8_t nand_read_byte16(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R)); } @@ -175,7 +175,7 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd) */ static u16 nand_read_word(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); return readw(chip->IO_ADDR_R); } @@ -188,7 +188,7 @@ static u16 nand_read_word(struct mtd_info *mtd) */ static void nand_select_chip(struct mtd_info *mtd, int chipnr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); switch (chipnr) { case -1: @@ -211,7 +211,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr) */ static void nand_write_byte(struct mtd_info *mtd, uint8_t byte) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); chip->write_buf(mtd, &byte, 1); } @@ -225,7 +225,7 @@ static void nand_write_byte(struct mtd_info *mtd, uint8_t byte) */ static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); uint16_t word = byte; /* @@ -257,7 +257,7 @@ static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte) */ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); iowrite8_rep(chip->IO_ADDR_W, buf, len); } @@ -272,7 +272,7 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) */ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); ioread8_rep(chip->IO_ADDR_R, buf, len); } @@ -287,7 +287,7 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) */ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); u16 *p = (u16 *) buf; iowrite16_rep(chip->IO_ADDR_W, p, len >> 1); @@ -303,7 +303,7 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) */ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); u16 *p = (u16 *) buf; ioread16_rep(chip->IO_ADDR_R, p, len >> 1); @@ -320,7 +320,7 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) { int page, chipnr, res = 0, i = 0; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); u16 bad; if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) @@ -380,7 +380,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) */ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mtd_oob_ops ops; uint8_t buf[2] = { 0, 0 }; int ret = 0, res, i = 0; @@ -430,7 +430,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) */ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int res, ret = 0; if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) { @@ -471,7 +471,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) */ static int nand_check_wp(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); /* Broken xD cards report WP despite being writable */ if (chip->options & NAND_BROKEN_XD) @@ -491,7 +491,7 @@ static int nand_check_wp(struct mtd_info *mtd) */ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if (!chip->bbt) return 0; @@ -512,7 +512,7 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs) static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if (!chip->bbt) return chip->block_bad(mtd, ofs, getchip); @@ -531,7 +531,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, */ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int i; /* Wait for the device to get ready */ @@ -551,7 +551,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) */ void nand_wait_ready(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); unsigned long timeo = 400; if (in_interrupt() || oops_in_progress) @@ -582,7 +582,7 @@ EXPORT_SYMBOL_GPL(nand_wait_ready); */ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo) { - register struct nand_chip *chip = mtd->priv; + register struct nand_chip *chip = mtd_to_nand(mtd); timeo = jiffies + msecs_to_jiffies(timeo); do { @@ -605,7 +605,7 @@ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo) static void nand_command(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { - register struct nand_chip *chip = mtd->priv; + register struct nand_chip *chip = mtd_to_nand(mtd); int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE; /* Write out the command to the device */ @@ -708,7 +708,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, static void nand_command_lp(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { - register struct nand_chip *chip = mtd->priv; + register struct nand_chip *chip = mtd_to_nand(mtd); /* Emulate NAND_CMD_READOOB */ if (command == NAND_CMD_READOOB) { @@ -832,7 +832,7 @@ static void panic_nand_get_device(struct nand_chip *chip, static int nand_get_device(struct mtd_info *mtd, int new_state) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); spinlock_t *lock = &chip->controller->lock; wait_queue_head_t *wq = &chip->controller->wq; DECLARE_WAITQUEUE(wait, current); @@ -952,7 +952,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, { int ret = 0; int status, page; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); /* Submit address of first page to unlock */ page = ofs >> chip->page_shift; @@ -987,7 +987,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { int ret = 0; int chipnr; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); pr_debug("%s: start = 0x%012llx, len = %llu\n", __func__, (unsigned long long)ofs, len); @@ -1050,7 +1050,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { int ret = 0; int chipnr, status, page; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); pr_debug("%s: start = 0x%012llx, len = %llu\n", __func__, (unsigned long long)ofs, len); @@ -1655,7 +1655,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, */ static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); pr_debug("setting READ RETRY mode %d\n", retry_mode); @@ -1680,7 +1680,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { int chipnr, page, realpage, col, bytes, aligned, oob_required; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int ret = 0; uint32_t readlen = ops->len; uint32_t oobreadlen = ops->ooblen; @@ -2024,7 +2024,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { int page, realpage, chipnr; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mtd_ecc_stats stats; int readlen = ops->ooblen; int len; @@ -2472,7 +2472,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, struct mtd_oob_ops *ops) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); /* * Initialise to all 0xFF, to avoid the possibility of left over OOB @@ -2532,7 +2532,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { int chipnr, realpage, page, blockmask, column; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); uint32_t writelen = ops->len; uint32_t oobwritelen = ops->ooblen; @@ -2662,7 +2662,7 @@ err_out: static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mtd_oob_ops ops; int ret; @@ -2722,7 +2722,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { int chipnr, page, status, len; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to, (int)ops->ooblen); @@ -2847,7 +2847,7 @@ out: */ static int single_erase(struct mtd_info *mtd, int page) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); /* Send commands to erase a block */ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); @@ -2879,7 +2879,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, int allowbbt) { int page, status, pages_per_block, ret, chipnr; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); loff_t len; pr_debug("%s: start = 0x%012llx, len = %llu\n", @@ -3094,7 +3094,7 @@ static int nand_suspend(struct mtd_info *mtd) */ static void nand_resume(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if (chip->state == FL_PM_SUSPENDED) nand_release_device(mtd); @@ -3266,7 +3266,7 @@ ext_out: static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode}; return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY, @@ -3985,7 +3985,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, struct nand_flash_dev *table) { int i, nand_maf_id, nand_dev_id; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct nand_flash_dev *type; int ret; @@ -4056,7 +4056,7 @@ EXPORT_SYMBOL(nand_scan_ident); */ static bool nand_ecc_strength_good(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &chip->ecc; int corr, ds_corr; @@ -4085,7 +4085,7 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd) int nand_scan_tail(struct mtd_info *mtd) { int i; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &chip->ecc; struct nand_buffers *nbuf; @@ -4429,7 +4429,7 @@ EXPORT_SYMBOL(nand_scan); */ void nand_release(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if (chip->ecc.mode == NAND_ECC_SOFT_BCH) nand_bch_free((struct nand_bch_control *)chip->ecc.priv); diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index b1d4f81..4b6a708 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -172,7 +172,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, struct nand_bbt_descr *td, int offs) { int res, ret = 0, i, j, act = 0; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); size_t retlen, len, totlen; loff_t from; int bits = td->options & NAND_BBT_NRBITS_MSK; @@ -263,7 +263,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, */ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int res = 0, i; if (td->options & NAND_BBT_PERCHIP) { @@ -388,7 +388,7 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td) static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); /* Read the primary version, if available */ if (td->options & NAND_BBT_VERSION) { @@ -454,7 +454,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int i, numblocks, numpages; int startblock; loff_t from; @@ -523,7 +523,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, */ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int i, chips; int startblock, block, dir; int scanlen = mtd->writesize + mtd->oobsize; @@ -618,7 +618,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct erase_info einfo; int i, res, chip = 0; int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; @@ -819,7 +819,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, */ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); return create_bbt(mtd, this->buffers->databuf, bd, -1); } @@ -838,7 +838,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) { int i, chips, writeops, create, chipsel, res, res2; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct nand_bbt_descr *td = this->bbt_td; struct nand_bbt_descr *md = this->bbt_md; struct nand_bbt_descr *rd, *rd2; @@ -962,7 +962,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc */ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int i, j, chips, block, nrblocks, update; uint8_t oldval; @@ -1022,7 +1022,7 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) */ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); u32 pattern_len; u32 bits; u32 table_size; @@ -1074,7 +1074,7 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) */ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int len, res; uint8_t *buf; struct nand_bbt_descr *td = this->bbt_td; @@ -1147,7 +1147,7 @@ err: */ static int nand_update_bbt(struct mtd_info *mtd, loff_t offs) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int len, res = 0; int chip, chipsel; uint8_t *buf; @@ -1281,7 +1281,7 @@ static int nand_create_badblock_pattern(struct nand_chip *this) */ int nand_default_bbt(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int ret; /* Is a flash based bad block table requested? */ @@ -1317,7 +1317,7 @@ int nand_default_bbt(struct mtd_info *mtd) */ int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int block; block = (int)(offs >> this->bbt_erase_shift); @@ -1332,7 +1332,7 @@ int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs) */ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int block, res; block = (int)(offs >> this->bbt_erase_shift); @@ -1359,7 +1359,7 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) */ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int block, ret = 0; block = (int)(offs >> this->bbt_erase_shift); diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index 3803e0b..e5758d8 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c @@ -52,7 +52,7 @@ struct nand_bch_control { int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf, unsigned char *code) { - const struct nand_chip *chip = mtd->priv; + const struct nand_chip *chip = mtd_to_nand(mtd); struct nand_bch_control *nbc = chip->ecc.priv; unsigned int i; @@ -79,7 +79,7 @@ EXPORT_SYMBOL(nand_bch_calculate_ecc); int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc) { - const struct nand_chip *chip = mtd->priv; + const struct nand_chip *chip = mtd_to_nand(mtd); struct nand_bch_control *nbc = chip->ecc.priv; unsigned int *errloc = nbc->errloc; int i, count; diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index 97c4c02..e612985 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c @@ -424,7 +424,7 @@ int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf, unsigned char *code) { __nand_calculate_ecc(buf, - ((struct nand_chip *)mtd->priv)->ecc.size, code); + mtd_to_nand(mtd)->ecc.size, code); return 0; } @@ -524,7 +524,7 @@ int nand_correct_data(struct mtd_info *mtd, unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc) { return __nand_correct_data(buf, read_ecc, calc_ecc, - ((struct nand_chip *)mtd->priv)->ecc.size); + mtd_to_nand(mtd)->ecc.size); } EXPORT_SYMBOL(nand_correct_data); diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index b16d70a..eb2a567 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -666,7 +666,7 @@ static char *get_partition_name(int i) */ static int init_nandsim(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct nandsim *ns = chip->priv; int i, ret = 0; uint64_t remains; @@ -1908,7 +1908,7 @@ static void switch_state(struct nandsim *ns) static u_char ns_nand_read_byte(struct mtd_info *mtd) { - struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; + struct nandsim *ns = mtd_to_nand(mtd)->priv; u_char outb = 0x00; /* Sanity and correctness checks */ @@ -1969,7 +1969,7 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd) static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) { - struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; + struct nandsim *ns = mtd_to_nand(mtd)->priv; /* Sanity and correctness checks */ if (!ns->lines.ce) { @@ -2123,7 +2123,7 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask) { - struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; + struct nandsim *ns = mtd_to_nand(mtd)->priv; ns->lines.cle = bitmask & NAND_CLE ? 1 : 0; ns->lines.ale = bitmask & NAND_ALE ? 1 : 0; @@ -2141,7 +2141,7 @@ static int ns_device_ready(struct mtd_info *mtd) static uint16_t ns_nand_read_word(struct mtd_info *mtd) { - struct nand_chip *chip = (struct nand_chip *)mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); NS_DBG("read_word\n"); @@ -2150,7 +2150,7 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd) static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { - struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; + struct nandsim *ns = mtd_to_nand(mtd)->priv; /* Check that chip is expecting data input */ if (!(ns->state & STATE_DATAIN_MASK)) { @@ -2177,7 +2177,7 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { - struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; + struct nandsim *ns = mtd_to_nand(mtd)->priv; /* Sanity and correctness checks */ if (!ns->lines.ce) { @@ -2198,7 +2198,7 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) int i; for (i = 0; i < len; i++) - buf[i] = ((struct nand_chip *)mtd->priv)->read_byte(mtd); + buf[i] = mtd_to_nand(mtd)->read_byte(mtd); return; } @@ -2405,7 +2405,7 @@ module_init(ns_init_module); */ static void __exit ns_cleanup_module(void) { - struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv; + struct nandsim *ns = mtd_to_nand(nsmtd)->priv; int i; nandsim_debugfs_remove(ns); -- cgit v1.1 From 4bd4ebcc540c35d4477b098cf26394f976551464 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Tue, 1 Dec 2015 12:03:04 +0100 Subject: mtd: nand: make use of mtd_to_nand() in NAND drivers mtd_to_nand() was recently introduced to avoid direct accesses to the mtd->priv field. Update all NAND drivers to use it. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/ams-delta.c | 4 +- drivers/mtd/nand/atmel_nand.c | 50 ++++++++++----------- drivers/mtd/nand/au1550nd.c | 22 +++++----- drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c | 16 +++---- drivers/mtd/nand/bf5xx_nand.c | 12 ++--- drivers/mtd/nand/brcmnand/brcmnand.c | 12 ++--- drivers/mtd/nand/cafe_nand.c | 18 ++++---- drivers/mtd/nand/cmx270_nand.c | 8 ++-- drivers/mtd/nand/cs553x_nand.c | 18 ++++---- drivers/mtd/nand/davinci_nand.c | 8 ++-- drivers/mtd/nand/diskonchip.c | 66 ++++++++++++++-------------- drivers/mtd/nand/docg4.c | 34 +++++++------- drivers/mtd/nand/fsl_elbc_nand.c | 14 +++--- drivers/mtd/nand/fsl_ifc_nand.c | 18 ++++---- drivers/mtd/nand/fsl_upm.c | 4 +- drivers/mtd/nand/fsmc_nand.c | 10 ++--- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 18 ++++---- drivers/mtd/nand/hisi504_nand.c | 16 +++---- drivers/mtd/nand/jz4740_nand.c | 4 +- drivers/mtd/nand/lpc32xx_mlc.c | 6 +-- drivers/mtd/nand/lpc32xx_slc.c | 14 +++--- drivers/mtd/nand/mpc5121_nfc.c | 24 +++++----- drivers/mtd/nand/mxc_nand.c | 34 +++++++------- drivers/mtd/nand/ndfc.c | 14 +++--- drivers/mtd/nand/nuc900_nand.c | 2 +- drivers/mtd/nand/omap2.c | 12 ++--- drivers/mtd/nand/orion_nand.c | 4 +- drivers/mtd/nand/pasemi_nand.c | 8 ++-- drivers/mtd/nand/pxa3xx_nand.c | 18 ++++---- drivers/mtd/nand/r852.c | 2 +- drivers/mtd/nand/s3c2410.c | 6 +-- drivers/mtd/nand/sharpsl.c | 2 +- drivers/mtd/nand/sm_common.c | 2 +- drivers/mtd/nand/socrates_nand.c | 8 ++-- drivers/mtd/nand/sunxi_nand.c | 26 +++++------ drivers/mtd/nand/tmio_nand.c | 2 +- drivers/mtd/nand/txx9ndfmc.c | 12 ++--- drivers/mtd/nand/xway_nand.c | 4 +- 38 files changed, 276 insertions(+), 276 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 842f8fe..b2b49c4 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -64,7 +64,7 @@ static struct mtd_partition partition_info[] = { static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); void __iomem *io_base = this->priv; writew(0, io_base + OMAP_MPUIO_IO_CNTL); @@ -77,7 +77,7 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) static u_char ams_delta_read_byte(struct mtd_info *mtd) { u_char res; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); void __iomem *io_base = this->priv; gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0); diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index f4e1f91..edd191a 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -182,7 +182,7 @@ static void atmel_nand_disable(struct atmel_nand_host *host) */ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; if (ctrl & NAND_CTRL_CHANGE) { @@ -205,7 +205,7 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl */ static int atmel_nand_device_ready(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; return gpio_get_value(host->board.rdy_pin) ^ @@ -215,7 +215,7 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) /* Set up for hardware ready pin and enable pin. */ static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand_host *host = chip->priv; int res = 0; @@ -267,7 +267,7 @@ static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd) */ static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { @@ -280,7 +280,7 @@ static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { @@ -293,14 +293,14 @@ static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); __raw_writesb(nand_chip->IO_ADDR_W, buf, len); } static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); } @@ -352,7 +352,7 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, dma_addr_t dma_src_addr, dma_dst_addr, phys_addr; struct dma_async_tx_descriptor *tx = NULL; dma_cookie_t cookie; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand_host *host = chip->priv; void *p = buf; int err = -EIO; @@ -425,7 +425,7 @@ err_buf: static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand_host *host = chip->priv; if (use_dma && len > mtd->oobsize) @@ -441,7 +441,7 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand_host *host = chip->priv; if (use_dma && len > mtd->oobsize) @@ -533,7 +533,7 @@ static int pmecc_data_alloc(struct atmel_nand_host *host) static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; int i; uint32_t value; @@ -550,7 +550,7 @@ static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector) static void pmecc_substitute(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; int16_t __iomem *alpha_to = host->pmecc_alpha_to; int16_t __iomem *index_of = host->pmecc_index_of; @@ -592,7 +592,7 @@ static void pmecc_substitute(struct mtd_info *mtd) static void pmecc_get_sigma(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; int16_t *lmu = host->pmecc_lmu; @@ -750,7 +750,7 @@ static void pmecc_get_sigma(struct mtd_info *mtd) static int pmecc_err_location(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; unsigned long end_time; const int cap = host->pmecc_corr_cap; @@ -802,7 +802,7 @@ static int pmecc_err_location(struct mtd_info *mtd) static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, int sector_num, int extra_bytes, int err_nbr) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; int i = 0; int byte_pos, bit_pos, sector_size, pos; @@ -848,7 +848,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, u8 *ecc) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; int i, err_nbr; uint8_t *buf_pos; @@ -992,7 +992,7 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, static void atmel_pmecc_core_init(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; uint32_t val = 0; struct nand_ecclayout *ecc_layout; @@ -1308,7 +1308,7 @@ err: static int atmel_nand_calculate(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; unsigned int ecc_value; @@ -1412,7 +1412,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *isnull) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; unsigned int ecc_status; unsigned int ecc_word, ecc_bit; @@ -1478,7 +1478,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, */ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; if (host->board.need_reset_workaround) @@ -1771,7 +1771,7 @@ static int nfc_send_command(struct atmel_nand_host *host, static int nfc_device_ready(struct mtd_info *mtd) { u32 status, mask; - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; status = nfc_read_status(host); @@ -1787,7 +1787,7 @@ static int nfc_device_ready(struct mtd_info *mtd) static void nfc_select_chip(struct mtd_info *mtd, int chip) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct atmel_nand_host *host = nand_chip->priv; if (chip == -1) @@ -1799,7 +1799,7 @@ static void nfc_select_chip(struct mtd_info *mtd, int chip) static int nfc_make_addr(struct mtd_info *mtd, int command, int column, int page_addr, unsigned int *addr1234, unsigned int *cycle0) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int acycle = 0; unsigned char addr_bytes[8]; @@ -1839,7 +1839,7 @@ static int nfc_make_addr(struct mtd_info *mtd, int command, int column, static void nfc_nand_command(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand_host *host = chip->priv; unsigned long timeout; unsigned int nfc_addr_cmd = 0; @@ -2026,7 +2026,7 @@ static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip, static int nfc_sram_init(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand_host *host = chip->priv; int res = 0; diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 08a130f..73fceb8 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -39,7 +39,7 @@ struct au1550nd_ctx { */ static u_char au_read_byte(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); u_char ret = readb(this->IO_ADDR_R); wmb(); /* drain writebuffer */ return ret; @@ -54,7 +54,7 @@ static u_char au_read_byte(struct mtd_info *mtd) */ static void au_write_byte(struct mtd_info *mtd, u_char byte) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); writeb(byte, this->IO_ADDR_W); wmb(); /* drain writebuffer */ } @@ -67,7 +67,7 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte) */ static u_char au_read_byte16(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); wmb(); /* drain writebuffer */ return ret; @@ -82,7 +82,7 @@ static u_char au_read_byte16(struct mtd_info *mtd) */ static void au_write_byte16(struct mtd_info *mtd, u_char byte) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); wmb(); /* drain writebuffer */ } @@ -95,7 +95,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte) */ static u16 au_read_word(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); u16 ret = readw(this->IO_ADDR_R); wmb(); /* drain writebuffer */ return ret; @@ -112,7 +112,7 @@ static u16 au_read_word(struct mtd_info *mtd) static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); for (i = 0; i < len; i++) { writeb(buf[i], this->IO_ADDR_W); @@ -131,7 +131,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); for (i = 0; i < len; i++) { buf[i] = readb(this->IO_ADDR_R); @@ -150,7 +150,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); u16 *p = (u16 *) buf; len >>= 1; @@ -172,7 +172,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); u16 *p = (u16 *) buf; len >>= 1; @@ -198,7 +198,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len) static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) { struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info); - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); switch (cmd) { @@ -268,7 +268,7 @@ static void au1550_select_chip(struct mtd_info *mtd, int chip) static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info); - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int ce_override = 0, i; unsigned long flags = 0; diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c index 592befc..e5b2e48 100644 --- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c @@ -89,7 +89,7 @@ static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc) static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; u32 ctlcode; @@ -139,7 +139,7 @@ static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf, static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; struct bcma_drv_cc *cc = b47n->cc; @@ -173,7 +173,7 @@ static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd, static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; u32 code = 0; @@ -199,7 +199,7 @@ static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd, static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd) { - struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY); @@ -216,7 +216,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; struct bcma_drv_cc *cc = b47n->cc; u32 ctlcode; @@ -312,7 +312,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd) { - struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; struct bcma_drv_cc *cc = b47n->cc; u32 tmp = 0; @@ -341,7 +341,7 @@ static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd) static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; switch (b47n->curr_command) { @@ -357,7 +357,7 @@ static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd, static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; switch (b47n->curr_command) { diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 61bd216..d9da5ed 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -304,7 +304,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat, static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int ret; ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); @@ -329,7 +329,7 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); u16 ecc0, ecc1; u32 code[2]; u8 *p; @@ -466,7 +466,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, uint8_t *buf, int is_read) { struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); unsigned short val; dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n", @@ -532,7 +532,7 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len); @@ -546,7 +546,7 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len); @@ -685,7 +685,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev) static int bf5xx_nand_scan(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int ret; ret = nand_scan_ident(mtd, 1, NULL); diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 35d78f7..190a99a 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -873,7 +873,7 @@ static struct nand_ecclayout *brcmstb_choose_ecc_layout( static void brcmnand_wp(struct mtd_info *mtd, int wp) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct brcmnand_host *host = chip->priv; struct brcmnand_controller *ctrl = host->ctrl; @@ -1039,7 +1039,7 @@ static void brcmnand_cmd_ctrl(struct mtd_info *mtd, int dat, static int brcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct brcmnand_host *host = chip->priv; struct brcmnand_controller *ctrl = host->ctrl; unsigned long timeo = msecs_to_jiffies(100); @@ -1113,7 +1113,7 @@ static int brcmnand_low_level_op(struct brcmnand_host *host, static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct brcmnand_host *host = chip->priv; struct brcmnand_controller *ctrl = host->ctrl; u64 addr = (u64)page_addr << chip->page_shift; @@ -1219,7 +1219,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, static uint8_t brcmnand_read_byte(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct brcmnand_host *host = chip->priv; struct brcmnand_controller *ctrl = host->ctrl; uint8_t ret = 0; @@ -1286,7 +1286,7 @@ static void brcmnand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { int i; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct brcmnand_host *host = chip->priv; switch (host->last_cmd) { @@ -2061,7 +2061,7 @@ static int brcmnand_resume(struct device *dev) list_for_each_entry(host, &ctrl->host_list, node) { struct mtd_info *mtd = &host->mtd; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); brcmnand_save_restore_cs_config(host, 1); diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index cce3ac4..77c92f1 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -101,7 +101,7 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; static int cafe_device_ready(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = chip->priv; int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000); uint32_t irqs = cafe_readl(cafe, NAND_IRQ); @@ -118,7 +118,7 @@ static int cafe_device_ready(struct mtd_info *mtd) static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = chip->priv; if (usedma) @@ -134,7 +134,7 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = chip->priv; if (usedma) @@ -149,7 +149,7 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static uint8_t cafe_read_byte(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = chip->priv; uint8_t d; @@ -162,7 +162,7 @@ static uint8_t cafe_read_byte(struct mtd_info *mtd) static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = chip->priv; int adrbytes = 0; uint32_t ctl1; @@ -318,7 +318,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, static void cafe_select_chip(struct mtd_info *mtd, int chipnr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = chip->priv; cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); @@ -334,7 +334,7 @@ static void cafe_select_chip(struct mtd_info *mtd, int chipnr) static irqreturn_t cafe_nand_interrupt(int irq, void *id) { struct mtd_info *mtd = id; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = chip->priv; uint32_t irqs = cafe_readl(cafe, NAND_IRQ); cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ); @@ -800,7 +800,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, static void cafe_nand_remove(struct pci_dev *pdev) { struct mtd_info *mtd = pci_get_drvdata(pdev); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = chip->priv; /* Disable NAND IRQ in global IRQ mask register */ @@ -828,7 +828,7 @@ static int cafe_nand_resume(struct pci_dev *pdev) { uint32_t ctrl; struct mtd_info *mtd = pci_get_drvdata(pdev); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = chip->priv; /* Start off by resetting the NAND controller completely */ diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index 66ec95e..43bded6 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c @@ -53,7 +53,7 @@ static struct mtd_partition partition_info[] = { static u_char cmx270_read_byte(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); return (readl(this->IO_ADDR_R) >> 16); } @@ -61,7 +61,7 @@ static u_char cmx270_read_byte(struct mtd_info *mtd) static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); for (i=0; iIO_ADDR_W); @@ -70,7 +70,7 @@ static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len) static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); for (i=0; iIO_ADDR_R) >> 16; @@ -94,7 +94,7 @@ static void nand_cs_off(void) static void cmx270_hwcontrol(struct mtd_info *mtd, int dat, unsigned int ctrl) { - struct nand_chip* this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; dsb(); diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index aec6045..8904d68 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -97,7 +97,7 @@ static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); while (unlikely(len > 0x800)) { memcpy_fromio(buf, this->IO_ADDR_R, 0x800); @@ -109,7 +109,7 @@ static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len) static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); while (unlikely(len > 0x800)) { memcpy_toio(this->IO_ADDR_R, buf, 0x800); @@ -121,13 +121,13 @@ static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len) static unsigned char cs553x_read_byte(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); return readb(this->IO_ADDR_R); } static void cs553x_write_byte(struct mtd_info *mtd, u_char byte) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); int i = 100000; while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) { @@ -140,7 +140,7 @@ static void cs553x_write_byte(struct mtd_info *mtd, u_char byte) static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); void __iomem *mmio_base = this->IO_ADDR_R; if (ctrl & NAND_CTRL_CHANGE) { unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01; @@ -152,7 +152,7 @@ static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd, static int cs553x_device_ready(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); void __iomem *mmio_base = this->IO_ADDR_R; unsigned char foo = readb(mmio_base + MM_NAND_STS); @@ -161,7 +161,7 @@ static int cs553x_device_ready(struct mtd_info *mtd) static void cs_enable_hwecc(struct mtd_info *mtd, int mode) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); void __iomem *mmio_base = this->IO_ADDR_R; writeb(0x07, mmio_base + MM_NAND_ECC_CTL); @@ -170,7 +170,7 @@ static void cs_enable_hwecc(struct mtd_info *mtd, int mode) static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { uint32_t ecc; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); void __iomem *mmio_base = this->IO_ADDR_R; ecc = readl(mmio_base + MM_NAND_STS); @@ -337,7 +337,7 @@ static void __exit cs553x_cleanup(void) if (!mtd) continue; - this = cs553x_mtd[i]->priv; + this = mtd_to_nand(cs553x_mtd[i]); mmio_base = this->IO_ADDR_R; /* Release resources, unregister device */ diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 8e351af..b5978d5 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -106,7 +106,7 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, { struct davinci_nand_info *info = to_davinci_nand(mtd); uint32_t addr = info->current_cs; - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); /* Did the control lines change? */ if (ctrl & NAND_CTRL_CHANGE) { @@ -192,7 +192,7 @@ static int nand_davinci_calculate_1bit(struct mtd_info *mtd, static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); uint32_t eccNand = read_ecc[0] | (read_ecc[1] << 8) | (read_ecc[2] << 16); uint32_t eccCalc = calc_ecc[0] | (calc_ecc[1] << 8) | @@ -447,7 +447,7 @@ correct: */ static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0) ioread32_rep(chip->IO_ADDR_R, buf, len >> 2); @@ -460,7 +460,7 @@ static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0) iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2); diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 0802158..5f7bcc8 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -299,7 +299,7 @@ static inline int DoC_WaitReady(struct doc_priv *doc) static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; @@ -311,7 +311,7 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) static u_char doc2000_read_byte(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; u_char ret; @@ -326,7 +326,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd) static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; @@ -343,7 +343,7 @@ static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; @@ -358,7 +358,7 @@ static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; @@ -379,7 +379,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len) static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; uint16_t ret; @@ -425,7 +425,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) static void __init doc2000_count_chips(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; uint16_t mfrid; int i; @@ -461,7 +461,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this) static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; @@ -472,7 +472,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) static u_char doc2001_read_byte(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; @@ -486,7 +486,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; @@ -499,7 +499,7 @@ static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; @@ -516,7 +516,7 @@ static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) static u_char doc2001plus_read_byte(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; u_char ret; @@ -531,7 +531,7 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd) static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; @@ -549,7 +549,7 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int le static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; @@ -580,7 +580,7 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len) static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int floor = 0; @@ -607,7 +607,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) static void doc200x_select_chip(struct mtd_info *mtd, int chip) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int floor = 0; @@ -638,7 +638,7 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip) static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; @@ -661,7 +661,7 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; @@ -767,7 +767,7 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu static int doc200x_dev_ready(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; @@ -807,7 +807,7 @@ static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; @@ -826,7 +826,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; @@ -846,7 +846,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) /* This code is only called on write */ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; int i; @@ -907,7 +907,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *isnull) { int i, ret = 0; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; void __iomem *docptr = doc->virtadr; uint8_t calc_ecc[6]; @@ -1007,7 +1007,7 @@ static struct nand_ecclayout doc200x_oobinfo = { mh1_page in the DOC private structure. */ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; unsigned offs; int ret; @@ -1050,7 +1050,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; int ret = 0; u_char *buf; @@ -1152,7 +1152,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio /* This is a stripped-down copy of the code in inftlmount.c */ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; int ret = 0; u_char *buf; @@ -1272,7 +1272,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti static int __init nftl_scan_bbt(struct mtd_info *mtd) { int ret, numparts; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; struct mtd_partition parts[2]; @@ -1307,7 +1307,7 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd) static int __init inftl_scan_bbt(struct mtd_info *mtd) { int ret, numparts; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; struct mtd_partition parts[5]; @@ -1360,7 +1360,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) static inline int __init doc2000_init(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; this->read_byte = doc2000_read_byte; @@ -1376,7 +1376,7 @@ static inline int __init doc2000_init(struct mtd_info *mtd) static inline int __init doc2001_init(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; this->read_byte = doc2001_read_byte; @@ -1406,7 +1406,7 @@ static inline int __init doc2001_init(struct mtd_info *mtd) static inline int __init doc2001plus_init(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = this->priv; this->read_byte = doc2001plus_read_byte; @@ -1523,7 +1523,7 @@ static int __init doc_probe(unsigned long physadr) for (mtd = doclist; mtd; mtd = doc->nextdoc) { unsigned char oldval; unsigned char newval; - nand = mtd->priv; + nand = mtd_to_nand(mtd); doc = nand->priv; /* Use the alias resolution register to determine if this is in fact the same DOC aliased to a new address. If writes @@ -1643,7 +1643,7 @@ static void release_nanddoc(void) struct doc_priv *doc; for (mtd = doclist; mtd; mtd = nextmtd) { - nand = mtd->priv; + nand = mtd_to_nand(mtd); doc = nand->priv; nextmtd = doc->nextdoc; diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index 408cf69..da93d7f 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c @@ -242,7 +242,7 @@ static inline void write_nop(void __iomem *docptr) static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { int i; - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); uint16_t *p = (uint16_t *) buf; len >>= 1; @@ -253,7 +253,7 @@ static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void docg4_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) { int i; - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); uint16_t *p = (uint16_t *) buf; len >>= 1; @@ -318,7 +318,7 @@ static void docg4_select_chip(struct mtd_info *mtd, int chip) * Select among multiple cascaded chips ("floors"). Multiple floors are * not yet supported, so the only valid non-negative value is 0. */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; @@ -337,7 +337,7 @@ static void reset(struct mtd_info *mtd) { /* full device reset */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; @@ -375,7 +375,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page) * Up to four bitflips can be corrected. */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; int i, numerrs, errpos[4]; @@ -464,7 +464,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page) static uint8_t docg4_read_byte(struct mtd_info *mtd) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; dev_dbg(doc->dev, "%s\n", __func__); @@ -545,7 +545,7 @@ static int pageprog(struct mtd_info *mtd) * internal buffer out to the flash array, or some such. */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; int retval = 0; @@ -582,7 +582,7 @@ static void sequence_reset(struct mtd_info *mtd) { /* common starting sequence for all operations */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; @@ -599,7 +599,7 @@ static void read_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr) { /* first step in reading a page */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; @@ -626,7 +626,7 @@ static void write_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr) { /* first step in writing a page */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; @@ -691,7 +691,7 @@ static void docg4_command(struct mtd_info *mtd, unsigned command, int column, { /* handle standard nand commands */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; uint32_t g4_addr = mtd_to_docg4_address(page_addr, column); @@ -874,7 +874,7 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, static int docg4_erase_block(struct mtd_info *mtd, int page) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; uint16_t g4_page; @@ -1016,7 +1016,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) * update the memory-based bbt accordingly. */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0); uint8_t *buf; @@ -1089,7 +1089,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) int ret, i; uint8_t *buf; - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; struct nand_bbt_descr *bbtd = nand->badblock_pattern; int page = (int)(ofs >> nand->page_shift); @@ -1202,7 +1202,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd) * things as well, such as call nand_set_defaults(). */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; mtd->size = DOCG4_CHIP_SIZE; @@ -1261,7 +1261,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd) static int __init read_id_reg(struct mtd_info *mtd) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; uint16_t id1, id2; @@ -1357,7 +1357,7 @@ static int __init probe_docg4(struct platform_device *pdev) iounmap(virtadr); if (mtd) { /* re-declarations avoid compiler warning */ - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; nand_release(mtd); /* deletes partitions and mtd devices */ free_bch(doc->bch); diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index bd6d493..ad6d5da 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -144,7 +144,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { */ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_elbc_mtd *priv = chip->priv; struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_lbc_regs __iomem *lbc = ctrl->regs; @@ -195,7 +195,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) */ static int fsl_elbc_run_command(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_elbc_mtd *priv = chip->priv; struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; @@ -300,7 +300,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob) static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_elbc_mtd *priv = chip->priv; struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; @@ -525,7 +525,7 @@ static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip) */ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; unsigned int bufsize = mtd->writesize + mtd->oobsize; @@ -563,7 +563,7 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) */ static u8 fsl_elbc_read_byte(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; @@ -580,7 +580,7 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd) */ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; int avail; @@ -619,7 +619,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_elbc_mtd *priv = chip->priv; struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_lbc_regs __iomem *lbc = ctrl->regs; diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index f260831..3136842 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -230,7 +230,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { */ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_regs __iomem *ifc = ctrl->regs; @@ -253,7 +253,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) static int is_blank(struct mtd_info *mtd, unsigned int bufnum) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = chip->priv; u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2); u32 __iomem *mainarea = (u32 __iomem *)addr; @@ -292,7 +292,7 @@ static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl, */ static void fsl_ifc_run_command(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; @@ -409,7 +409,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip, /* cmdfunc send commands to the IFC NAND Machine */ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_regs __iomem *ifc = ctrl->regs; @@ -624,7 +624,7 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip) */ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = chip->priv; unsigned int bufsize = mtd->writesize + mtd->oobsize; @@ -650,7 +650,7 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) */ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = chip->priv; unsigned int offset; @@ -673,7 +673,7 @@ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd) */ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = chip->priv; uint16_t data; @@ -696,7 +696,7 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) */ static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = chip->priv; int avail; @@ -782,7 +782,7 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = chip->priv; dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__, diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index b3f4a01..68ec128 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -79,7 +79,7 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun) static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); u32 mar; @@ -109,7 +109,7 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) static void fun_select_chip(struct mtd_info *mtd, int mchip_nr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); if (mchip_nr == -1) { diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 59fc6d0..1c6c399 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -329,7 +329,7 @@ struct fsmc_nand_data { /* Assert CS signal based on chipnr */ static void fsmc_select_chip(struct mtd_info *mtd, int chipnr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct fsmc_nand_data *host; host = container_of(mtd, struct fsmc_nand_data, mtd); @@ -358,7 +358,7 @@ static void fsmc_select_chip(struct mtd_info *mtd, int chipnr) */ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct fsmc_nand_data *host = container_of(mtd, struct fsmc_nand_data, mtd); void __iomem *regs = host->regs_va; @@ -629,7 +629,7 @@ unmap_dma: static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { int i; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) && IS_ALIGNED(len, sizeof(uint32_t))) { @@ -652,7 +652,7 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { int i; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) && IS_ALIGNED(len, sizeof(uint32_t))) { @@ -784,7 +784,7 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, { struct fsmc_nand_data *host = container_of(mtd, struct fsmc_nand_data, mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); void __iomem *regs = host->regs_va; unsigned int bank = host->bank; uint32_t err_idx[8]; diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 5a9b696..802adb0 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -140,7 +140,7 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) { struct bch_geometry *geo = &this->bch_geometry; struct mtd_info *mtd = &this->mtd; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct nand_oobfree *of = gpmi_hw_ecclayout.oobfree; unsigned int block_mark_bit_offset; @@ -856,7 +856,7 @@ error_alloc: static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = chip->priv; int ret; @@ -890,7 +890,7 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) static int gpmi_dev_ready(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = chip->priv; return gpmi_is_ready(this, this->current_chip); @@ -898,7 +898,7 @@ static int gpmi_dev_ready(struct mtd_info *mtd) static void gpmi_select_chip(struct mtd_info *mtd, int chipnr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = chip->priv; if ((this->current_chip < 0) && (chipnr >= 0)) @@ -911,7 +911,7 @@ static void gpmi_select_chip(struct mtd_info *mtd, int chipnr) static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = chip->priv; dev_dbg(this->dev, "len is %d\n", len); @@ -923,7 +923,7 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = chip->priv; dev_dbg(this->dev, "len is %d\n", len); @@ -935,7 +935,7 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) static uint8_t gpmi_read_byte(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = chip->priv; uint8_t *buf = this->data_buffer_dma; @@ -1538,7 +1538,7 @@ static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = chip->priv; int ret = 0; uint8_t *block_mark; @@ -1838,7 +1838,7 @@ static void gpmi_nand_exit(struct gpmi_nand_data *this) static int gpmi_init_last(struct gpmi_nand_data *this) { struct mtd_info *mtd = &this->mtd; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &chip->ecc; struct bch_geometry *bch_geo = &this->bch_geometry; int ret; diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c index 0aad4ac..6358d4a 100644 --- a/drivers/mtd/nand/hisi504_nand.c +++ b/drivers/mtd/nand/hisi504_nand.c @@ -190,7 +190,7 @@ static void wait_controller_finished(struct hinfc_host *host) static void hisi_nfc_dma_transfer(struct hinfc_host *host, int todev) { struct mtd_info *mtd = &host->mtd; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); unsigned long val; int ret; @@ -357,7 +357,7 @@ static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect) static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = chip->priv; if (chipselect < 0) @@ -368,7 +368,7 @@ static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect) static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = chip->priv; if (host->command == NAND_CMD_STATUS) @@ -384,7 +384,7 @@ static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd) static u16 hisi_nfc_read_word(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = chip->priv; host->offset += 2; @@ -394,7 +394,7 @@ static u16 hisi_nfc_read_word(struct mtd_info *mtd) static void hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = chip->priv; memcpy(host->buffer + host->offset, buf, len); @@ -403,7 +403,7 @@ hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = chip->priv; memcpy(buf, host->buffer + host->offset, len); @@ -412,7 +412,7 @@ static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void set_addr(struct mtd_info *mtd, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = chip->priv; unsigned int command = host->command; @@ -448,7 +448,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr) static void hisi_nfc_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = chip->priv; int is_cache_invalid = 1; unsigned int flag = 0; diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 5a99a93..5a06fba 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -82,7 +82,7 @@ static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd) static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr) { struct jz_nand *nand = mtd_to_jz_nand(mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); uint32_t ctrl; int banknr; @@ -104,7 +104,7 @@ static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr) static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) { struct jz_nand *nand = mtd_to_jz_nand(mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); uint32_t reg; void __iomem *bank_base = nand->bank_base[nand->selected_bank]; diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index 57c4b71..3738856 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -275,7 +275,7 @@ static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host) static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = nand_chip->priv; if (cmd != NAND_CMD_NONE) { @@ -291,7 +291,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, */ static int lpc32xx_nand_device_ready(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = nand_chip->priv; if ((readb(MLC_ISR(host->io_base)) & @@ -389,7 +389,7 @@ static void lpc32xx_dma_complete_func(void *completion) static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len, enum dma_transfer_direction dir) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = chip->priv; struct dma_async_tx_descriptor *desc; int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index 277626e..fcd9fac 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c @@ -260,7 +260,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { uint32_t tmp; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = chip->priv; /* Does CE state need to be changed? */ @@ -284,7 +284,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, */ static int lpc32xx_nand_device_ready(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = chip->priv; int rdy = 0; @@ -339,7 +339,7 @@ static int lpc32xx_nand_ecc_calculate(struct mtd_info *mtd, */ static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = chip->priv; return (uint8_t)readl(SLC_DATA(host->io_base)); @@ -350,7 +350,7 @@ static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd) */ static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = chip->priv; /* Direct device read with no ECC */ @@ -363,7 +363,7 @@ static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) */ static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = chip->priv; /* Direct device write with no ECC */ @@ -428,7 +428,7 @@ static void lpc32xx_dma_complete_func(void *completion) static int lpc32xx_xmit_dma(struct mtd_info *mtd, dma_addr_t dma, void *mem, int len, enum dma_transfer_direction dir) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = chip->priv; struct dma_async_tx_descriptor *desc; int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; @@ -488,7 +488,7 @@ out1: static int lpc32xx_xfer(struct mtd_info *mtd, uint8_t *buf, int eccsubpages, int read) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = chip->priv; int i, status = 0; unsigned long timeout; diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 0fdfc42..642c486 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -135,7 +135,7 @@ static void mpc5121_nfc_done(struct mtd_info *mtd); /* Read NFC register */ static inline u16 nfc_read(struct mtd_info *mtd, uint reg) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = chip->priv; return in_be16(prv->regs + reg); @@ -144,7 +144,7 @@ static inline u16 nfc_read(struct mtd_info *mtd, uint reg) /* Write NFC register */ static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = chip->priv; out_be16(prv->regs + reg, val); @@ -214,7 +214,7 @@ static inline void mpc5121_nfc_send_read_status(struct mtd_info *mtd) static irqreturn_t mpc5121_nfc_irq(int irq, void *data) { struct mtd_info *mtd = data; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = chip->priv; nfc_set(mtd, NFC_CONFIG1, NFC_INT_MASK); @@ -226,7 +226,7 @@ static irqreturn_t mpc5121_nfc_irq(int irq, void *data) /* Wait for operation complete */ static void mpc5121_nfc_done(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = chip->priv; int rv; @@ -246,7 +246,7 @@ static void mpc5121_nfc_done(struct mtd_info *mtd) /* Do address cycle(s) */ static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); u32 pagemask = chip->pagemask; if (column != -1) { @@ -281,7 +281,7 @@ static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip) /* Init external chip select logic on ADS5121 board */ static int ads5121_chipselect_init(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = chip->priv; struct device_node *dn; @@ -303,7 +303,7 @@ static int ads5121_chipselect_init(struct mtd_info *mtd) /* Control chips select signal on ADS5121 board */ static void ads5121_select_chip(struct mtd_info *mtd, int chip) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = nand->priv; u8 v; @@ -333,7 +333,7 @@ static int mpc5121_nfc_dev_ready(struct mtd_info *mtd) static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command, int column, int page) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = chip->priv; prv->column = (column >= 0) ? column : 0; @@ -406,7 +406,7 @@ static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command, static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset, u8 *buffer, uint size, int wr) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = nand->priv; uint o, s, sbsize, blksize; @@ -458,7 +458,7 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset, static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len, int wr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = chip->priv; uint c = prv->column; uint l; @@ -536,7 +536,7 @@ static u16 mpc5121_nfc_read_word(struct mtd_info *mtd) */ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = chip->priv; struct mpc512x_reset_module *rm; struct device_node *rmnode; @@ -615,7 +615,7 @@ out: /* Free driver resources */ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mpc5121_nfc_prv *prv = chip->priv; if (prv->clk) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index f507d36..b291258 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -532,7 +532,7 @@ static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islas static void send_page_v3(struct mtd_info *mtd, unsigned int ops) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; uint32_t tmp; @@ -548,7 +548,7 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops) static void send_page_v2(struct mtd_info *mtd, unsigned int ops) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; /* NANDFC buffer 0 is used for page read/write */ @@ -562,7 +562,7 @@ static void send_page_v2(struct mtd_info *mtd, unsigned int ops) static void send_page_v1(struct mtd_info *mtd, unsigned int ops) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; int bufs, i; @@ -663,7 +663,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; /* @@ -684,7 +684,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; u32 ecc_stat, err; int no_subpages = 1; @@ -722,7 +722,7 @@ static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, static u_char mxc_nand_read_byte(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; uint8_t ret; @@ -746,7 +746,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) static uint16_t mxc_nand_read_word(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; uint16_t ret; @@ -762,7 +762,7 @@ static uint16_t mxc_nand_read_word(struct mtd_info *mtd) static void mxc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; u16 col = host->buf_start; int n = mtd->oobsize + mtd->writesize - col; @@ -780,7 +780,7 @@ static void mxc_nand_write_buf(struct mtd_info *mtd, */ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; u16 col = host->buf_start; int n = mtd->oobsize + mtd->writesize - col; @@ -796,7 +796,7 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) * deselect of the NAND chip */ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; if (chip == -1) { @@ -817,7 +817,7 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; if (chip == -1) { @@ -850,7 +850,7 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) */ static void copy_spare(struct mtd_info *mtd, bool bfrom) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct mxc_nand_host *host = this->priv; u16 i, oob_chunk_size; u16 num_chunks = mtd->writesize / 512; @@ -893,7 +893,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) */ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; /* Write out column address, if necessary */ @@ -979,7 +979,7 @@ static void ecc_8bit_layout_4k(struct nand_ecclayout *layout) static void preset_v1(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; uint16_t config1 = 0; @@ -1007,7 +1007,7 @@ static void preset_v1(struct mtd_info *mtd) static void preset_v2(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; uint16_t config1 = 0; @@ -1053,7 +1053,7 @@ static void preset_v2(struct mtd_info *mtd) static void preset_v3(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct mxc_nand_host *host = chip->priv; uint32_t config2, config3; int i, addr_phases; @@ -1124,7 +1124,7 @@ static void preset_v3(struct mtd_info *mtd) static void mxc_nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_chip->priv; pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 6965858..d8a23b0 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -48,7 +48,7 @@ static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS]; static void ndfc_select_chip(struct mtd_info *mtd, int chip) { uint32_t ccr; - struct nand_chip *nchip = mtd->priv; + struct nand_chip *nchip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nchip->priv; ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); @@ -62,7 +62,7 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip) static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = chip->priv; if (cmd == NAND_CMD_NONE) @@ -76,7 +76,7 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) static int ndfc_ready(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = chip->priv; return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; @@ -85,7 +85,7 @@ static int ndfc_ready(struct mtd_info *mtd) static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) { uint32_t ccr; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = chip->priv; ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); @@ -97,7 +97,7 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) static int ndfc_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = chip->priv; uint32_t ecc; uint8_t *p = (uint8_t *)&ecc; @@ -121,7 +121,7 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd, */ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = chip->priv; uint32_t *p = (uint32_t *) buf; @@ -131,7 +131,7 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = chip->priv; uint32_t *p = (uint32_t *) buf; diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index f0687f7..8148cd6 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -136,7 +136,7 @@ static int nuc900_nand_devready(struct mtd_info *mtd) static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { - register struct nand_chip *chip = mtd->priv; + register struct nand_chip *chip = mtd_to_nand(mtd); struct nuc900_nand *nand; nand = container_of(mtd, struct nuc900_nand, mtd); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index e307576..944a74e 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -270,7 +270,7 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) */ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); ioread8_rep(nand->IO_ADDR_R, buf, len); } @@ -306,7 +306,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) */ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); ioread16_rep(nand->IO_ADDR_R, buf, len / 2); } @@ -955,7 +955,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; u32 val; @@ -1001,7 +1001,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) */ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); unsigned long timeo = jiffies; @@ -1061,7 +1061,7 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); enum omap_ecc ecc_opt = info->ecc_opt; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); u32 val, wr_mode; unsigned int ecc_size1, ecc_size0; @@ -2056,7 +2056,7 @@ return_error: static int omap_nand_remove(struct platform_device *pdev) { struct mtd_info *mtd = platform_get_drvdata(pdev); - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); if (nand_chip->ecc.priv) { diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 5c21416..4ed4f67 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -25,7 +25,7 @@ static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *nc = mtd->priv; + struct nand_chip *nc = mtd_to_nand(mtd); struct orion_nand_data *board = nc->priv; u32 offs; @@ -47,7 +47,7 @@ static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); void __iomem *io_base = chip->IO_ADDR_R; uint64_t *buf64; int i = 0; diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 83cf021..0ececac 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -45,7 +45,7 @@ static const char driver_name[] = "pasemi-nand"; static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); while (len > 0x800) { memcpy_fromio(buf, chip->IO_ADDR_R, 0x800); @@ -57,7 +57,7 @@ static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len) static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); while (len > 0x800) { memcpy_toio(chip->IO_ADDR_R, buf, 0x800); @@ -70,7 +70,7 @@ static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len) static void pasemi_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if (cmd == NAND_CMD_NONE) return; @@ -192,7 +192,7 @@ static int pasemi_nand_remove(struct platform_device *ofdev) if (!pasemi_nand_mtd) return 0; - chip = pasemi_nand_mtd->priv; + chip = mtd_to_nand(pasemi_nand_mtd); /* Release resources, unregister device */ nand_release(pasemi_nand_mtd); diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index bdbc2c2..dc39a98 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1113,7 +1113,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, static void nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; int exec_cmd; @@ -1162,7 +1162,7 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, const unsigned command, int column, int page_addr) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; int exec_cmd, ext_cmd_type; @@ -1309,7 +1309,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; char retval = 0xFF; @@ -1323,7 +1323,7 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; u16 retval = 0xFFFF; @@ -1337,7 +1337,7 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; int real_len = min_t(size_t, len, info->buf_count - info->buf_start); @@ -1349,7 +1349,7 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void pxa3xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; int real_len = min_t(size_t, len, info->buf_count - info->buf_start); @@ -1365,7 +1365,7 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip) static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; @@ -1416,7 +1416,7 @@ static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info) { struct pxa3xx_nand_host *host = info->host[info->cs]; struct mtd_info *mtd = host->mtd; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0; info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0; @@ -1572,7 +1572,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, static int pxa3xx_nand_scan(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct pxa3xx_nand_host *host = chip->priv; struct pxa3xx_nand_info *info = host->info_data; struct platform_device *pdev = info->pdev; diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index be28cdd..ca05b20 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -64,7 +64,7 @@ static inline void r852_write_reg_dword(struct r852_device *dev, /* returns pointer to our private structure */ static inline struct r852_device *r852_get_dev(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); return chip->priv; } diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 05105ca..e658b29 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -382,7 +382,7 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) { struct s3c2410_nand_info *info; struct s3c2410_nand_mtd *nmtd; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); unsigned long cur; nmtd = this->priv; @@ -634,7 +634,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); readsb(this->IO_ADDR_R, buf, len); } @@ -656,7 +656,7 @@ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); writesb(this->IO_ADDR_W, buf, len); } diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 082b600..84129e5 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -66,7 +66,7 @@ static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if (ctrl & NAND_CTRL_CHANGE) { unsigned char bits = ctrl & 0x07; diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index e06b5e5..c514740 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c @@ -102,7 +102,7 @@ static struct nand_flash_dev nand_xd_flash_ids[] = { int sm_register_device(struct mtd_info *mtd, int smartmedia) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int ret; chip->options |= NAND_SKIP_BBTSCAN; diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index bde4043..2dfb1e0 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -45,7 +45,7 @@ static void socrates_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct socrates_nand_host *host = this->priv; for (i = 0; i < len; i++) { @@ -64,7 +64,7 @@ static void socrates_nand_write_buf(struct mtd_info *mtd, static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); struct socrates_nand_host *host = this->priv; uint32_t val; @@ -105,7 +105,7 @@ static uint16_t socrates_nand_read_word(struct mtd_info *mtd) static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_chip->priv; uint32_t val; @@ -130,7 +130,7 @@ static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, */ static int socrates_nand_device_ready(struct mtd_info *mtd) { - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_chip->priv; if (in_be32(host->io_base) & FPGA_NAND_BUSY) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 1bbcc0c..4ecd486 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -350,7 +350,7 @@ static int sunxi_nfc_rst(struct sunxi_nfc *nfc) static int sunxi_nfc_dev_ready(struct mtd_info *mtd) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct sunxi_nand_rb *rb; @@ -388,7 +388,7 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd) static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct sunxi_nand_chip_sel *sel; @@ -433,7 +433,7 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip) static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); int ret; @@ -466,7 +466,7 @@ static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); int ret; @@ -507,7 +507,7 @@ static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd) static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); int ret; @@ -541,7 +541,7 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct sunxi_nand_hw_ecc *data = nand->ecc.priv; u32 ecc_ctl; @@ -556,7 +556,7 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd) static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN, @@ -577,7 +577,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, int *cur_off, unsigned int *max_bitflips) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; u32 status; @@ -638,7 +638,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, u8 *oob, int *cur_off) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &nand->ecc; int offset = ((ecc->bytes + 4) * ecc->steps); int len = mtd->oobsize - offset; @@ -665,7 +665,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, const u8 *oob, int oob_off, int *cur_off) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; int ret; @@ -702,7 +702,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, u8 *oob, int *cur_off) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &nand->ecc; int offset = ((ecc->bytes + 4) * ecc->steps); int len = mtd->oobsize - offset; @@ -1031,7 +1031,7 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, struct device_node *np) { static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 }; - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct sunxi_nand_hw_ecc *data; @@ -1189,7 +1189,7 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc) static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc, struct device_node *np) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); int ret; if (!ecc->size) { diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index befddf0..6d0cbe9 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c @@ -128,7 +128,7 @@ static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct tmio_nand *tmio = mtd_to_tmio(mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); if (ctrl & NAND_CTRL_CHANGE) { u8 mode; diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index 8572519..ff9afb1 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c @@ -79,7 +79,7 @@ struct txx9ndfmc_drvdata { static struct platform_device *mtd_to_platdev(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct txx9ndfmc_priv *txx9_priv = chip->priv; return txx9_priv->dev; } @@ -135,7 +135,7 @@ static void txx9ndfmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); struct txx9ndfmc_priv *txx9_priv = chip->priv; struct platform_device *dev = txx9_priv->dev; struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); @@ -175,7 +175,7 @@ static int txx9ndfmc_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code) { struct platform_device *dev = mtd_to_platdev(mtd); - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int eccbytes; u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); @@ -195,7 +195,7 @@ static int txx9ndfmc_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, static int txx9ndfmc_correct_data(struct mtd_info *mtd, unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int eccsize; int corrected = 0; int stat; @@ -257,7 +257,7 @@ static void txx9ndfmc_initialize(struct platform_device *dev) static int txx9ndfmc_nand_scan(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); int ret; ret = nand_scan_ident(mtd, 1, NULL); @@ -391,7 +391,7 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev) if (!mtd) continue; - chip = mtd->priv; + chip = mtd_to_nand(mtd); txx9_priv = chip->priv; nand_release(mtd); diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/xway_nand.c index 3b28db4..0cf0ac0 100644 --- a/drivers/mtd/nand/xway_nand.c +++ b/drivers/mtd/nand/xway_nand.c @@ -89,7 +89,7 @@ static void xway_select_chip(struct mtd_info *mtd, int chip) static void xway_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); unsigned long nandaddr = (unsigned long) this->IO_ADDR_W; unsigned long flags; @@ -118,7 +118,7 @@ static int xway_dev_ready(struct mtd_info *mtd) static unsigned char xway_read_byte(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd_to_nand(mtd); unsigned long nandaddr = (unsigned long) this->IO_ADDR_R; unsigned long flags; int ret; -- cgit v1.1 From e488ca9f8d4f62c2dc36bfa5c32f68e7f05ab381 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 3 Dec 2015 14:47:32 -0800 Subject: doc: dt: mtd: partitions: add compatible property to "partitions" node As noted here [1], there are potentially future conflicts if we try to use MTD's "partitions" subnode to describe anything besides just the fixed-in-the-device-tree partitions currently described in this document. Particularly, there was a proposal to use this node for the AFS parser too. It can pose a (small) problem to try to differentiate the following nodes: // using binding as currently specified partitions { #address-cells = ; #size-cells = ; partition@0 { ...; }; }; and // proposed future binding partitions { compatible = "arm,arm-flash-structure"; }; It's especially difficult if other uses of this node start having subnodes. So, since the "partitions" node is new in v4.4, let's fixup the binding before release so that it requires a compatible property, so it's much clearer to distinguish. e.g.: // proposed partitions { compatible = "fixed-partitions"; #address-cells = ; #size-cells = ; partition@0 { ...; }; }; [1] Subject: "mtd: create a partition type device tree binding" http://lkml.kernel.org/g/20151113220039.GA74382@google.com http://lists.infradead.org/pipermail/linux-mtd/2015-November/063355.html http://lists.infradead.org/pipermail/linux-mtd/2015-November/063364.html Cc: Michal Suchanek Signed-off-by: Brian Norris Acked-by: Rob Herring --- drivers/mtd/ofpart.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 3e9c585..9ed6038 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -55,6 +55,9 @@ static int parse_ofpart_partitions(struct mtd_info *master, master->name, mtd_node->full_name); ofpart_node = mtd_node; dedicated = false; + } else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) { + /* The 'partitions' subnode might be used by another parser */ + return 0; } /* First count the subnodes */ -- cgit v1.1 From c3168d26c8deea4cc0202bb19341ab55247c3941 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 4 Dec 2015 15:25:13 -0800 Subject: mtd: ofpart: assign return argument exactly once It's easier to refactor these parsers if the return value gets assigned only once, just like every other MTD partition parser. This prepares for making the second arg to the parse_fn() const. This is OK if we construct the partitions completely first, and assign them to the return pointer only after we're done modifying them. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/ofpart.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 9046451..c7df2f1 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -29,6 +29,7 @@ static int parse_ofpart_partitions(struct mtd_info *master, struct mtd_partition **pparts, struct mtd_part_parser_data *data) { + struct mtd_partition *parts; struct device_node *mtd_node; struct device_node *ofpart_node; const char *partname; @@ -70,8 +71,8 @@ static int parse_ofpart_partitions(struct mtd_info *master, if (nr_parts == 0) return 0; - *pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL); - if (!*pparts) + parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + if (!parts) return -ENOMEM; i = 0; @@ -105,19 +106,19 @@ static int parse_ofpart_partitions(struct mtd_info *master, goto ofpart_fail; } - (*pparts)[i].offset = of_read_number(reg, a_cells); - (*pparts)[i].size = of_read_number(reg + a_cells, s_cells); + parts[i].offset = of_read_number(reg, a_cells); + parts[i].size = of_read_number(reg + a_cells, s_cells); partname = of_get_property(pp, "label", &len); if (!partname) partname = of_get_property(pp, "name", &len); - (*pparts)[i].name = partname; + parts[i].name = partname; if (of_get_property(pp, "read-only", &len)) - (*pparts)[i].mask_flags |= MTD_WRITEABLE; + parts[i].mask_flags |= MTD_WRITEABLE; if (of_get_property(pp, "lock", &len)) - (*pparts)[i].mask_flags |= MTD_POWERUP_LOCK; + parts[i].mask_flags |= MTD_POWERUP_LOCK; i++; } @@ -125,6 +126,7 @@ static int parse_ofpart_partitions(struct mtd_info *master, if (!nr_parts) goto ofpart_none; + *pparts = parts; return nr_parts; ofpart_fail: @@ -133,8 +135,7 @@ ofpart_fail: ret = -EINVAL; ofpart_none: of_node_put(pp); - kfree(*pparts); - *pparts = NULL; + kfree(parts); return ret; } @@ -147,6 +148,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, struct mtd_partition **pparts, struct mtd_part_parser_data *data) { + struct mtd_partition *parts; struct device_node *dp; int i, plen, nr_parts; const struct { @@ -168,32 +170,33 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, nr_parts = plen / sizeof(part[0]); - *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); - if (!*pparts) + parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + if (!parts) return -ENOMEM; names = of_get_property(dp, "partition-names", &plen); for (i = 0; i < nr_parts; i++) { - (*pparts)[i].offset = be32_to_cpu(part->offset); - (*pparts)[i].size = be32_to_cpu(part->len) & ~1; + parts[i].offset = be32_to_cpu(part->offset); + parts[i].size = be32_to_cpu(part->len) & ~1; /* bit 0 set signifies read only partition */ if (be32_to_cpu(part->len) & 1) - (*pparts)[i].mask_flags = MTD_WRITEABLE; + parts[i].mask_flags = MTD_WRITEABLE; if (names && (plen > 0)) { int len = strlen(names) + 1; - (*pparts)[i].name = names; + parts[i].name = names; plen -= len; names += len; } else { - (*pparts)[i].name = "unnamed"; + parts[i].name = "unnamed"; } part++; } + *pparts = parts; return nr_parts; } -- cgit v1.1 From b9adf469f8abb8a66f5795bbd8fe50fe201a14a1 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 4 Dec 2015 15:25:14 -0800 Subject: mtd: partitions: make parsers return 'const' partition arrays We only want to modify these arrays inside the parser "drivers", so the drivers should construct them however they like, then return them as immutable arrays. This will make other refactorings easier. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/afs.c | 2 +- drivers/mtd/ar7part.c | 2 +- drivers/mtd/bcm47xxpart.c | 2 +- drivers/mtd/bcm63xxpart.c | 2 +- drivers/mtd/cmdlinepart.c | 2 +- drivers/mtd/ofpart.c | 4 ++-- drivers/mtd/redboot.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c index e02dae3..d61b7ed 100644 --- a/drivers/mtd/afs.c +++ b/drivers/mtd/afs.c @@ -162,7 +162,7 @@ afs_read_iis_v1(struct mtd_info *mtd, struct image_info_v1 *iis, u_int ptr) } static int parse_afs_partitions(struct mtd_info *mtd, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { struct mtd_partition *parts; diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c index 9203b96..90575de 100644 --- a/drivers/mtd/ar7part.c +++ b/drivers/mtd/ar7part.c @@ -43,7 +43,7 @@ struct ar7_bin_rec { }; static int create_mtd_partitions(struct mtd_info *master, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { struct ar7_bin_rec header; diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index 92a6dd1..8282f47 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c @@ -82,7 +82,7 @@ out_default: } static int bcm47xxpart_parse(struct mtd_info *master, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { struct mtd_partition *parts; diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index cf02135..4409369 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -68,7 +68,7 @@ static int bcm63xx_detect_cfe(struct mtd_info *master) } static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { /* CFE, NVRAM and global Linux are always present */ diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 4204898..fbd5aff 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -304,7 +304,7 @@ static int mtdpart_setup_real(char *s) * the first one in the chain if a NULL mtd_id is passed in. */ static int parse_cmdline_partitions(struct mtd_info *master, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { unsigned long long offset; diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index c7df2f1..ede407d 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -26,7 +26,7 @@ static bool node_has_compatible(struct device_node *pp) } static int parse_ofpart_partitions(struct mtd_info *master, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { struct mtd_partition *parts; @@ -145,7 +145,7 @@ static struct mtd_part_parser ofpart_parser = { }; static int parse_ofoldpart_partitions(struct mtd_info *master, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { struct mtd_partition *parts; diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 11c3447..7623ac5 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c @@ -57,7 +57,7 @@ static inline int redboot_checksum(struct fis_image_desc *img) } static int parse_redboot_partitions(struct mtd_info *master, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { int nrparts = 0; -- cgit v1.1 From 5531ae4818fb04b9a30f87099f44595c1786f518 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 4 Dec 2015 15:25:15 -0800 Subject: mtd: partitions: rename MTD parser get/put We're going to reuse put_partition_parser(), so let's fix up the prefix naming a bit, to hopefully be more consistent. Also make convert to a true C function instead of a macro. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/mtdpart.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index c32b127..4a660ae 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -687,7 +687,7 @@ int add_mtd_partitions(struct mtd_info *master, static DEFINE_SPINLOCK(part_parser_lock); static LIST_HEAD(part_parsers); -static struct mtd_part_parser *get_partition_parser(const char *name) +static struct mtd_part_parser *mtd_part_parser_get(const char *name) { struct mtd_part_parser *p, *ret = NULL; @@ -704,7 +704,10 @@ static struct mtd_part_parser *get_partition_parser(const char *name) return ret; } -#define put_partition_parser(p) do { module_put((p)->owner); } while (0) +static inline void mtd_part_parser_put(const struct mtd_part_parser *p) +{ + module_put(p->owner); +} int __register_mtd_parser(struct mtd_part_parser *p, struct module *owner) { @@ -768,9 +771,9 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, for ( ; *types; types++) { pr_debug("%s: parsing partitions %s\n", master->name, *types); - parser = get_partition_parser(*types); + parser = mtd_part_parser_get(*types); if (!parser && !request_module("%s", *types)) - parser = get_partition_parser(*types); + parser = mtd_part_parser_get(*types); pr_debug("%s: got parser %s\n", master->name, parser ? parser->name : NULL); if (!parser) @@ -778,7 +781,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, ret = (*parser->parse_fn)(master, pparts, data); pr_debug("%s: parser %s: %i\n", master->name, parser->name, ret); - put_partition_parser(parser); + mtd_part_parser_put(parser); if (ret > 0) { printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", ret, parser->name, master->name); -- cgit v1.1 From c42c2710d64381fd48d36b278e0744aa683d93fe Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 4 Dec 2015 15:25:16 -0800 Subject: mtd: partitions: remove kmemdup() The use of kmemdup() complicates the error handling a bit. We don't actually need to allocate new memory, since this reference is treated as const, and it is copied into new memory by the partition registration code anyway. So remove it. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/mtdcore.c | 16 +++++++--------- drivers/mtd/mtdcore.h | 2 +- drivers/mtd/mtdpart.c | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 62f83b0..868ee52 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -532,7 +532,7 @@ out_error: } static int mtd_add_device_partitions(struct mtd_info *mtd, - struct mtd_partition *real_parts, + const struct mtd_partition *real_parts, int nbparts) { int ret; @@ -589,16 +589,12 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, int nr_parts) { int ret; - struct mtd_partition *real_parts = NULL; + const struct mtd_partition *real_parts = NULL; ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data); if (ret <= 0 && nr_parts && parts) { - real_parts = kmemdup(parts, sizeof(*parts) * nr_parts, - GFP_KERNEL); - if (!real_parts) - ret = -ENOMEM; - else - ret = nr_parts; + real_parts = parts; + ret = nr_parts; } /* Didn't come up with either parsed OR fallback partitions */ if (ret < 0) { @@ -628,7 +624,9 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, } out: - kfree(real_parts); + /* Cleanup any parsed partitions */ + if (real_parts != parts) + kfree(real_parts); return ret; } EXPORT_SYMBOL_GPL(mtd_device_parse_register); diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h index 7b03533..537ec66 100644 --- a/drivers/mtd/mtdcore.h +++ b/drivers/mtd/mtdcore.h @@ -11,7 +11,7 @@ int del_mtd_device(struct mtd_info *mtd); int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); int del_mtd_partitions(struct mtd_info *); int parse_mtd_partitions(struct mtd_info *master, const char * const *types, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data); int __init init_mtdchar(void); diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 4a660ae..898999c 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -760,7 +760,7 @@ static const char * const default_mtd_part_types[] = { * point to an array containing this number of &struct mtd_info objects. */ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, - struct mtd_partition **pparts, + const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { struct mtd_part_parser *parser; -- cgit v1.1 From 07fd2f871c5e3dfb8ff5eb9c4b44fdb4cf1aeff5 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 4 Dec 2015 15:25:17 -0800 Subject: mtd: partitions: pass around 'mtd_partitions' wrapper struct For some of the core partitioning code, it helps to keep info about the parsed partition (and who parsed them) together in one place. Signed-off-by: Brian Norris --- drivers/mtd/mtdcore.c | 33 +++++++++++++++++++-------------- drivers/mtd/mtdcore.h | 5 ++++- drivers/mtd/mtdpart.c | 15 ++++++++------- 3 files changed, 31 insertions(+), 22 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 868ee52..20b2b38 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -532,9 +532,10 @@ out_error: } static int mtd_add_device_partitions(struct mtd_info *mtd, - const struct mtd_partition *real_parts, - int nbparts) + struct mtd_partitions *parts) { + const struct mtd_partition *real_parts = parts->parts; + int nbparts = parts->nr_parts; int ret; if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { @@ -588,23 +589,27 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, const struct mtd_partition *parts, int nr_parts) { + struct mtd_partitions parsed; int ret; - const struct mtd_partition *real_parts = NULL; - ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data); - if (ret <= 0 && nr_parts && parts) { - real_parts = parts; - ret = nr_parts; - } - /* Didn't come up with either parsed OR fallback partitions */ - if (ret < 0) { + memset(&parsed, 0, sizeof(parsed)); + + ret = parse_mtd_partitions(mtd, types, &parsed, parser_data); + if ((ret < 0 || parsed.nr_parts == 0) && parts && nr_parts) { + /* Fall back to driver-provided partitions */ + parsed = (struct mtd_partitions){ + .parts = parts, + .nr_parts = nr_parts, + }; + } else if (ret < 0) { + /* Didn't come up with parsed OR fallback partitions */ pr_info("mtd: failed to find partitions; one or more parsers reports errors (%d)\n", ret); /* Don't abort on errors; we can still use unpartitioned MTD */ - ret = 0; + memset(&parsed, 0, sizeof(parsed)); } - ret = mtd_add_device_partitions(mtd, real_parts, ret); + ret = mtd_add_device_partitions(mtd, &parsed); if (ret) goto out; @@ -625,8 +630,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, out: /* Cleanup any parsed partitions */ - if (real_parts != parts) - kfree(real_parts); + if (parsed.parser) + kfree(parsed.parts); return ret; } EXPORT_SYMBOL_GPL(mtd_device_parse_register); diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h index 537ec66..ce81cc2 100644 --- a/drivers/mtd/mtdcore.h +++ b/drivers/mtd/mtdcore.h @@ -10,8 +10,11 @@ int add_mtd_device(struct mtd_info *mtd); int del_mtd_device(struct mtd_info *mtd); int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); int del_mtd_partitions(struct mtd_info *); + +struct mtd_partitions; + int parse_mtd_partitions(struct mtd_info *master, const char * const *types, - const struct mtd_partition **pparts, + struct mtd_partitions *pparts, struct mtd_part_parser_data *data); int __init init_mtdchar(void); diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 898999c..53517d7 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -743,7 +743,7 @@ static const char * const default_mtd_part_types[] = { * parse_mtd_partitions - parse MTD partitions * @master: the master partition (describes whole MTD device) * @types: names of partition parsers to try or %NULL - * @pparts: array of partitions found is returned here + * @pparts: info about partitions found is returned here * @data: MTD partition parser-specific data * * This function tries to find partition on MTD device @master. It uses MTD @@ -755,12 +755,11 @@ static const char * const default_mtd_part_types[] = { * * This function may return: * o a negative error code in case of failure - * o zero if no partitions were found - * o a positive number of found partitions, in which case on exit @pparts will - * point to an array containing this number of &struct mtd_info objects. + * o zero otherwise, and @pparts will describe the partitions, number of + * partitions, and the parser which parsed them */ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, - const struct mtd_partition **pparts, + struct mtd_partitions *pparts, struct mtd_part_parser_data *data) { struct mtd_part_parser *parser; @@ -778,14 +777,16 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, parser ? parser->name : NULL); if (!parser) continue; - ret = (*parser->parse_fn)(master, pparts, data); + ret = (*parser->parse_fn)(master, &pparts->parts, data); pr_debug("%s: parser %s: %i\n", master->name, parser->name, ret); mtd_part_parser_put(parser); if (ret > 0) { printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", ret, parser->name, master->name); - return ret; + pparts->nr_parts = ret; + pparts->parser = parser; + return 0; } /* * Stash the first error we see; only report it if no parser -- cgit v1.1 From adc83bf8896353603213754353dd66dae69e3d7f Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 9 Dec 2015 10:24:03 -0800 Subject: mtd: partitions: support a cleanup callback for parsers If partition parsers need to clean up their resources, we shouldn't assume that all memory will fit in a single kmalloc() that the caller can kfree(). We should allow the parser to provide a proper cleanup routine. Note that this means we need to keep a hold on the parser's module for a bit longer, and release it later with mtd_part_parser_put(). Alongside this, define a default callback that we'll automatically use if the parser doesn't provide one, so we can still retain the old behavior. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/mtdcore.c | 3 +-- drivers/mtd/mtdcore.h | 2 ++ drivers/mtd/mtdpart.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 20b2b38..89d811e 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -630,8 +630,7 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, out: /* Cleanup any parsed partitions */ - if (parsed.parser) - kfree(parsed.parts); + mtd_part_parser_cleanup(&parsed); return ret; } EXPORT_SYMBOL_GPL(mtd_device_parse_register); diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h index ce81cc2..55fdb8e 100644 --- a/drivers/mtd/mtdcore.h +++ b/drivers/mtd/mtdcore.h @@ -17,6 +17,8 @@ int parse_mtd_partitions(struct mtd_info *master, const char * const *types, struct mtd_partitions *pparts, struct mtd_part_parser_data *data); +void mtd_part_parser_cleanup(struct mtd_partitions *parts); + int __init init_mtdchar(void); void __exit cleanup_mtdchar(void); diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 53517d7..10bf304 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -709,10 +709,23 @@ static inline void mtd_part_parser_put(const struct mtd_part_parser *p) module_put(p->owner); } +/* + * Many partition parsers just expected the core to kfree() all their data in + * one chunk. Do that by default. + */ +static void mtd_part_parser_cleanup_default(const struct mtd_partition *pparts, + int nr_parts) +{ + kfree(pparts); +} + int __register_mtd_parser(struct mtd_part_parser *p, struct module *owner) { p->owner = owner; + if (!p->cleanup) + p->cleanup = &mtd_part_parser_cleanup_default; + spin_lock(&part_parser_lock); list_add(&p->list, &part_parsers); spin_unlock(&part_parser_lock); @@ -756,7 +769,9 @@ static const char * const default_mtd_part_types[] = { * This function may return: * o a negative error code in case of failure * o zero otherwise, and @pparts will describe the partitions, number of - * partitions, and the parser which parsed them + * partitions, and the parser which parsed them. Caller must release + * resources with mtd_part_parser_cleanup() when finished with the returned + * data. */ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, struct mtd_partitions *pparts, @@ -780,7 +795,6 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, ret = (*parser->parse_fn)(master, &pparts->parts, data); pr_debug("%s: parser %s: %i\n", master->name, parser->name, ret); - mtd_part_parser_put(parser); if (ret > 0) { printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", ret, parser->name, master->name); @@ -788,6 +802,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, pparts->parser = parser; return 0; } + mtd_part_parser_put(parser); /* * Stash the first error we see; only report it if no parser * succeeds @@ -798,6 +813,22 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, return err; } +void mtd_part_parser_cleanup(struct mtd_partitions *parts) +{ + const struct mtd_part_parser *parser; + + if (!parts) + return; + + parser = parts->parser; + if (parser) { + if (parser->cleanup) + parser->cleanup(parts->parts, parts->nr_parts); + + mtd_part_parser_put(parser); + } +} + int mtd_is_partition(const struct mtd_info *mtd) { struct mtd_part *part; -- cgit v1.1 From f49289ce64b7f7da4d7129666854b499b9d415eb Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 20 Nov 2015 16:26:11 -0200 Subject: mtd: spi-nor: Check the return value from read_sr() We should better check the return value from read_sr() and propagate it in the case of error. Signed-off-by: Fabio Estevam Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/spi-nor.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 3b2460e..7e5051e 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -478,11 +478,13 @@ static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) { struct mtd_info *mtd = &nor->mtd; - u8 status_old, status_new; + int status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; status_old = read_sr(nor); + if (status_old < 0) + return status_old; /* SPI NOR always locks to the end */ if (ofs + len != mtd->size) { @@ -528,11 +530,13 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) { struct mtd_info *mtd = &nor->mtd; - uint8_t status_old, status_new; + int status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; status_old = read_sr(nor); + if (status_old < 0) + return status_old; /* Cannot unlock; would unlock larger region than requested */ if (stm_is_locked_sr(nor, status_old, ofs - mtd->erasesize, @@ -1032,6 +1036,8 @@ static int macronix_quad_enable(struct spi_nor *nor) int ret, val; val = read_sr(nor); + if (val < 0) + return val; write_enable(nor); write_sr(nor, val | SR_QUAD_EN_MX); -- cgit v1.1 From d5c5620167d0fde476a0c0d8bb1f5751bcc1e495 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 8 Dec 2015 18:40:59 +0100 Subject: mtd: nand: Confine MTD_NAND_SH_FLCTL to SUPERH As of commit a521422ea4ae6128 ("ARM: shmobile: mackerel: Remove Legacy C board code"), the Renesas SuperH FLCTL driver is no longer used on ARM SH-Mobile SoCs. Restrict the dependencies, unless compile-testing. Signed-off-by: Geert Uytterhoeven Signed-off-by: Brian Norris --- drivers/mtd/nand/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 2896640..6c71f62 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -480,7 +480,7 @@ config MTD_NAND_MXC config MTD_NAND_SH_FLCTL tristate "Support for NAND on Renesas SuperH FLCTL" - depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST + depends on SUPERH || COMPILE_TEST depends on HAS_IOMEM depends on HAS_DMA help -- cgit v1.1 From 5c05bc00721bbe223ce93d8873ac42c8170d809c Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Wed, 9 Dec 2015 20:42:25 +0000 Subject: mtd: brcmnand: Request and enable the clock if present Attempt to enable a clock named "nand" as some SoCs have a clock for the controller that needs to be enabled. Signed-off-by: Simon Arlott Reviewed-by: Florian Fainelli Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.c | 64 ++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 14 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 190a99a..dca8162 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -11,6 +11,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -122,6 +123,9 @@ struct brcmnand_controller { /* Some SoCs provide custom interrupt status register(s) */ struct brcmnand_soc *soc; + /* Some SoCs have a gateable clock for the controller */ + struct clk *clk; + int cmd_pending; bool dma_pending; struct completion done; @@ -2127,10 +2131,24 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) if (IS_ERR(ctrl->nand_base)) return PTR_ERR(ctrl->nand_base); + /* Enable clock before using NAND registers */ + ctrl->clk = devm_clk_get(dev, "nand"); + if (!IS_ERR(ctrl->clk)) { + ret = clk_prepare_enable(ctrl->clk); + if (ret) + return ret; + } else { + ret = PTR_ERR(ctrl->clk); + if (ret == -EPROBE_DEFER) + return ret; + + ctrl->clk = NULL; + } + /* Initialize NAND revision */ ret = brcmnand_revision_init(ctrl); if (ret) - return ret; + goto err; /* * Most chips have this cache at a fixed offset within 'nand' block. @@ -2139,8 +2157,10 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-cache"); if (res) { ctrl->nand_fc = devm_ioremap_resource(dev, res); - if (IS_ERR(ctrl->nand_fc)) - return PTR_ERR(ctrl->nand_fc); + if (IS_ERR(ctrl->nand_fc)) { + ret = PTR_ERR(ctrl->nand_fc); + goto err; + } } else { ctrl->nand_fc = ctrl->nand_base + ctrl->reg_offsets[BRCMNAND_FC_BASE]; @@ -2150,8 +2170,10 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-dma"); if (res) { ctrl->flash_dma_base = devm_ioremap_resource(dev, res); - if (IS_ERR(ctrl->flash_dma_base)) - return PTR_ERR(ctrl->flash_dma_base); + if (IS_ERR(ctrl->flash_dma_base)) { + ret = PTR_ERR(ctrl->flash_dma_base); + goto err; + } flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */ flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0); @@ -2160,13 +2182,16 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) ctrl->dma_desc = dmam_alloc_coherent(dev, sizeof(*ctrl->dma_desc), &ctrl->dma_pa, GFP_KERNEL); - if (!ctrl->dma_desc) - return -ENOMEM; + if (!ctrl->dma_desc) { + ret = -ENOMEM; + goto err; + } ctrl->dma_irq = platform_get_irq(pdev, 1); if ((int)ctrl->dma_irq < 0) { dev_err(dev, "missing FLASH_DMA IRQ\n"); - return -ENODEV; + ret = -ENODEV; + goto err; } ret = devm_request_irq(dev, ctrl->dma_irq, @@ -2175,7 +2200,7 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) if (ret < 0) { dev_err(dev, "can't allocate IRQ %d: error %d\n", ctrl->dma_irq, ret); - return ret; + goto err; } dev_info(dev, "enabling FLASH_DMA\n"); @@ -2199,7 +2224,8 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) ctrl->irq = platform_get_irq(pdev, 0); if ((int)ctrl->irq < 0) { dev_err(dev, "no IRQ defined\n"); - return -ENODEV; + ret = -ENODEV; + goto err; } /* @@ -2223,7 +2249,7 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) if (ret < 0) { dev_err(dev, "can't allocate IRQ %d: error %d\n", ctrl->irq, ret); - return ret; + goto err; } for_each_available_child_of_node(dn, child) { @@ -2233,7 +2259,8 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); if (!host) { of_node_put(child); - return -ENOMEM; + ret = -ENOMEM; + goto err; } host->pdev = pdev; host->ctrl = ctrl; @@ -2249,10 +2276,17 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) } /* No chip-selects could initialize properly */ - if (list_empty(&ctrl->host_list)) - return -ENODEV; + if (list_empty(&ctrl->host_list)) { + ret = -ENODEV; + goto err; + } return 0; + +err: + clk_disable_unprepare(ctrl->clk); + return ret; + } EXPORT_SYMBOL_GPL(brcmnand_probe); @@ -2264,6 +2298,8 @@ int brcmnand_remove(struct platform_device *pdev) list_for_each_entry(host, &ctrl->host_list, node) nand_release(&host->mtd); + clk_disable_unprepare(ctrl->clk); + dev_set_drvdata(&pdev->dev, NULL); return 0; -- cgit v1.1 From af3855dd191799a797e80dc55ecd5a9a226c3e2c Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Wed, 9 Dec 2015 20:43:54 +0000 Subject: mtd: brcmnand: Add support for the BCM6368 The BCM6368 has a NAND interrupt register with combined status and enable registers. As the BCM6328, BCM6362 and BCM6368 all use v2.1 controllers, the first variant that will work with this driver is the BCM63268 using a v4.0 controller. Set up the device by disabling and acking all interrupts, then handle the CTRL_READY interrupt. Signed-off-by: Simon Arlott Reviewed-by: Florian Fainelli Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/Makefile | 1 + drivers/mtd/nand/brcmnand/bcm6368_nand.c | 145 +++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 drivers/mtd/nand/brcmnand/bcm6368_nand.c (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/Makefile b/drivers/mtd/nand/brcmnand/Makefile index 3b1fbfd..b28ffb59 100644 --- a/drivers/mtd/nand/brcmnand/Makefile +++ b/drivers/mtd/nand/brcmnand/Makefile @@ -2,5 +2,6 @@ # more specific iproc_nand.o, for instance obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o +obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6368_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o diff --git a/drivers/mtd/nand/brcmnand/bcm6368_nand.c b/drivers/mtd/nand/brcmnand/bcm6368_nand.c new file mode 100644 index 0000000..7f5359b --- /dev/null +++ b/drivers/mtd/nand/brcmnand/bcm6368_nand.c @@ -0,0 +1,145 @@ +/* + * Copyright 2015 Simon Arlott + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Derived from bcm63138_nand.c: + * Copyright © 2015 Broadcom Corporation + * + * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h: + * Copyright 2000-2010 Broadcom Corporation + * + * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c: + * Copyright 2000-2010 Broadcom Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "brcmnand.h" + +struct bcm6368_nand_soc { + struct brcmnand_soc soc; + void __iomem *base; +}; + +#define BCM6368_NAND_INT 0x00 +#define BCM6368_NAND_STATUS_SHIFT 0 +#define BCM6368_NAND_STATUS_MASK (0xfff << BCM6368_NAND_STATUS_SHIFT) +#define BCM6368_NAND_ENABLE_SHIFT 16 +#define BCM6368_NAND_ENABLE_MASK (0xffff << BCM6368_NAND_ENABLE_SHIFT) +#define BCM6368_NAND_BASE_ADDR0 0x04 +#define BCM6368_NAND_BASE_ADDR1 0x0c + +enum { + BCM6368_NP_READ = BIT(0), + BCM6368_BLOCK_ERASE = BIT(1), + BCM6368_COPY_BACK = BIT(2), + BCM6368_PAGE_PGM = BIT(3), + BCM6368_CTRL_READY = BIT(4), + BCM6368_DEV_RBPIN = BIT(5), + BCM6368_ECC_ERR_UNC = BIT(6), + BCM6368_ECC_ERR_CORR = BIT(7), +}; + +static bool bcm6368_nand_intc_ack(struct brcmnand_soc *soc) +{ + struct bcm6368_nand_soc *priv = + container_of(soc, struct bcm6368_nand_soc, soc); + void __iomem *mmio = priv->base + BCM6368_NAND_INT; + u32 val = brcmnand_readl(mmio); + + if (val & (BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT)) { + /* Ack interrupt */ + val &= ~BCM6368_NAND_STATUS_MASK; + val |= BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT; + brcmnand_writel(val, mmio); + return true; + } + + return false; +} + +static void bcm6368_nand_intc_set(struct brcmnand_soc *soc, bool en) +{ + struct bcm6368_nand_soc *priv = + container_of(soc, struct bcm6368_nand_soc, soc); + void __iomem *mmio = priv->base + BCM6368_NAND_INT; + u32 val = brcmnand_readl(mmio); + + /* Don't ack any interrupts */ + val &= ~BCM6368_NAND_STATUS_MASK; + + if (en) + val |= BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT; + else + val &= ~(BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT); + + brcmnand_writel(val, mmio); +} + +static int bcm6368_nand_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct bcm6368_nand_soc *priv; + struct brcmnand_soc *soc; + struct resource *res; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + soc = &priv->soc; + + res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "nand-int-base"); + if (!res) + return -EINVAL; + + priv->base = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + soc->ctlrdy_ack = bcm6368_nand_intc_ack; + soc->ctlrdy_set_enabled = bcm6368_nand_intc_set; + + /* Disable and ack all interrupts */ + brcmnand_writel(0, priv->base + BCM6368_NAND_INT); + brcmnand_writel(BCM6368_NAND_STATUS_MASK, + priv->base + BCM6368_NAND_INT); + + return brcmnand_probe(pdev, soc); +} + +static const struct of_device_id bcm6368_nand_of_match[] = { + { .compatible = "brcm,nand-bcm6368" }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm6368_nand_of_match); + +static struct platform_driver bcm6368_nand_driver = { + .probe = bcm6368_nand_probe, + .remove = brcmnand_remove, + .driver = { + .name = "bcm6368_nand", + .pm = &brcmnand_pm_ops, + .of_match_table = bcm6368_nand_of_match, + } +}; +module_platform_driver(bcm6368_nand_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Simon Arlott"); +MODULE_DESCRIPTION("NAND driver for BCM6368"); -- cgit v1.1 From 207f6582dd9adb8e2ed64b4c64d6d5c009e5bbf9 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 9 Dec 2015 18:33:17 -0800 Subject: mtd: brcmnand: defer to devm_ioremap_resource() for error checking devm_ioremap_resource() does error checking on the 'res' argument, so drop the error check in bcm6368_nand.c. Signed-off-by: Brian Norris Tested-by: Simon Arlott --- drivers/mtd/nand/brcmnand/bcm6368_nand.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/bcm6368_nand.c b/drivers/mtd/nand/brcmnand/bcm6368_nand.c index 7f5359b..34c91b0 100644 --- a/drivers/mtd/nand/brcmnand/bcm6368_nand.c +++ b/drivers/mtd/nand/brcmnand/bcm6368_nand.c @@ -105,9 +105,6 @@ static int bcm6368_nand_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-int-base"); - if (!res) - return -EINVAL; - priv->base = devm_ioremap_resource(dev, res); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); -- cgit v1.1 From 320092a05dab2f44819c42f33d6b51efb6c474f2 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Dec 2015 15:02:34 +0100 Subject: mtd: nand: denali: add missing nand_release() call in denali_remove() Unregister the NAND device from the NAND subsystem when removing a denali NAND controller, otherwise the MTD attached to the NAND device is still exposed by the MTD layer, and accesses to this device will likely crash the system. Fixes: 2a0a288ec258 ("mtd: denali: split the generic driver and PCI layer") Signed-off-by: Boris Brezillon Acked-by: Dinh Nguyen Signed-off-by: Brian Norris --- drivers/mtd/nand/denali.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 67eb2be..9a5035c 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1622,9 +1622,16 @@ EXPORT_SYMBOL(denali_init); /* driver exit point */ void denali_remove(struct denali_nand_info *denali) { + /* + * Pre-compute DMA buffer size to avoid any problems in case + * nand_release() ever changes in a way that mtd->writesize and + * mtd->oobsize are not reliable after this call. + */ + int bufsize = denali->mtd.writesize + denali->mtd.oobsize; + + nand_release(&denali->mtd); denali_irq_cleanup(denali->irq, denali); - dma_unmap_single(denali->dev, denali->buf.dma_buf, - denali->mtd.writesize + denali->mtd.oobsize, + dma_unmap_single(denali->dev, denali->buf.dma_buf, bufsize, DMA_BIDIRECTIONAL); } EXPORT_SYMBOL(denali_remove); -- cgit v1.1 From 665d2c2848f14c0c2a2e89192bde9073c4d352f7 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 8 Dec 2015 17:04:59 -0800 Subject: mtd: bcm47xxnflash: really unregister NAND on device removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The field bcma_nflash::mtd is never set to be non-zero anywhere, but we test for it in the removal path. So the MTD is never unregistered. Also, we should use nand_release(), not mtd_device_unregister(). Finally, we don't need to use the 'platdata' for stashing/retrieving our *driver* data -- that's what *_{get,set}_drvdata() are for. So, kill off bcm_nflash::mtd, and stash the struct bcm47xxnflash in drvdata instead. Also move the forward declaration of mtd_info up a bit, since struct bcma_sflash should be using it. Caught while inspecting other changes being made to this driver. Compile tested only. Signed-off-by: Brian Norris Cc: "Rafał Miłecki" Cc: linux-wireless@vger.kernel.org Acked-by: Boris Brezillon --- drivers/mtd/nand/bcm47xxnflash/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c index 9ba0c0f..0b3acc4 100644 --- a/drivers/mtd/nand/bcm47xxnflash/main.c +++ b/drivers/mtd/nand/bcm47xxnflash/main.c @@ -49,6 +49,8 @@ static int bcm47xxnflash_probe(struct platform_device *pdev) return err; } + platform_set_drvdata(pdev, b47n); + err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0); if (err) { pr_err("Failed to register MTD device: %d\n", err); @@ -60,10 +62,9 @@ static int bcm47xxnflash_probe(struct platform_device *pdev) static int bcm47xxnflash_remove(struct platform_device *pdev) { - struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev); + struct bcm47xxnflash *nflash = platform_get_drvdata(pdev); - if (nflash->mtd) - mtd_device_unregister(nflash->mtd); + nand_release(&nflash->mtd); return 0; } -- cgit v1.1 From 97cb69dd800a471c3ee2467be3826badd9c12883 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 20 Nov 2015 15:44:20 +0530 Subject: UBI: fix return error code We are checking dfs_rootdir for error value or NULL. But in the conditional ternary operator we returned -ENODEV if dfs_rootdir contains an error value and returned PTR_ERR(dfs_rootdir) if dfs_rootdir is NULL. So in the case of dfs_rootdir being NULL we actually assigned 0 to err and returned it to the caller implying a success. Lets return -ENODEV when dfs_rootdir is NULL else return PTR_ERR(dfs_rootdir). Signed-off-by: Sudip Mukherjee Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index b077e43..c4cb15a 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -236,7 +236,7 @@ int ubi_debugfs_init(void) dfs_rootdir = debugfs_create_dir("ubi", NULL); if (IS_ERR_OR_NULL(dfs_rootdir)) { - int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir); + int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV; pr_err("UBI error: cannot create \"ubi\" debugfs directory, error %d\n", err); -- cgit v1.1 From 2e69d4912f2fc9d4cd952311d58ceae1cd83057b Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 20 Nov 2015 14:10:54 -0800 Subject: UBI: fix use of "VID" vs. "EC" in header self-check Looks like a typo, using UBI_EC_HDR_SIZE_CRC (note the "EC") to compute the CRC for the VID header. This shouldn't cause any functional change, as both structures are 64 bytes. Verified with: BUILD_BUG_ON(UBI_VID_HDR_SIZE_CRC != UBI_EC_HDR_SIZE_CRC); Reported here: http://lists.infradead.org/pipermail/linux-mtd/2013-September/048570.html Reported by: Bill Pringlemeir Signed-off-by: Brian Norris Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 1fc23e4..10cf3b5 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -1299,7 +1299,7 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) goto exit; - crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC); + crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC); hdr_crc = be32_to_cpu(vid_hdr->hdr_crc); if (hdr_crc != crc) { ubi_err(ubi, "bad VID header CRC at PEB %d, calculated %#08x, read %#08x", -- cgit v1.1 From 1a31b20cd81d5cbc7ec6e24cb08066009a1ca32d Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Thu, 26 Nov 2015 21:23:48 +0100 Subject: mtd: ubi: fixup error correction in do_sync_erase() Since fastmap we gained do_sync_erase(). This function can return an error and its error handling isn't obvious. First the memory allocation for struct ubi_work can fail and as such struct ubi_wl_entry is leaked. However if the memory allocation succeeds then the tail function takes care of the struct ubi_wl_entry. A free here could result in a double free. To make the error handling simpler, I split the tail function into one piece which does the work and another which frees the struct ubi_work which is passed as argument. As result do_sync_erase() can keep the struct on stack and we get rid of one error source. Cc: Fixes: 8199b901a ("UBI: Add fastmap support to the WL sub-system") Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/wl.c | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index eb4489f9..f73233f 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -603,6 +603,7 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, return 0; } +static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk); /** * do_sync_erase - run the erase worker synchronously. * @ubi: UBI device description object @@ -615,20 +616,16 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, static int do_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int vol_id, int lnum, int torture) { - struct ubi_work *wl_wrk; + struct ubi_work wl_wrk; dbg_wl("sync erase of PEB %i", e->pnum); - wl_wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS); - if (!wl_wrk) - return -ENOMEM; - - wl_wrk->e = e; - wl_wrk->vol_id = vol_id; - wl_wrk->lnum = lnum; - wl_wrk->torture = torture; + wl_wrk.e = e; + wl_wrk.vol_id = vol_id; + wl_wrk.lnum = lnum; + wl_wrk.torture = torture; - return erase_worker(ubi, wl_wrk, 0); + return __erase_worker(ubi, &wl_wrk); } /** @@ -1014,7 +1011,7 @@ out_unlock: } /** - * erase_worker - physical eraseblock erase worker function. + * __erase_worker - physical eraseblock erase worker function. * @ubi: UBI device description object * @wl_wrk: the work object * @shutdown: non-zero if the worker has to free memory and exit @@ -1025,8 +1022,7 @@ out_unlock: * needed. Returns zero in case of success and a negative error code in case of * failure. */ -static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, - int shutdown) +static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk) { struct ubi_wl_entry *e = wl_wrk->e; int pnum = e->pnum; @@ -1034,21 +1030,11 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, int lnum = wl_wrk->lnum; int err, available_consumed = 0; - if (shutdown) { - dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec); - kfree(wl_wrk); - wl_entry_destroy(ubi, e); - return 0; - } - dbg_wl("erase PEB %d EC %d LEB %d:%d", pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum); err = sync_erase(ubi, e, wl_wrk->torture); if (!err) { - /* Fine, we've erased it successfully */ - kfree(wl_wrk); - spin_lock(&ubi->wl_lock); wl_tree_add(e, &ubi->free); ubi->free_count++; @@ -1066,7 +1052,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, } ubi_err(ubi, "failed to erase PEB %d, error %d", pnum, err); - kfree(wl_wrk); if (err == -EINTR || err == -ENOMEM || err == -EAGAIN || err == -EBUSY) { @@ -1150,6 +1135,25 @@ out_ro: return err; } +static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, + int shutdown) +{ + int ret; + + if (shutdown) { + struct ubi_wl_entry *e = wl_wrk->e; + + dbg_wl("cancel erasure of PEB %d EC %d", e->pnum, e->ec); + kfree(wl_wrk); + wl_entry_destroy(ubi, e); + return 0; + } + + ret = __erase_worker(ubi, wl_wrk); + kfree(wl_wrk); + return ret; +} + /** * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system. * @ubi: UBI device description object -- cgit v1.1 From 6b238de189f69dc77d660d4cce62eed15547f4c3 Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Thu, 26 Nov 2015 21:23:49 +0100 Subject: mtd: ubi: don't leak e if schedule_erase() fails If __erase_worker() fails to erase the EB and schedule_erase() fails as well to do anything about it then we go RO. But that is not a reason to leak the e argument here. Therefore clean up e. Cc: Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/wl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index f73233f..5606563 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1060,6 +1060,7 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk) /* Re-schedule the LEB for erasure */ err1 = schedule_erase(ubi, e, vol_id, lnum, 0); if (err1) { + wl_entry_destroy(ubi, e); err = err1; goto out_ro; } -- cgit v1.1 From ce7f28531fe05fcabc8ccff8b6dc9b4b296a811e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 18 Dec 2015 14:15:17 +0100 Subject: mtd: omap_elm: print interrupt resource using %pr When CONFIG_LPAE is set on ARM, resource_size_t is 64-bit wide and we get a warning about an incorrect format string for printing the interrupt number in elm_probe: drivers/mtd/nand/omap_elm.c: In function 'elm_probe': drivers/mtd/nand/omap_elm.c:417:23: warning: format '%i' expects argument of type 'int', but argument 3 has type 'resource_size_t {aka long long unsigned int}' [-Wformat=] This patch avoids the type mismatch by printing the interrupt as a resource using the %pr format string. Signed-off-by: Arnd Bergmann Signed-off-by: Brian Norris --- drivers/mtd/nand/omap_elm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/omap_elm.c b/drivers/mtd/nand/omap_elm.c index 235ec79..a3f32f9 100644 --- a/drivers/mtd/nand/omap_elm.c +++ b/drivers/mtd/nand/omap_elm.c @@ -414,7 +414,7 @@ static int elm_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, irq->start, elm_isr, 0, pdev->name, info); if (ret) { - dev_err(&pdev->dev, "failure requesting irq %i\n", irq->start); + dev_err(&pdev->dev, "failure requesting %pr\n", irq); return ret; } -- cgit v1.1 From 277af429fb40cf484c4a76c0b4cde2afc3e0c3d0 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:46 +0100 Subject: mtd: nand: fsmc: create and use mtd_to_fsmc() Create and use mtd_to_fsmc() to avoid duplication of container_of(mtd, struct fsmc_nand_data, mtd) calls. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/fsmc_nand.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 1c6c399..499fc59 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -326,13 +326,18 @@ struct fsmc_nand_data { void (*select_chip)(uint32_t bank, uint32_t busw); }; +static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd) +{ + return container_of(mtd, struct fsmc_nand_data, mtd); +} + /* Assert CS signal based on chipnr */ static void fsmc_select_chip(struct mtd_info *mtd, int chipnr) { struct nand_chip *chip = mtd_to_nand(mtd); struct fsmc_nand_data *host; - host = container_of(mtd, struct fsmc_nand_data, mtd); + host = mtd_to_fsmc(mtd); switch (chipnr) { case -1: @@ -359,8 +364,7 @@ static void fsmc_select_chip(struct mtd_info *mtd, int chipnr) static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *this = mtd_to_nand(mtd); - struct fsmc_nand_data *host = container_of(mtd, - struct fsmc_nand_data, mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(mtd); void __iomem *regs = host->regs_va; unsigned int bank = host->bank; @@ -445,8 +449,7 @@ static void fsmc_nand_setup(void __iomem *regs, uint32_t bank, */ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) { - struct fsmc_nand_data *host = container_of(mtd, - struct fsmc_nand_data, mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(mtd); void __iomem *regs = host->regs_va; uint32_t bank = host->bank; @@ -466,8 +469,7 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, uint8_t *ecc) { - struct fsmc_nand_data *host = container_of(mtd, - struct fsmc_nand_data, mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(mtd); void __iomem *regs = host->regs_va; uint32_t bank = host->bank; uint32_t ecc_tmp; @@ -517,8 +519,7 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, uint8_t *ecc) { - struct fsmc_nand_data *host = container_of(mtd, - struct fsmc_nand_data, mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(mtd); void __iomem *regs = host->regs_va; uint32_t bank = host->bank; uint32_t ecc_tmp; @@ -674,9 +675,8 @@ static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) */ static void fsmc_read_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len) { - struct fsmc_nand_data *host; + struct fsmc_nand_data *host = mtd_to_fsmc(mtd); - host = container_of(mtd, struct fsmc_nand_data, mtd); dma_xfer(host, buf, len, DMA_FROM_DEVICE); } @@ -689,9 +689,8 @@ static void fsmc_read_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len) static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, int len) { - struct fsmc_nand_data *host; + struct fsmc_nand_data *host = mtd_to_fsmc(mtd); - host = container_of(mtd, struct fsmc_nand_data, mtd); dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE); } @@ -712,8 +711,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct fsmc_nand_data *host = container_of(mtd, - struct fsmc_nand_data, mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(mtd); struct fsmc_eccplace *ecc_place = host->ecc_place; int i, j, s, stat, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -782,9 +780,8 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc) { - struct fsmc_nand_data *host = container_of(mtd, - struct fsmc_nand_data, mtd); struct nand_chip *chip = mtd_to_nand(mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(mtd); void __iomem *regs = host->regs_va; unsigned int bank = host->bank; uint32_t err_idx[8]; -- cgit v1.1 From faee6c358b0f1906f0f653a9d9f8beb5ebef174f Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:47 +0100 Subject: mtd: nand: nuc900: create and use mtd_to_nuc900() Create and use mtd_to_nuc900() instead of direct container_of() calls. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nuc900_nand.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 8148cd6..65908c0 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -62,6 +62,11 @@ struct nuc900_nand { spinlock_t lock; }; +static inline struct nuc900_nand *mtd_to_nuc900(struct mtd_info *mtd) +{ + return container_of(mtd, struct nuc900_nand, mtd); +} + static const struct mtd_partition partitions[] = { { .name = "NAND FS 0", @@ -78,9 +83,7 @@ static const struct mtd_partition partitions[] = { static unsigned char nuc900_nand_read_byte(struct mtd_info *mtd) { unsigned char ret; - struct nuc900_nand *nand; - - nand = container_of(mtd, struct nuc900_nand, mtd); + struct nuc900_nand *nand = mtd_to_nuc900(mtd); ret = (unsigned char)read_data_reg(nand); @@ -91,9 +94,7 @@ static void nuc900_nand_read_buf(struct mtd_info *mtd, unsigned char *buf, int len) { int i; - struct nuc900_nand *nand; - - nand = container_of(mtd, struct nuc900_nand, mtd); + struct nuc900_nand *nand = mtd_to_nuc900(mtd); for (i = 0; i < len; i++) buf[i] = (unsigned char)read_data_reg(nand); @@ -103,9 +104,7 @@ static void nuc900_nand_write_buf(struct mtd_info *mtd, const unsigned char *buf, int len) { int i; - struct nuc900_nand *nand; - - nand = container_of(mtd, struct nuc900_nand, mtd); + struct nuc900_nand *nand = mtd_to_nuc900(mtd); for (i = 0; i < len; i++) write_data_reg(nand, buf[i]); @@ -124,11 +123,9 @@ static int nuc900_check_rb(struct nuc900_nand *nand) static int nuc900_nand_devready(struct mtd_info *mtd) { - struct nuc900_nand *nand; + struct nuc900_nand *nand = mtd_to_nuc900(mtd); int ready; - nand = container_of(mtd, struct nuc900_nand, mtd); - ready = (nuc900_check_rb(nand)) ? 1 : 0; return ready; } @@ -137,9 +134,7 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { register struct nand_chip *chip = mtd_to_nand(mtd); - struct nuc900_nand *nand; - - nand = container_of(mtd, struct nuc900_nand, mtd); + struct nuc900_nand *nand = mtd_to_nuc900(mtd); if (command == NAND_CMD_READOOB) { column += mtd->writesize; -- cgit v1.1 From 4578ea9a9989d19633b005b9bdc23729ceb58a1b Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:48 +0100 Subject: mtd: nand: omap2: create and use mtd_to_omap() Define and use mtd_to_omap() instead of container_of(); Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/omap2.c | 55 ++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 34 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 944a74e..1fb40db 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -177,6 +177,10 @@ struct omap_nand_info { struct device_node *of_node; }; +static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd) +{ + return container_of(mtd, struct omap_nand_info, mtd); +} /** * omap_prefetch_enable - configures and starts prefetch transfer * @cs: cs (chip select) number @@ -247,8 +251,7 @@ static int omap_prefetch_reset(int cs, struct omap_nand_info *info) */ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); if (cmd != NAND_CMD_NONE) { if (ctrl & NAND_CLE) @@ -283,8 +286,7 @@ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len) */ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); u_char *p = (u_char *)buf; u32 status = 0; @@ -319,8 +321,7 @@ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len) */ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); u16 *p = (u16 *) buf; u32 status = 0; /* FIXME try bursts of writesw() or DMA ... */ @@ -344,8 +345,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) */ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); uint32_t r_count = 0; int ret = 0; u32 *p = (u32 *)buf; @@ -392,8 +392,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) static void omap_write_buf_pref(struct mtd_info *mtd, const u_char *buf, int len) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); uint32_t w_count = 0; int i = 0, ret = 0; u16 *p = (u16 *)buf; @@ -458,8 +457,7 @@ static void omap_nand_dma_callback(void *data) static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, unsigned int len, int is_write) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); struct dma_async_tx_descriptor *tx; enum dma_data_direction dir = is_write ? DMA_TO_DEVICE : DMA_FROM_DEVICE; @@ -623,8 +621,7 @@ done: */ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); int ret = 0; if (len <= mtd->oobsize) { @@ -671,8 +668,7 @@ out_copy: static void omap_write_buf_irq_pref(struct mtd_info *mtd, const u_char *buf, int len) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); int ret = 0; unsigned long tim, limit; u32 val; @@ -886,8 +882,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ static int omap_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); int blockCnt = 0, i = 0, ret = 0; int stat = 0; @@ -928,8 +923,7 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat, static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); u32 val; val = readl(info->reg.gpmc_ecc_config); @@ -953,8 +947,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, */ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) { - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); struct nand_chip *chip = mtd_to_nand(mtd); unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; u32 val; @@ -1002,8 +995,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) { struct nand_chip *this = mtd_to_nand(mtd); - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); unsigned long timeo = jiffies; int status, state = this->state; @@ -1031,8 +1023,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) static int omap_dev_ready(struct mtd_info *mtd) { unsigned int val = 0; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); val = readl(info->reg.gpmc_status); @@ -1058,8 +1049,7 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) { unsigned int bch_type; unsigned int dev_width, nsectors; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); enum omap_ecc ecc_opt = info->ecc_opt; struct nand_chip *chip = mtd_to_nand(mtd); u32 val, wr_mode; @@ -1162,8 +1152,7 @@ static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2, static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, u_char *ecc_calc) { - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); int eccbytes = info->nand.ecc.bytes; struct gpmc_nand_regs *gpmc_regs = &info->reg; u8 *ecc_code; @@ -1334,8 +1323,7 @@ static int erased_sector_bitflips(u_char *data, u_char *oob, static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, u_char *read_ecc, u_char *calc_ecc) { - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); struct nand_ecc_ctrl *ecc = &info->nand.ecc; int eccsteps = info->nand.ecc.steps; int i , j, stat = 0; @@ -2057,8 +2045,7 @@ static int omap_nand_remove(struct platform_device *pdev) { struct mtd_info *mtd = platform_get_drvdata(pdev); struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); + struct omap_nand_info *info = mtd_to_omap(mtd); if (nand_chip->ecc.priv) { nand_bch_free(nand_chip->ecc.priv); nand_chip->ecc.priv = NULL; -- cgit v1.1 From 187d6ada2a129b3829c81b3e4f4bdf660859bb11 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:49 +0100 Subject: mtd: nand: ams-delta: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance instead of allocating our own. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/ams-delta.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index b2b49c4..0f638c6 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -183,19 +183,16 @@ static int ams_delta_init(struct platform_device *pdev) return -ENXIO; /* Allocate memory for MTD device structure and private data */ - ams_delta_mtd = kzalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), GFP_KERNEL); - if (!ams_delta_mtd) { + this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); + if (!this) { printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n"); err = -ENOMEM; goto out; } + ams_delta_mtd = nand_to_mtd(this); ams_delta_mtd->owner = THIS_MODULE; - /* Get pointer to private data */ - this = (struct nand_chip *) (&ams_delta_mtd[1]); - /* Link the private data with the MTD structure */ ams_delta_mtd->priv = this; @@ -256,7 +253,7 @@ out_gpio: gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); iounmap(io_base); out_free: - kfree(ams_delta_mtd); + kfree(this); out: return err; } @@ -276,7 +273,7 @@ static int ams_delta_cleanup(struct platform_device *pdev) iounmap(io_base); /* Free the MTD device structure */ - kfree(ams_delta_mtd); + kfree(mtd_to_nand(ams_delta_mtd)); return 0; } -- cgit v1.1 From ac01efebb1075a51a2803237159a440b71383117 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:50 +0100 Subject: mtd: nand: atmel: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index edd191a..9ba28312 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -116,7 +116,6 @@ static struct atmel_nfc nand_nfc; struct atmel_nand_host { struct nand_chip nand_chip; - struct mtd_info mtd; void __iomem *io_base; dma_addr_t io_phys; struct atmel_nand_data board; @@ -317,8 +316,10 @@ static int nfc_set_sram_bank(struct atmel_nand_host *host, unsigned int bank) return -EINVAL; if (bank) { + struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); + /* Only for a 2k-page or lower flash, NFC can handle 2 banks */ - if (host->mtd.writesize > 2048) + if (mtd->writesize > 2048) return -EINVAL; nfc_writel(host->nfc->hsmc_regs, BANK, ATMEL_HSMC_NFC_BANK1); } else { @@ -1159,8 +1160,8 @@ static uint16_t *create_lookup_table(struct device *dev, int sector_size) static int atmel_pmecc_nand_init_params(struct platform_device *pdev, struct atmel_nand_host *host) { - struct mtd_info *mtd = &host->mtd; struct nand_chip *nand_chip = &host->nand_chip; + struct mtd_info *mtd = nand_to_mtd(nand_chip); struct resource *regs, *regs_pmerr, *regs_rom; uint16_t *galois_table; int cap, sector_size, err_no; @@ -1586,8 +1587,8 @@ static int atmel_of_init_port(struct atmel_nand_host *host, static int atmel_hw_nand_init_params(struct platform_device *pdev, struct atmel_nand_host *host) { - struct mtd_info *mtd = &host->mtd; struct nand_chip *nand_chip = &host->nand_chip; + struct mtd_info *mtd = nand_to_mtd(nand_chip); struct resource *regs; regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); @@ -2112,8 +2113,8 @@ static int atmel_nand_probe(struct platform_device *pdev) } host->io_phys = (dma_addr_t)mem->start; - mtd = &host->mtd; nand_chip = &host->nand_chip; + mtd = nand_to_mtd(nand_chip); host->dev = &pdev->dev; if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { nand_set_flash_node(nand_chip, pdev->dev.of_node); @@ -2283,7 +2284,7 @@ err_nand_ioremap: static int atmel_nand_remove(struct platform_device *pdev) { struct atmel_nand_host *host = platform_get_drvdata(pdev); - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); nand_release(mtd); -- cgit v1.1 From ff70f354a960f01afb2e0d4313bd664b88b1532f Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:51 +0100 Subject: mtd: nand: au1550nd: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/au1550nd.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 73fceb8..280e5b6 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -23,7 +23,6 @@ struct au1550nd_ctx { - struct mtd_info info; struct nand_chip chip; int cs; @@ -197,8 +196,9 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len) static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) { - struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info); struct nand_chip *this = mtd_to_nand(mtd); + struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx, + chip); switch (cmd) { @@ -267,8 +267,9 @@ static void au1550_select_chip(struct mtd_info *mtd, int chip) */ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info); struct nand_chip *this = mtd_to_nand(mtd); + struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx, + chip); int ce_override = 0, i; unsigned long flags = 0; @@ -405,6 +406,7 @@ static int au1550nd_probe(struct platform_device *pdev) struct au1550nd_platdata *pd; struct au1550nd_ctx *ctx; struct nand_chip *this; + struct mtd_info *mtd; struct resource *r; int ret, cs; @@ -438,8 +440,9 @@ static int au1550nd_probe(struct platform_device *pdev) } this = &ctx->chip; - ctx->info.priv = this; - ctx->info.dev.parent = &pdev->dev; + mtd = nand_to_mtd(this); + mtd->priv = this; + mtd->dev.parent = &pdev->dev; /* figure out which CS# r->start belongs to */ cs = find_nand_cs(r->start); @@ -467,13 +470,13 @@ static int au1550nd_probe(struct platform_device *pdev) this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf; this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf; - ret = nand_scan(&ctx->info, 1); + ret = nand_scan(mtd, 1); if (ret) { dev_err(&pdev->dev, "NAND scan failed with %d\n", ret); goto out3; } - mtd_device_register(&ctx->info, pd->parts, pd->num_parts); + mtd_device_register(mtd, pd->parts, pd->num_parts); platform_set_drvdata(pdev, ctx); @@ -493,7 +496,7 @@ static int au1550nd_remove(struct platform_device *pdev) struct au1550nd_ctx *ctx = platform_get_drvdata(pdev); struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - nand_release(&ctx->info); + nand_release(nand_to_mtd(&ctx->chip)); iounmap(ctx->base); release_mem_region(r->start, 0x1000); kfree(ctx); -- cgit v1.1 From 7085a3bee3a20e3be07a103dd1f1cd997375527a Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:53 +0100 Subject: mtd: nand: bf5xx: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/bf5xx_nand.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index d9da5ed..928d599 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -142,7 +142,6 @@ static struct nand_ecclayout bootrom_ecclayout = { struct bf5xx_nand_info { /* mtd info */ struct nand_hw_control controller; - struct mtd_info mtd; struct nand_chip chip; /* platform info */ @@ -160,7 +159,8 @@ struct bf5xx_nand_info { */ static struct bf5xx_nand_info *mtd_to_nand_info(struct mtd_info *mtd) { - return container_of(mtd, struct bf5xx_nand_info, mtd); + return container_of(mtd_to_nand(mtd), struct bf5xx_nand_info, + chip); } static struct bf5xx_nand_info *to_nand_info(struct platform_device *pdev) @@ -660,7 +660,7 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info) */ static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info) { - struct mtd_info *mtd = &info->mtd; + struct mtd_info *mtd = nand_to_mtd(&info->chip); struct mtd_partition *parts = info->platform->partitions; int nr = info->platform->nr_partitions; @@ -675,7 +675,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev) * and their partitions, then go through freeing the * resources used */ - nand_release(&info->mtd); + nand_release(nand_to_mtd(&info->chip)); peripheral_free_list(bfin_nfc_pin_req); bf5xx_nand_dma_remove(info); @@ -756,6 +756,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev) /* initialise chip data struct */ chip = &info->chip; + mtd = nand_to_mtd(&info->chip); if (plat->data_width) chip->options |= NAND_BUSWIDTH_16; @@ -772,7 +773,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev) chip->cmd_ctrl = bf5xx_nand_hwcontrol; chip->dev_ready = bf5xx_nand_devready; - chip->priv = &info->mtd; + chip->priv = mtd; chip->controller = &info->controller; chip->IO_ADDR_R = (void __iomem *) NFC_READ; @@ -781,7 +782,6 @@ static int bf5xx_nand_probe(struct platform_device *pdev) chip->chip_delay = 0; /* initialise mtd info data struct */ - mtd = &info->mtd; mtd->priv = chip; mtd->dev.parent = &pdev->dev; -- cgit v1.1 From f1c4c9992b1f088ab42ff9fa483ad9eed411e421 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:54 +0100 Subject: mtd: nand: brcm: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index dca8162..c05723b 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -182,7 +182,6 @@ struct brcmnand_host { struct list_head node; struct nand_chip chip; - struct mtd_info mtd; struct platform_device *pdev; int cs; @@ -1078,7 +1077,7 @@ static int brcmnand_low_level_op(struct brcmnand_host *host, enum brcmnand_llop_type type, u32 data, bool last_op) { - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->chip); struct nand_chip *chip = &host->chip; struct brcmnand_controller *ctrl = host->ctrl; u32 tmp; @@ -1806,7 +1805,7 @@ static inline int get_blk_adr_bytes(u64 size, u32 writesize) static int brcmnand_setup_dev(struct brcmnand_host *host) { - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->chip); struct nand_chip *chip = &host->chip; struct brcmnand_controller *ctrl = host->ctrl; struct brcmnand_cfg *cfg = &host->hwcfg; @@ -1920,7 +1919,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) return -ENXIO; } - mtd = &host->mtd; + mtd = nand_to_mtd(&host->chip); chip = &host->chip; nand_set_flash_node(chip, dn); @@ -2064,8 +2063,8 @@ static int brcmnand_resume(struct device *dev) } list_for_each_entry(host, &ctrl->host_list, node) { - struct mtd_info *mtd = &host->mtd; - struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); brcmnand_save_restore_cs_config(host, 1); @@ -2296,7 +2295,7 @@ int brcmnand_remove(struct platform_device *pdev) struct brcmnand_host *host; list_for_each_entry(host, &ctrl->host_list, node) - nand_release(&host->mtd); + nand_release(nand_to_mtd(&host->chip)); clk_disable_unprepare(ctrl->clk); -- cgit v1.1 From e787dfd1be424e0546d05d6819c8ab9c222ec248 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:55 +0100 Subject: mtd: nand: cafe: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/cafe_nand.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 77c92f1..7d6a142 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -605,11 +605,11 @@ static int cafe_nand_probe(struct pci_dev *pdev, pci_set_master(pdev); - mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL); - if (!mtd) + cafe = kzalloc(sizeof(*cafe), GFP_KERNEL); + if (!cafe) return -ENOMEM; - cafe = (void *)(&mtd[1]); + mtd = nand_to_mtd(&cafe->nand); mtd->dev.parent = &pdev->dev; mtd->priv = &cafe->nand; cafe->nand.priv = cafe; @@ -792,7 +792,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, out_ior: pci_iounmap(pdev, cafe->mmio); out_free_mtd: - kfree(mtd); + kfree(cafe); out: return err; } @@ -813,7 +813,7 @@ static void cafe_nand_remove(struct pci_dev *pdev) 2112 + sizeof(struct nand_buffers) + mtd->writesize + mtd->oobsize, cafe->dmabuf, cafe->dmaaddr); - kfree(mtd); + kfree(cafe); } static const struct pci_device_id cafe_nand_tbl[] = { -- cgit v1.1 From 8cd65d1a63d272a20bcd51b459b0550da53a80e5 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:57 +0100 Subject: mtd: nand: cs553x: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/cs553x_nand.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 8904d68..386ae83 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -197,14 +197,13 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) } /* Allocate memory for MTD device structure and private data */ - new_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); - if (!new_mtd) { + this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); + if (!this) { err = -ENOMEM; goto out; } - /* Get pointer to private data */ - this = (struct nand_chip *)(&new_mtd[1]); + new_mtd = nand_to_mtd(this); /* Link the private data with the MTD structure */ new_mtd->priv = this; @@ -257,7 +256,7 @@ out_free: out_ior: iounmap(this->IO_ADDR_R); out_mtd: - kfree(new_mtd); + kfree(this); out: return err; } @@ -337,19 +336,19 @@ static void __exit cs553x_cleanup(void) if (!mtd) continue; - this = mtd_to_nand(cs553x_mtd[i]); + this = mtd_to_nand(mtd); mmio_base = this->IO_ADDR_R; /* Release resources, unregister device */ - nand_release(cs553x_mtd[i]); - kfree(cs553x_mtd[i]->name); + nand_release(mtd); + kfree(mtd->name); cs553x_mtd[i] = NULL; /* unmap physical address */ iounmap(mmio_base); /* Free the MTD device structure */ - kfree(mtd); + kfree(this); } } -- cgit v1.1 From 2afd14f9270e4161a1f2528e75ff517c2d23d2f8 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:56 +0100 Subject: mtd: nand: cmx270: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon [Brian: dropped a defunct comment] Signed-off-by: Brian Norris --- drivers/mtd/nand/cmx270_nand.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index 43bded6..00fd0e9 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c @@ -160,10 +160,8 @@ static int __init cmx270_init(void) gpio_direction_input(GPIO_NAND_RB); /* Allocate memory for MTD device structure and private data */ - cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), - GFP_KERNEL); - if (!cmx270_nand_mtd) { + this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); + if (!this) { ret = -ENOMEM; goto err_kzalloc; } @@ -175,8 +173,7 @@ static int __init cmx270_init(void) goto err_ioremap; } - /* Get pointer to private data */ - this = (struct nand_chip *)(&cmx270_nand_mtd[1]); + cmx270_nand_mtd = nand_to_mtd(this); /* Link the private data with the MTD structure */ cmx270_nand_mtd->owner = THIS_MODULE; @@ -216,7 +213,7 @@ static int __init cmx270_init(void) err_scan: iounmap(cmx270_nand_io); err_ioremap: - kfree(cmx270_nand_mtd); + kfree(this); err_kzalloc: gpio_free(GPIO_NAND_RB); err_gpio_request: @@ -240,8 +237,7 @@ static void __exit cmx270_cleanup(void) iounmap(cmx270_nand_io); - /* Free the MTD device structure */ - kfree (cmx270_nand_mtd); + kfree(mtd_to_nand(cmx270_nand_mtd)); } module_exit(cmx270_cleanup); -- cgit v1.1 From a5cfb4db89bc73e9d35b8a348133fa0b4b99d81e Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:58 +0100 Subject: mtd: nand: davinci: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/davinci_nand.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index b5978d5..b1f69f9 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -53,7 +53,6 @@ * outputs in a "wire-AND" configuration, with no per-chip signals. */ struct davinci_nand_info { - struct mtd_info mtd; struct nand_chip chip; struct nand_ecclayout ecclayout; @@ -80,8 +79,10 @@ struct davinci_nand_info { static DEFINE_SPINLOCK(davinci_nand_lock); static bool ecc4_busy; -#define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd) - +static inline struct davinci_nand_info *to_davinci_nand(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct davinci_nand_info, chip); +} static inline unsigned int davinci_nand_readl(struct davinci_nand_info *info, int offset) @@ -636,6 +637,7 @@ static int nand_davinci_probe(struct platform_device *pdev) int ret; uint32_t val; nand_ecc_modes_t ecc_mode; + struct mtd_info *mtd; pdata = nand_davinci_get_pdata(pdev); if (IS_ERR(pdata)) @@ -682,8 +684,9 @@ static int nand_davinci_probe(struct platform_device *pdev) info->base = base; info->vaddr = vaddr; - info->mtd.priv = &info->chip; - info->mtd.dev.parent = &pdev->dev; + mtd = nand_to_mtd(&info->chip); + mtd->priv = &info->chip; + mtd->dev.parent = &pdev->dev; nand_set_flash_node(&info->chip, pdev->dev.of_node); info->chip.IO_ADDR_R = vaddr; @@ -785,7 +788,7 @@ static int nand_davinci_probe(struct platform_device *pdev) spin_unlock_irq(&davinci_nand_lock); /* Scan to find existence of the device(s) */ - ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1, NULL); + ret = nand_scan_ident(mtd, pdata->mask_chipsel ? 2 : 1, NULL); if (ret < 0) { dev_dbg(&pdev->dev, "no NAND chip(s) found\n"); goto err; @@ -797,9 +800,9 @@ static int nand_davinci_probe(struct platform_device *pdev) * usable: 10 bytes are needed, not 6. */ if (pdata->ecc_bits == 4) { - int chunks = info->mtd.writesize / 512; + int chunks = mtd->writesize / 512; - if (!chunks || info->mtd.oobsize < 16) { + if (!chunks || mtd->oobsize < 16) { dev_dbg(&pdev->dev, "too small\n"); ret = -EINVAL; goto err; @@ -811,8 +814,7 @@ static int nand_davinci_probe(struct platform_device *pdev) */ if (chunks == 1) { info->ecclayout = hwecc4_small; - info->ecclayout.oobfree[1].length = - info->mtd.oobsize - 16; + info->ecclayout.oobfree[1].length = mtd->oobsize - 16; goto syndrome_done; } if (chunks == 4) { @@ -833,15 +835,15 @@ syndrome_done: info->chip.ecc.layout = &info->ecclayout; } - ret = nand_scan_tail(&info->mtd); + ret = nand_scan_tail(mtd); if (ret < 0) goto err; if (pdata->parts) - ret = mtd_device_parse_register(&info->mtd, NULL, NULL, + ret = mtd_device_parse_register(mtd, NULL, NULL, pdata->parts, pdata->nr_parts); else - ret = mtd_device_register(&info->mtd, NULL, 0); + ret = mtd_device_register(mtd, NULL, 0); if (ret < 0) goto err; @@ -871,7 +873,7 @@ static int nand_davinci_remove(struct platform_device *pdev) ecc4_busy = false; spin_unlock_irq(&davinci_nand_lock); - nand_release(&info->mtd); + nand_release(nand_to_mtd(&info->chip)); clk_disable_unprepare(info->clk); -- cgit v1.1 From b0c423c7b630ecfff1e12f7bd7c3c7f0556bebb1 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:00 +0100 Subject: mtd: nand: diskonchip: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/diskonchip.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 5f7bcc8..fff7a4a 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -1556,15 +1556,15 @@ static int __init doc_probe(unsigned long physadr) printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr); - len = sizeof(struct mtd_info) + - sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); - mtd = kzalloc(len, GFP_KERNEL); - if (!mtd) { + len = sizeof(struct nand_chip) + sizeof(struct doc_priv) + + (2 * sizeof(struct nand_bbt_descr)); + nand = kzalloc(len, GFP_KERNEL); + if (!nand) { ret = -ENOMEM; goto fail; } - nand = (struct nand_chip *) (mtd + 1); + mtd = nand_to_mtd(nand); doc = (struct doc_priv *) (nand + 1); nand->bbt_td = (struct nand_bbt_descr *) (doc + 1); nand->bbt_md = nand->bbt_td + 1; @@ -1615,7 +1615,7 @@ static int __init doc_probe(unsigned long physadr) haven't yet added it. This is handled without incident by mtd_device_unregister, as far as I can tell. */ nand_release(mtd); - kfree(mtd); + kfree(nand); goto fail; } @@ -1650,7 +1650,7 @@ static void release_nanddoc(void) nand_release(mtd); iounmap(doc->virtadr); release_mem_region(doc->physadr, DOC_IOREMAP_LEN); - kfree(mtd); + kfree(nand); } } -- cgit v1.1 From 5d07379681a3b4b6b1543388cb0c4b5148292351 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:01 +0100 Subject: mtd: nand: docg4: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/docg4.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index da93d7f..cb6efad 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c @@ -1305,14 +1305,14 @@ static int __init probe_docg4(struct platform_device *pdev) return -EIO; } - len = sizeof(struct mtd_info) + sizeof(struct nand_chip) + - sizeof(struct docg4_priv); - mtd = kzalloc(len, GFP_KERNEL); - if (mtd == NULL) { + len = sizeof(struct nand_chip) + sizeof(struct docg4_priv); + nand = kzalloc(len, GFP_KERNEL); + if (nand == NULL) { retval = -ENOMEM; - goto fail; + goto fail_unmap; } - nand = (struct nand_chip *) (mtd + 1); + + mtd = nand_to_mtd(nand); doc = (struct docg4_priv *) (nand + 1); mtd->priv = nand; nand->priv = doc; @@ -1354,16 +1354,17 @@ static int __init probe_docg4(struct platform_device *pdev) return 0; fail: - iounmap(virtadr); - if (mtd) { + if (nand) { /* re-declarations avoid compiler warning */ - struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand->priv; nand_release(mtd); /* deletes partitions and mtd devices */ free_bch(doc->bch); - kfree(mtd); + kfree(nand); } +fail_unmap: + iounmap(virtadr); + return retval; } @@ -1372,7 +1373,7 @@ static int __exit cleanup_docg4(struct platform_device *pdev) struct docg4_priv *doc = platform_get_drvdata(pdev); nand_release(doc->mtd); free_bch(doc->bch); - kfree(doc->mtd); + kfree(mtd_to_nand(doc->mtd)); iounmap(doc->virtadr); return 0; } -- cgit v1.1 From 18ba50c3c0cc423019f8ed4b1c07e7a74203b289 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:02 +0100 Subject: mtd: nand: fsl_elbc: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/fsl_elbc_nand.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index ad6d5da..7bde76a 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -48,7 +48,6 @@ /* mtd information per set */ struct fsl_elbc_mtd { - struct mtd_info mtd; struct nand_chip chip; struct fsl_lbc_ctrl *ctrl; @@ -742,12 +741,13 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) struct fsl_lbc_regs __iomem *lbc = ctrl->regs; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; struct nand_chip *chip = &priv->chip; + struct mtd_info *mtd = nand_to_mtd(chip); dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); /* Fill in fsl_elbc_mtd structure */ - priv->mtd.priv = chip; - priv->mtd.dev.parent = priv->dev; + mtd->priv = chip; + mtd->dev.parent = priv->dev; nand_set_flash_node(chip, priv->dev->of_node); /* set timeout to maximum */ @@ -798,9 +798,11 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) { struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; - nand_release(&priv->mtd); + struct mtd_info *mtd = nand_to_mtd(&priv->chip); - kfree(priv->mtd.name); + nand_release(mtd); + + kfree(mtd->name); if (priv->vbase) iounmap(priv->vbase); @@ -824,6 +826,7 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev) int bank; struct device *dev; struct device_node *node = pdev->dev.of_node; + struct mtd_info *mtd; if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) return -ENODEV; @@ -886,8 +889,9 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev) goto err; } - priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start); - if (!priv->mtd.name) { + mtd = nand_to_mtd(&priv->chip); + mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start); + if (!nand_to_mtd(&priv->chip)->name) { ret = -ENOMEM; goto err; } @@ -896,21 +900,21 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev) if (ret) goto err; - ret = nand_scan_ident(&priv->mtd, 1, NULL); + ret = nand_scan_ident(mtd, 1, NULL); if (ret) goto err; - ret = fsl_elbc_chip_init_tail(&priv->mtd); + ret = fsl_elbc_chip_init_tail(mtd); if (ret) goto err; - ret = nand_scan_tail(&priv->mtd); + ret = nand_scan_tail(mtd); if (ret) goto err; /* First look for RedBoot table or partitions on the command * line, these take precedence over device tree information */ - mtd_device_parse_register(&priv->mtd, part_probe_types, NULL, + mtd_device_parse_register(mtd, part_probe_types, NULL, NULL, 0); printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n", -- cgit v1.1 From 5e9fb93dd3782eba5e6f282e01f4fc577f2d653a Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:03 +0100 Subject: mtd: nand: fsl_ifc: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/fsl_ifc_nand.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 3136842..3f5654f 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -40,7 +40,6 @@ struct fsl_ifc_ctrl; /* mtd information per set */ struct fsl_ifc_mtd { - struct mtd_info mtd; struct nand_chip chip; struct fsl_ifc_ctrl *ctrl; @@ -877,12 +876,13 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_regs __iomem *ifc = ctrl->regs; struct nand_chip *chip = &priv->chip; + struct mtd_info *mtd = nand_to_mtd(&priv->chip); struct nand_ecclayout *layout; u32 csor; /* Fill in fsl_ifc_mtd structure */ - priv->mtd.priv = chip; - priv->mtd.dev.parent = priv->dev; + mtd->priv = chip; + mtd->dev.parent = priv->dev; nand_set_flash_node(chip, priv->dev->of_node); /* fill in nand_chip structure */ @@ -994,9 +994,11 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv) { - nand_release(&priv->mtd); + struct mtd_info *mtd = nand_to_mtd(&priv->chip); - kfree(priv->mtd.name); + nand_release(mtd); + + kfree(mtd->name); if (priv->vbase) iounmap(priv->vbase); @@ -1031,6 +1033,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) int ret; int bank; struct device_node *node = dev->dev.of_node; + struct mtd_info *mtd; if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) return -ENODEV; @@ -1103,8 +1106,10 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) IFC_NAND_EVTER_INTR_FTOERIR_EN | IFC_NAND_EVTER_INTR_WPERIR_EN, &ifc->ifc_nand.nand_evter_intr_en); - priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start); - if (!priv->mtd.name) { + + mtd = nand_to_mtd(&priv->chip); + mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start); + if (!mtd->name) { ret = -ENOMEM; goto err; } @@ -1113,22 +1118,21 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) if (ret) goto err; - ret = nand_scan_ident(&priv->mtd, 1, NULL); + ret = nand_scan_ident(mtd, 1, NULL); if (ret) goto err; - ret = fsl_ifc_chip_init_tail(&priv->mtd); + ret = fsl_ifc_chip_init_tail(mtd); if (ret) goto err; - ret = nand_scan_tail(&priv->mtd); + ret = nand_scan_tail(mtd); if (ret) goto err; /* First look for RedBoot table or partitions on the command * line, these take precedence over device tree information */ - mtd_device_parse_register(&priv->mtd, part_probe_types, NULL, - NULL, 0); + mtd_device_parse_register(mtd, part_probe_types, NULL, NULL, 0); dev_info(priv->dev, "IFC NAND device at 0x%llx, bank %d\n", (unsigned long long)res.start, priv->bank); -- cgit v1.1 From 478d51f0213b9a4b0e605481aa3c14f4a084df4f Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:04 +0100 Subject: mtd: nand: fsl_upm: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/fsl_upm.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 68ec128..0379adc 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -31,7 +31,6 @@ struct fsl_upm_nand { struct device *dev; - struct mtd_info mtd; struct nand_chip chip; int last_ctrl; struct mtd_partition *parts; @@ -49,7 +48,8 @@ struct fsl_upm_nand { static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo) { - return container_of(mtdinfo, struct fsl_upm_nand, mtd); + return container_of(mtd_to_nand(mtdinfo), struct fsl_upm_nand, + chip); } static int fun_chip_ready(struct mtd_info *mtd) @@ -66,9 +66,10 @@ static int fun_chip_ready(struct mtd_info *mtd) static void fun_wait_rnb(struct fsl_upm_nand *fun) { if (fun->rnb_gpio[fun->mchip_number] >= 0) { + struct mtd_info *mtd = nand_to_mtd(&fun->chip); int cnt = 1000000; - while (--cnt && !fun_chip_ready(&fun->mtd)) + while (--cnt && !fun_chip_ready(mtd)) cpu_relax(); if (!cnt) dev_err(fun->dev, "tired waiting for RNB\n"); @@ -157,6 +158,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, const struct device_node *upm_np, const struct resource *io_res) { + struct mtd_info *mtd = nand_to_mtd(&fun->chip); int ret; struct device_node *flash_np; @@ -174,30 +176,30 @@ static int fun_chip_init(struct fsl_upm_nand *fun, if (fun->rnb_gpio[0] >= 0) fun->chip.dev_ready = fun_chip_ready; - fun->mtd.priv = &fun->chip; - fun->mtd.dev.parent = fun->dev; + mtd->priv = &fun->chip; + mtd->dev.parent = fun->dev; flash_np = of_get_next_child(upm_np, NULL); if (!flash_np) return -ENODEV; nand_set_flash_node(&fun->chip, flash_np); - fun->mtd.name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start, - flash_np->name); - if (!fun->mtd.name) { + mtd->name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start, + flash_np->name); + if (!mtd->name) { ret = -ENOMEM; goto err; } - ret = nand_scan(&fun->mtd, fun->mchip_count); + ret = nand_scan(mtd, fun->mchip_count); if (ret) goto err; - ret = mtd_device_register(&fun->mtd, NULL, 0); + ret = mtd_device_register(mtd, NULL, 0); err: of_node_put(flash_np); if (ret) - kfree(fun->mtd.name); + kfree(mtd->name); return ret; } @@ -321,10 +323,11 @@ err1: static int fun_remove(struct platform_device *ofdev) { struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); + struct mtd_info *mtd = nand_to_mtd(&fun->chip); int i; - nand_release(&fun->mtd); - kfree(fun->mtd.name); + nand_release(mtd); + kfree(mtd->name); for (i = 0; i < fun->mchip_count; i++) { if (fun->rnb_gpio[i] < 0) -- cgit v1.1 From bdf3a5550152606c7541094e14f892c2f4825856 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:05 +0100 Subject: mtd: nand: fsmc: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/fsmc_nand.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 499fc59..4c68e7a 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -299,7 +299,6 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = { */ struct fsmc_nand_data { u32 pid; - struct mtd_info mtd; struct nand_chip nand; struct mtd_partition *partitions; unsigned int nr_partitions; @@ -328,7 +327,7 @@ struct fsmc_nand_data { static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd) { - return container_of(mtd, struct fsmc_nand_data, mtd); + return container_of(mtd_to_nand(mtd), struct fsmc_nand_data, nand); } /* Assert CS signal based on chipnr */ @@ -1008,13 +1007,13 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) init_completion(&host->dma_access_complete); /* Link all private pointers */ - mtd = &host->mtd; + mtd = nand_to_mtd(&host->nand); nand = &host->nand; mtd->priv = nand; nand->priv = host; nand_set_flash_node(nand, np); - host->mtd.dev.parent = &pdev->dev; + mtd->dev.parent = &pdev->dev; nand->IO_ADDR_R = host->data_va; nand->IO_ADDR_W = host->data_va; nand->cmd_ctrl = fsmc_cmd_ctrl; @@ -1077,14 +1076,14 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) /* * Scan to find existence of the device */ - if (nand_scan_ident(&host->mtd, 1, NULL)) { + if (nand_scan_ident(mtd, 1, NULL)) { ret = -ENXIO; dev_err(&pdev->dev, "No NAND Device found!\n"); goto err_scan_ident; } if (AMBA_REV_BITS(host->pid) >= 8) { - switch (host->mtd.oobsize) { + switch (mtd->oobsize) { case 16: nand->ecc.layout = &fsmc_ecc4_16_layout; host->ecc_place = &fsmc_ecc4_sp_place; @@ -1135,7 +1134,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) * generated later in nand_bch_init() later. */ if (nand->ecc.mode != NAND_ECC_SOFT_BCH) { - switch (host->mtd.oobsize) { + switch (mtd->oobsize) { case 16: nand->ecc.layout = &fsmc_ecc1_16_layout; break; @@ -1156,7 +1155,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) } /* Second stage of scan to fill MTD data-structures */ - if (nand_scan_tail(&host->mtd)) { + if (nand_scan_tail(mtd)) { ret = -ENXIO; goto err_probe; } @@ -1171,9 +1170,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) /* * Check for partition info passed */ - host->mtd.name = "nand"; - ret = mtd_device_register(&host->mtd, host->partitions, - host->nr_partitions); + mtd->name = "nand"; + ret = mtd_device_register(mtd, host->partitions, host->nr_partitions); if (ret) goto err_probe; @@ -1203,7 +1201,7 @@ static int fsmc_nand_remove(struct platform_device *pdev) struct fsmc_nand_data *host = platform_get_drvdata(pdev); if (host) { - nand_release(&host->mtd); + nand_release(nand_to_mtd(&host->nand)); if (host->mode == USE_DMA_ACCESS) { dma_release_channel(host->write_dma_chan); -- cgit v1.1 From dc2948ca66e4133ccac1948dd7631072e84e996d Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:06 +0100 Subject: mtd: nand: gpio: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/gpio.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index d57a07a..99dd74c 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c @@ -35,12 +35,14 @@ struct gpiomtd { void __iomem *io_sync; - struct mtd_info mtd_info; struct nand_chip nand_chip; struct gpio_nand_platdata plat; }; -#define gpio_nand_getpriv(x) container_of(x, struct gpiomtd, mtd_info) +static inline struct gpiomtd *gpio_nand_getpriv(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct gpiomtd, nand_chip); +} #ifdef CONFIG_ARM @@ -195,7 +197,7 @@ static int gpio_nand_remove(struct platform_device *pdev) { struct gpiomtd *gpiomtd = platform_get_drvdata(pdev); - nand_release(&gpiomtd->mtd_info); + nand_release(nand_to_mtd(&gpiomtd->nand_chip)); if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) gpio_set_value(gpiomtd->plat.gpio_nwp, 0); @@ -208,6 +210,7 @@ static int gpio_nand_probe(struct platform_device *pdev) { struct gpiomtd *gpiomtd; struct nand_chip *chip; + struct mtd_info *mtd; struct resource *res; int ret = 0; @@ -274,24 +277,24 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->chip_delay = gpiomtd->plat.chip_delay; chip->cmd_ctrl = gpio_nand_cmd_ctrl; - gpiomtd->mtd_info.priv = chip; - gpiomtd->mtd_info.dev.parent = &pdev->dev; + mtd = nand_to_mtd(chip); + mtd->priv = chip; + mtd->dev.parent = &pdev->dev; platform_set_drvdata(pdev, gpiomtd); if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) gpio_direction_output(gpiomtd->plat.gpio_nwp, 1); - if (nand_scan(&gpiomtd->mtd_info, 1)) { + if (nand_scan(mtd, 1)) { ret = -ENXIO; goto err_wp; } if (gpiomtd->plat.adjust_parts) - gpiomtd->plat.adjust_parts(&gpiomtd->plat, - gpiomtd->mtd_info.size); + gpiomtd->plat.adjust_parts(&gpiomtd->plat, mtd->size); - ret = mtd_device_register(&gpiomtd->mtd_info, gpiomtd->plat.parts, + ret = mtd_device_register(mtd, gpiomtd->plat.parts, gpiomtd->plat.num_parts); if (!ret) return 0; -- cgit v1.1 From 2a690b25f6c770e70cc00357846f39327531c464 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:07 +0100 Subject: mtd: nand: gpmi: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 2 +- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 23 +++++++++++------------ drivers/mtd/nand/gpmi-nand/gpmi-nand.h | 1 - 3 files changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 43fa16b5..0f68a99 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -919,7 +919,7 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode) { struct resources *r = &this->resources; struct nand_chip *nand = &this->nand; - struct mtd_info *mtd = &this->mtd; + struct mtd_info *mtd = nand_to_mtd(nand); uint8_t *feature; unsigned long rate; int ret; diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 802adb0..38b07c7 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -107,7 +107,7 @@ static irqreturn_t bch_irq(int irq, void *cookie) static inline int get_ecc_strength(struct gpmi_nand_data *this) { struct bch_geometry *geo = &this->bch_geometry; - struct mtd_info *mtd = &this->mtd; + struct mtd_info *mtd = nand_to_mtd(&this->nand); int ecc_strength; ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8) @@ -139,8 +139,8 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this) static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) { struct bch_geometry *geo = &this->bch_geometry; - struct mtd_info *mtd = &this->mtd; - struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_chip *chip = &this->nand; + struct mtd_info *mtd = nand_to_mtd(chip); struct nand_oobfree *of = gpmi_hw_ecclayout.oobfree; unsigned int block_mark_bit_offset; @@ -257,7 +257,7 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) static int legacy_set_geometry(struct gpmi_nand_data *this) { struct bch_geometry *geo = &this->bch_geometry; - struct mtd_info *mtd = &this->mtd; + struct mtd_info *mtd = nand_to_mtd(&this->nand); unsigned int metadata_size; unsigned int status_size; unsigned int block_mark_bit_offset; @@ -804,7 +804,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this) { struct bch_geometry *geo = &this->bch_geometry; struct device *dev = this->dev; - struct mtd_info *mtd = &this->mtd; + struct mtd_info *mtd = nand_to_mtd(&this->nand); /* [1] Allocate a command buffer. PAGE_SIZE is enough. */ this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL); @@ -1600,8 +1600,8 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this) { struct boot_rom_geometry *rom_geo = &this->rom_geometry; struct device *dev = this->dev; - struct mtd_info *mtd = &this->mtd; struct nand_chip *chip = &this->nand; + struct mtd_info *mtd = nand_to_mtd(chip); unsigned int search_area_size_in_strides; unsigned int stride; unsigned int page; @@ -1655,8 +1655,8 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) { struct device *dev = this->dev; struct boot_rom_geometry *rom_geo = &this->rom_geometry; - struct mtd_info *mtd = &this->mtd; struct nand_chip *chip = &this->nand; + struct mtd_info *mtd = nand_to_mtd(chip); unsigned int block_size_in_pages; unsigned int search_area_size_in_strides; unsigned int search_area_size_in_pages; @@ -1735,7 +1735,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this) { struct device *dev = this->dev; struct nand_chip *chip = &this->nand; - struct mtd_info *mtd = &this->mtd; + struct mtd_info *mtd = nand_to_mtd(chip); unsigned int block_count; unsigned int block; int chipnr; @@ -1831,14 +1831,13 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this) static void gpmi_nand_exit(struct gpmi_nand_data *this) { - nand_release(&this->mtd); + nand_release(nand_to_mtd(&this->nand)); gpmi_free_dma_buffer(this); } static int gpmi_init_last(struct gpmi_nand_data *this) { - struct mtd_info *mtd = &this->mtd; - struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_chip *chip = &this->nand; struct nand_ecc_ctrl *ecc = &chip->ecc; struct bch_geometry *bch_geo = &this->bch_geometry; int ret; @@ -1886,8 +1885,8 @@ static int gpmi_init_last(struct gpmi_nand_data *this) static int gpmi_nand_init(struct gpmi_nand_data *this) { - struct mtd_info *mtd = &this->mtd; struct nand_chip *chip = &this->nand; + struct mtd_info *mtd = nand_to_mtd(chip); int ret; /* init current chip */ diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index 544062f..4e49a1f 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h @@ -160,7 +160,6 @@ struct gpmi_nand_data { /* MTD / NAND */ struct nand_chip nand; - struct mtd_info mtd; /* General-use Variables */ int current_chip; -- cgit v1.1 From fa100163d38ef8607652681fbe6f75491032610e Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:08 +0100 Subject: mtd: nand: hisi504: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/hisi504_nand.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c index 6358d4a..6e6e482 100644 --- a/drivers/mtd/nand/hisi504_nand.c +++ b/drivers/mtd/nand/hisi504_nand.c @@ -134,7 +134,6 @@ struct hinfc_host { struct nand_chip chip; - struct mtd_info mtd; struct device *dev; void __iomem *iobase; void __iomem *mmio; @@ -189,8 +188,8 @@ static void wait_controller_finished(struct hinfc_host *host) static void hisi_nfc_dma_transfer(struct hinfc_host *host, int todev) { - struct mtd_info *mtd = &host->mtd; - struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); unsigned long val; int ret; @@ -262,7 +261,7 @@ static int hisi_nfc_send_cmd_pageprog(struct hinfc_host *host) static int hisi_nfc_send_cmd_readstart(struct hinfc_host *host) { - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->chip); if ((host->addr_value[0] == host->cache_addr_value[0]) && (host->addr_value[1] == host->cache_addr_value[1])) @@ -643,7 +642,7 @@ static int hisi_nfc_ecc_probe(struct hinfc_host *host) int size, strength, ecc_bits; struct device *dev = host->dev; struct nand_chip *chip = &host->chip; - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(chip); struct device_node *np = host->dev->of_node; size = of_get_nand_ecc_step_size(np); @@ -712,7 +711,7 @@ static int hisi_nfc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); chip = &host->chip; - mtd = &host->mtd; + mtd = nand_to_mtd(chip); irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -822,7 +821,7 @@ err_res: static int hisi_nfc_remove(struct platform_device *pdev) { struct hinfc_host *host = platform_get_drvdata(pdev); - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->chip); nand_release(mtd); -- cgit v1.1 From d25cc7abb164cea73894934d6b699c465b0bedaf Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:09 +0100 Subject: mtd: nand: jz4740: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/jz4740_nand.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 5a06fba..03239a5 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -59,7 +59,6 @@ #define JZ_NAND_MEM_ADDR_OFFSET 0x10000 struct jz_nand { - struct mtd_info mtd; struct nand_chip chip; void __iomem *base; struct resource *mem; @@ -76,7 +75,7 @@ struct jz_nand { static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd) { - return container_of(mtd, struct jz_nand, mtd); + return container_of(mtd_to_nand(mtd), struct jz_nand, chip); } static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr) @@ -334,8 +333,8 @@ static int jz_nand_detect_bank(struct platform_device *pdev, char gpio_name[9]; char res_name[6]; uint32_t ctrl; - struct mtd_info *mtd = &nand->mtd; struct nand_chip *chip = &nand->chip; + struct mtd_info *mtd = nand_to_mtd(chip); /* Request GPIO port. */ gpio = JZ_GPIO_MEM_CS0 + bank - 1; @@ -432,8 +431,8 @@ static int jz_nand_probe(struct platform_device *pdev) goto err_iounmap_mmio; } - mtd = &nand->mtd; chip = &nand->chip; + mtd = nand_to_mtd(chip); mtd->priv = chip; mtd->dev.parent = &pdev->dev; mtd->name = "jz4740-nand"; @@ -543,7 +542,7 @@ static int jz_nand_remove(struct platform_device *pdev) struct jz_nand *nand = platform_get_drvdata(pdev); size_t i; - nand_release(&nand->mtd); + nand_release(nand_to_mtd(&nand->chip)); /* Deassert and disable all chips */ writel(0, nand->base + JZ_REG_NAND_CTRL); -- cgit v1.1 From 0faf8c39c0580ecc0edfc2f5c932972ee3424935 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:10 +0100 Subject: mtd: nand: lpc32xx: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/lpc32xx_mlc.c | 7 +++---- drivers/mtd/nand/lpc32xx_slc.c | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index 3738856..3400b3f 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -173,7 +173,6 @@ struct lpc32xx_nand_host { struct nand_chip nand_chip; struct lpc32xx_mlc_platform_data *pdata; struct clk *clk; - struct mtd_info mtd; void __iomem *io_base; int irq; struct lpc32xx_nand_cfg_mlc *ncfg; @@ -566,7 +565,7 @@ static void lpc32xx_ecc_enable(struct mtd_info *mtd, int mode) static int lpc32xx_dma_setup(struct lpc32xx_nand_host *host) { - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); dma_cap_mask_t mask; if (!host->pdata || !host->pdata->dma_filter) { @@ -660,8 +659,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) host->io_base_phy = rc->start; - mtd = &host->mtd; nand_chip = &host->nand_chip; + mtd = nand_to_mtd(nand_chip); if (pdev->dev.of_node) host->ncfg = lpc32xx_parse_dt(&pdev->dev); if (!host->ncfg) { @@ -814,7 +813,7 @@ err_exit1: static int lpc32xx_nand_remove(struct platform_device *pdev) { struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); nand_release(mtd); free_irq(host->irq, host); diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index fcd9fac..61b2961 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c @@ -204,7 +204,6 @@ struct lpc32xx_nand_host { struct nand_chip nand_chip; struct lpc32xx_slc_platform_data *pdata; struct clk *clk; - struct mtd_info mtd; void __iomem *io_base; struct lpc32xx_nand_cfg_slc *ncfg; @@ -703,7 +702,7 @@ static int lpc32xx_nand_write_page_raw_syndrome(struct mtd_info *mtd, static int lpc32xx_nand_dma_setup(struct lpc32xx_nand_host *host) { - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); dma_cap_mask_t mask; if (!host->pdata || !host->pdata->dma_filter) { @@ -799,8 +798,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) host->pdata = dev_get_platdata(&pdev->dev); - mtd = &host->mtd; chip = &host->nand_chip; + mtd = nand_to_mtd(chip); chip->priv = host; nand_set_flash_node(chip, pdev->dev.of_node); mtd->priv = chip; @@ -932,7 +931,7 @@ static int lpc32xx_nand_remove(struct platform_device *pdev) { uint32_t tmp; struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); nand_release(mtd); dma_release_channel(host->dma_chan); -- cgit v1.1 From 5a9f23ffb6da3a6141ab58aeeb7470e0ec69f2ff Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:11 +0100 Subject: mtd: nand: mpc5121: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/mpc5121_nfc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 642c486..8b4cd82 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -118,7 +118,6 @@ #define NFC_TIMEOUT (HZ / 10) /* 1/10 s */ struct mpc5121_nfc_prv { - struct mtd_info mtd; struct nand_chip chip; int irq; void __iomem *regs; @@ -654,8 +653,8 @@ static int mpc5121_nfc_probe(struct platform_device *op) if (!prv) return -ENOMEM; - mtd = &prv->mtd; chip = &prv->chip; + mtd = nand_to_mtd(chip); mtd->priv = chip; mtd->dev.parent = dev; -- cgit v1.1 From a008deb1655ca7301dd388237aa60f867d9f784c Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:12 +0100 Subject: mtd: nand: mxc: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/mxc_nand.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index b291258..9dd71af 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -173,7 +173,6 @@ struct mxc_nand_devtype_data { }; struct mxc_nand_host { - struct mtd_info mtd; struct nand_chip nand; struct device *dev; @@ -1514,7 +1513,7 @@ static int mxcnd_probe(struct platform_device *pdev) host->dev = &pdev->dev; /* structures must be linked */ this = &host->nand; - mtd = &host->mtd; + mtd = nand_to_mtd(this); mtd->priv = this; mtd->dev.parent = &pdev->dev; mtd->name = DRIVER_NAME; @@ -1702,7 +1701,7 @@ static int mxcnd_remove(struct platform_device *pdev) { struct mxc_nand_host *host = platform_get_drvdata(pdev); - nand_release(&host->mtd); + nand_release(nand_to_mtd(&host->nand)); if (host->clk_act) clk_disable_unprepare(host->clk); -- cgit v1.1 From ed10f1655832de0c7e26d4c76ef1bad3bbf87b51 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:13 +0100 Subject: mtd: nand: nandsim: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nandsim.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index eb2a567..442eeaf 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -2236,13 +2236,13 @@ static int __init ns_init_module(void) } /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ - nsmtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) - + sizeof(struct nandsim), GFP_KERNEL); - if (!nsmtd) { + chip = kzalloc(sizeof(struct nand_chip) + sizeof(struct nandsim), + GFP_KERNEL); + if (!chip) { NS_ERR("unable to allocate core structures.\n"); return -ENOMEM; } - chip = (struct nand_chip *)(nsmtd + 1); + nsmtd = nand_to_mtd(chip); nsmtd->priv = (void *)chip; nand = (struct nandsim *)(chip + 1); chip->priv = (void *)nand; @@ -2392,7 +2392,7 @@ err_exit: for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i) kfree(nand->partitions[i].name); error: - kfree(nsmtd); + kfree(chip); free_lists(); return retval; @@ -2413,7 +2413,7 @@ static void __exit ns_cleanup_module(void) nand_release(nsmtd); /* Unregister driver */ for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) kfree(ns->partitions[i].name); - kfree(nsmtd); /* Free other structures */ + kfree(mtd_to_nand(nsmtd)); /* Free other structures */ free_lists(); } -- cgit v1.1 From ca921b537aea1731d0c14805452662eb5ac37fcb Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:14 +0100 Subject: mtd: nand: ndfc: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/ndfc.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index d8a23b0..3a7168e 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -37,7 +37,6 @@ struct ndfc_controller { struct platform_device *ofdev; void __iomem *ndfcbase; - struct mtd_info mtd; struct nand_chip chip; int chip_select; struct nand_hw_control ndfc_control; @@ -147,6 +146,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, { struct device_node *flash_np; struct nand_chip *chip = &ndfc->chip; + struct mtd_info *mtd = nand_to_mtd(chip); int ret; chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; @@ -167,31 +167,32 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, chip->ecc.strength = 1; chip->priv = ndfc; - ndfc->mtd.priv = chip; - ndfc->mtd.dev.parent = &ndfc->ofdev->dev; + mtd->priv = chip; + mtd->dev.parent = &ndfc->ofdev->dev; flash_np = of_get_next_child(node, NULL); if (!flash_np) return -ENODEV; nand_set_flash_node(chip, flash_np); - ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s", - dev_name(&ndfc->ofdev->dev), flash_np->name); - if (!ndfc->mtd.name) { + ppdata.of_node = flash_np; + mtd->name = kasprintf(GFP_KERNEL, "%s.%s", dev_name(&ndfc->ofdev->dev), + flash_np->name); + if (!mtd->name) { ret = -ENOMEM; goto err; } - ret = nand_scan(&ndfc->mtd, 1); + ret = nand_scan(mtd, 1); if (ret) goto err; - ret = mtd_device_register(&ndfc->mtd, NULL, 0); + ret = mtd_device_register(mtd, NULL, 0); err: of_node_put(flash_np); if (ret) - kfree(ndfc->mtd.name); + kfree(mtd->name); return ret; } @@ -258,9 +259,10 @@ static int ndfc_probe(struct platform_device *ofdev) static int ndfc_remove(struct platform_device *ofdev) { struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); + struct mtd_info *mtd = nand_to_mtd(&ndfc->chip); - nand_release(&ndfc->mtd); - kfree(ndfc->mtd.name); + nand_release(mtd); + kfree(mtd->name); return 0; } -- cgit v1.1 From 396a9c437bc0e884de58f58b4b4d7cce52181528 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:15 +0100 Subject: mtd: nand: nuc900: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nuc900_nand.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 65908c0..4dad170 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -55,7 +55,6 @@ __raw_writel((val), (dev)->reg + REG_SMADDR) struct nuc900_nand { - struct mtd_info mtd; struct nand_chip chip; void __iomem *reg; struct clk *clk; @@ -64,7 +63,7 @@ struct nuc900_nand { static inline struct nuc900_nand *mtd_to_nuc900(struct mtd_info *mtd) { - return container_of(mtd, struct nuc900_nand, mtd); + return container_of(mtd_to_nand(mtd), struct nuc900_nand, chip); } static const struct mtd_partition partitions[] = { @@ -236,6 +235,7 @@ static int nuc900_nand_probe(struct platform_device *pdev) { struct nuc900_nand *nuc900_nand; struct nand_chip *chip; + struct mtd_info *mtd; struct resource *res; nuc900_nand = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_nand), @@ -243,9 +243,10 @@ static int nuc900_nand_probe(struct platform_device *pdev) if (!nuc900_nand) return -ENOMEM; chip = &(nuc900_nand->chip); + mtd = nand_to_mtd(chip); - nuc900_nand->mtd.priv = chip; - nuc900_nand->mtd.dev.parent = &pdev->dev; + mtd->priv = chip; + mtd->dev.parent = &pdev->dev; spin_lock_init(&nuc900_nand->lock); nuc900_nand->clk = devm_clk_get(&pdev->dev, NULL); @@ -269,11 +270,10 @@ static int nuc900_nand_probe(struct platform_device *pdev) nuc900_nand_enable(nuc900_nand); - if (nand_scan(&(nuc900_nand->mtd), 1)) + if (nand_scan(mtd, 1)) return -ENXIO; - mtd_device_register(&(nuc900_nand->mtd), partitions, - ARRAY_SIZE(partitions)); + mtd_device_register(mtd, partitions, ARRAY_SIZE(partitions)); platform_set_drvdata(pdev, nuc900_nand); @@ -284,7 +284,7 @@ static int nuc900_nand_remove(struct platform_device *pdev) { struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev); - nand_release(&nuc900_nand->mtd); + nand_release(nand_to_mtd(&nuc900_nand->chip)); clk_disable(nuc900_nand->clk); return 0; -- cgit v1.1 From 432420c0fc8d077c30900a4e90779cd7dca021da Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:16 +0100 Subject: mtd: nand: omap2: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/omap2.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 1fb40db..f9d0b58 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -152,7 +152,6 @@ static struct nand_hw_control omap_gpmc_controller = { struct omap_nand_info { struct omap_nand_platform_data *pdata; - struct mtd_info mtd; struct nand_chip nand; struct platform_device *pdev; @@ -179,8 +178,9 @@ struct omap_nand_info { static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd) { - return container_of(mtd, struct omap_nand_info, mtd); + return container_of(mtd_to_nand(mtd), struct omap_nand_info, nand); } + /** * omap_prefetch_enable - configures and starts prefetch transfer * @cs: cs (chip select) number @@ -1670,10 +1670,10 @@ static int omap_nand_probe(struct platform_device *pdev) info->reg = pdata->reg; info->of_node = pdata->of_node; info->ecc_opt = pdata->ecc_opt; - mtd = &info->mtd; + nand_chip = &info->nand; + mtd = nand_to_mtd(nand_chip); mtd->priv = &info->nand; mtd->dev.parent = &pdev->dev; - nand_chip = &info->nand; nand_chip->ecc.priv = NULL; nand_set_flash_node(nand_chip, pdata->of_node); @@ -1897,7 +1897,7 @@ static int omap_nand_probe(struct platform_device *pdev) ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; err = elm_config(info->elm_dev, BCH4_ECC, - info->mtd.writesize / nand_chip->ecc.size, + mtd->writesize / nand_chip->ecc.size, nand_chip->ecc.size, nand_chip->ecc.bytes); if (err < 0) goto return_error; @@ -1951,7 +1951,7 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->ecc.write_page = omap_write_page_bch; err = elm_config(info->elm_dev, BCH8_ECC, - info->mtd.writesize / nand_chip->ecc.size, + mtd->writesize / nand_chip->ecc.size, nand_chip->ecc.size, nand_chip->ecc.bytes); if (err < 0) goto return_error; @@ -1981,7 +1981,7 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->ecc.write_page = omap_write_page_bch; err = elm_config(info->elm_dev, BCH16_ECC, - info->mtd.writesize / nand_chip->ecc.size, + mtd->writesize / nand_chip->ecc.size, nand_chip->ecc.size, nand_chip->ecc.bytes); if (err < 0) goto return_error; -- cgit v1.1 From 53cd2681e02bee59e433b20934bf71f4db5a87d8 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:17 +0100 Subject: mtd: nand: orion: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/orion_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 4ed4f67..087a040 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -85,11 +85,11 @@ static int __init orion_nand_probe(struct platform_device *pdev) u32 val = 0; nc = devm_kzalloc(&pdev->dev, - sizeof(struct nand_chip) + sizeof(struct mtd_info), + sizeof(struct nand_chip), GFP_KERNEL); if (!nc) return -ENOMEM; - mtd = (struct mtd_info *)(nc + 1); + mtd = nand_to_mtd(nc); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); io_base = devm_ioremap_resource(&pdev->dev, res); -- cgit v1.1 From 4e3b6d1701be50dfb33879a066bae16c627f5794 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:18 +0100 Subject: mtd: nand: pasemi: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/pasemi_nand.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 0ececac..4dd2985 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -110,17 +110,15 @@ static int pasemi_nand_probe(struct platform_device *ofdev) pr_debug("pasemi_nand at %pR\n", &res); /* Allocate memory for MTD device structure and private data */ - pasemi_nand_mtd = kzalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), GFP_KERNEL); - if (!pasemi_nand_mtd) { + chip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); + if (!chip) { printk(KERN_WARNING "Unable to allocate PASEMI NAND MTD device structure\n"); err = -ENOMEM; goto out; } - /* Get pointer to private data */ - chip = (struct nand_chip *)&pasemi_nand_mtd[1]; + pasemi_nand_mtd = nand_to_mtd(chip); /* Link the private data with the MTD structure */ pasemi_nand_mtd->priv = chip; @@ -180,7 +178,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) out_ior: iounmap(chip->IO_ADDR_R); out_mtd: - kfree(pasemi_nand_mtd); + kfree(chip); out: return err; } @@ -202,7 +200,7 @@ static int pasemi_nand_remove(struct platform_device *ofdev) iounmap(chip->IO_ADDR_R); /* Free the MTD device structure */ - kfree(pasemi_nand_mtd); + kfree(chip); pasemi_nand_mtd = NULL; -- cgit v1.1 From a0260d21ac91c5deaeadf4d53a27b3f9f40cb77b Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:19 +0100 Subject: mtd: nand: plat: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/plat_nand.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 06ac6c6..796eb7d 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -20,7 +20,6 @@ struct plat_nand_data { struct nand_chip chip; - struct mtd_info mtd; void __iomem *io_base; }; @@ -31,6 +30,7 @@ static int plat_nand_probe(struct platform_device *pdev) { struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); struct plat_nand_data *data; + struct mtd_info *mtd; struct resource *res; const char **part_types; int err = 0; @@ -58,8 +58,9 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.priv = &data; nand_set_flash_node(&data->chip, pdev->dev.of_node); - data->mtd.priv = &data->chip; - data->mtd.dev.parent = &pdev->dev; + mtd = nand_to_mtd(&data->chip); + mtd->priv = &data->chip; + mtd->dev.parent = &pdev->dev; data->chip.IO_ADDR_R = data->io_base; data->chip.IO_ADDR_W = data->io_base; @@ -87,21 +88,21 @@ static int plat_nand_probe(struct platform_device *pdev) } /* Scan to find existence of the device */ - if (nand_scan(&data->mtd, pdata->chip.nr_chips)) { + if (nand_scan(mtd, pdata->chip.nr_chips)) { err = -ENXIO; goto out; } part_types = pdata->chip.part_probe_types; - err = mtd_device_parse_register(&data->mtd, part_types, NULL, + err = mtd_device_parse_register(mtd, part_types, NULL, pdata->chip.partitions, pdata->chip.nr_partitions); if (!err) return err; - nand_release(&data->mtd); + nand_release(mtd); out: if (pdata->ctrl.remove) pdata->ctrl.remove(pdev); @@ -116,7 +117,7 @@ static int plat_nand_remove(struct platform_device *pdev) struct plat_nand_data *data = platform_get_drvdata(pdev); struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); - nand_release(&data->mtd); + nand_release(nand_to_mtd(&data->chip)); if (pdata->ctrl.remove) pdata->ctrl.remove(pdev); -- cgit v1.1 From 063294a36e8e8c2642b6c63a709d6792a609ec33 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:20 +0100 Subject: mtd: nand: pxa3xx: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index dc39a98..c4d5788 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -167,7 +167,6 @@ enum pxa3xx_nand_variant { struct pxa3xx_nand_host { struct nand_chip chip; - struct mtd_info *mtd; void *info_data; /* page size of attached chip */ @@ -450,14 +449,15 @@ static int pxa3xx_nand_init_timings_compat(struct pxa3xx_nand_host *host, struct nand_chip *chip = &host->chip; struct pxa3xx_nand_info *info = host->info_data; const struct pxa3xx_nand_flash *f = NULL; + struct mtd_info *mtd = nand_to_mtd(&host->chip); int i, id, ntypes; ntypes = ARRAY_SIZE(builtin_flash_types); - chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1); + chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); - id = chip->read_byte(host->mtd); - id |= chip->read_byte(host->mtd) << 0x8; + id = chip->read_byte(mtd); + id |= chip->read_byte(mtd) << 0x8; for (i = 0; i < ntypes; i++) { f = &builtin_flash_types[i]; @@ -890,7 +890,7 @@ static void set_command_address(struct pxa3xx_nand_info *info, static void prepare_start_command(struct pxa3xx_nand_info *info, int command) { struct pxa3xx_nand_host *host = info->host[info->cs]; - struct mtd_info *mtd = host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->chip); /* reset data and oob column point to handle data */ info->buf_start = 0; @@ -943,7 +943,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, struct mtd_info *mtd; host = info->host[info->cs]; - mtd = host->mtd; + mtd = nand_to_mtd(&host->chip); addr_cycle = 0; exec_cmd = 1; @@ -1415,8 +1415,8 @@ static int pxa3xx_nand_config_ident(struct pxa3xx_nand_info *info) static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info) { struct pxa3xx_nand_host *host = info->host[info->cs]; - struct mtd_info *mtd = host->mtd; - struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0; info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0; @@ -1693,19 +1693,20 @@ static int alloc_nand_resource(struct platform_device *pdev) pdata = dev_get_platdata(&pdev->dev); if (pdata->num_cs <= 0) return -ENODEV; - info = devm_kzalloc(&pdev->dev, sizeof(*info) + (sizeof(*mtd) + - sizeof(*host)) * pdata->num_cs, GFP_KERNEL); + info = devm_kzalloc(&pdev->dev, + sizeof(*info) + sizeof(*host) * pdata->num_cs, + GFP_KERNEL); if (!info) return -ENOMEM; info->pdev = pdev; info->variant = pxa3xx_nand_get_variant(pdev); for (cs = 0; cs < pdata->num_cs; cs++) { - mtd = (void *)&info[1] + (sizeof(*mtd) + sizeof(*host)) * cs; - chip = (struct nand_chip *)(&mtd[1]); - host = (struct pxa3xx_nand_host *)chip; + host = (void *)&info[1] + sizeof(*host) * cs; + chip = &host->chip; + chip->priv = host; + mtd = nand_to_mtd(chip); info->host[cs] = host; - host->mtd = mtd; host->cs = cs; host->info_data = info; mtd->priv = chip; @@ -1833,7 +1834,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) clk_disable_unprepare(info->clk); for (cs = 0; cs < pdata->num_cs; cs++) - nand_release(info->host[cs]->mtd); + nand_release(nand_to_mtd(&info->host[cs]->chip)); return 0; } @@ -1904,7 +1905,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) info = platform_get_drvdata(pdev); probe_success = 0; for (cs = 0; cs < pdata->num_cs; cs++) { - struct mtd_info *mtd = info->host[cs]->mtd; + struct mtd_info *mtd = nand_to_mtd(&info->host[cs]->chip); /* * The mtd name matches the one used in 'mtdparts' kernel -- cgit v1.1 From de9f56f9137b8a6bfaf9b9dcb7d297bf0b61ffbf Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:21 +0100 Subject: mtd: nand: r852: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/r852.c | 34 +++++++++++++++------------------- drivers/mtd/nand/r852.h | 1 - 2 files changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index ca05b20..1ac8ef2 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -634,25 +634,22 @@ static void r852_update_media_status(struct r852_device *dev) */ static int r852_register_nand_device(struct r852_device *dev) { - dev->mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); - - if (!dev->mtd) - goto error1; + struct mtd_info *mtd = nand_to_mtd(dev->chip); WARN_ON(dev->card_registred); - dev->mtd->priv = dev->chip; - dev->mtd->dev.parent = &dev->pci_dev->dev; + mtd->priv = dev->chip; + mtd->dev.parent = &dev->pci_dev->dev; if (dev->readonly) dev->chip->options |= NAND_ROM; r852_engine_enable(dev); - if (sm_register_device(dev->mtd, dev->sm)) - goto error2; + if (sm_register_device(mtd, dev->sm)) + goto error1; - if (device_create_file(&dev->mtd->dev, &dev_attr_media_type)) { + if (device_create_file(&mtd->dev, &dev_attr_media_type)) { message("can't create media type sysfs attribute"); goto error3; } @@ -660,9 +657,7 @@ static int r852_register_nand_device(struct r852_device *dev) dev->card_registred = 1; return 0; error3: - nand_release(dev->mtd); -error2: - kfree(dev->mtd); + nand_release(mtd); error1: /* Force card redetect */ dev->card_detected = 0; @@ -675,15 +670,15 @@ error1: static void r852_unregister_nand_device(struct r852_device *dev) { + struct mtd_info *mtd = nand_to_mtd(dev->chip); + if (!dev->card_registred) return; - device_remove_file(&dev->mtd->dev, &dev_attr_media_type); - nand_release(dev->mtd); + device_remove_file(&mtd->dev, &dev_attr_media_type); + nand_release(mtd); r852_engine_disable(dev); dev->card_registred = 0; - kfree(dev->mtd); - dev->mtd = NULL; } /* Card state updater */ @@ -1031,6 +1026,7 @@ static int r852_suspend(struct device *device) static int r852_resume(struct device *device) { struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); + struct mtd_info *mtd = nand_to_mtd(dev->chip); r852_disable_irqs(dev); r852_card_update_present(dev); @@ -1050,9 +1046,9 @@ static int r852_resume(struct device *device) /* Otherwise, initialize the card */ if (dev->card_registred) { r852_engine_enable(dev); - dev->chip->select_chip(dev->mtd, 0); - dev->chip->cmdfunc(dev->mtd, NAND_CMD_RESET, -1, -1); - dev->chip->select_chip(dev->mtd, -1); + dev->chip->select_chip(mtd, 0); + dev->chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + dev->chip->select_chip(mtd, -1); } /* Program card detection IRQ */ diff --git a/drivers/mtd/nand/r852.h b/drivers/mtd/nand/r852.h index e6a21d9..d042ddb 100644 --- a/drivers/mtd/nand/r852.h +++ b/drivers/mtd/nand/r852.h @@ -108,7 +108,6 @@ struct r852_device { void __iomem *mmio; /* mmio */ - struct mtd_info *mtd; /* mtd backpointer */ struct nand_chip *chip; /* nand chip backpointer */ struct pci_dev *pci_dev; /* pci backpointer */ -- cgit v1.1 From 9c9eef89ec74433f00593938f8af5113383d898a Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:23 +0100 Subject: mtd: nand: sh_flctl: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/sh_flctl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 57dc525..0ec4b04 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -607,13 +607,13 @@ static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr) case FL_REPAIRABLE: dev_info(&flctl->pdev->dev, "applied ecc on page 0x%x", page_addr); - flctl->mtd.ecc_stats.corrected++; + mtd->ecc_stats.corrected++; break; case FL_ERROR: dev_warn(&flctl->pdev->dev, "page 0x%x contains corrupted data\n", page_addr); - flctl->mtd.ecc_stats.failed++; + mtd->ecc_stats.failed++; break; default: ; @@ -1120,8 +1120,8 @@ static int flctl_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, flctl); - flctl_mtd = &flctl->mtd; nand = &flctl->chip; + flctl_mtd = nand_to_mtd(nand); nand_set_flash_node(nand, pdev->dev.of_node); flctl_mtd->priv = nand; flctl_mtd->dev.parent = &pdev->dev; @@ -1178,7 +1178,7 @@ static int flctl_remove(struct platform_device *pdev) struct sh_flctl *flctl = platform_get_drvdata(pdev); flctl_release_dma(flctl); - nand_release(&flctl->mtd); + nand_release(nand_to_mtd(&flctl->chip)); pm_runtime_disable(&pdev->dev); return 0; -- cgit v1.1 From 0324e6469ab056bef1ffd7c36833448ab1f3df8d Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:24 +0100 Subject: mtd: nand: sharpsl: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/sharpsl.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 84129e5..4b649fb 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -29,13 +29,15 @@ #include struct sharpsl_nand { - struct mtd_info mtd; struct nand_chip chip; void __iomem *io; }; -#define mtd_to_sharpsl(_mtd) container_of(_mtd, struct sharpsl_nand, mtd) +static inline struct sharpsl_nand *mtd_to_sharpsl(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct sharpsl_nand, chip); +} /* register offset */ #define ECCLPLB 0x00 /* line parity 7 - 0 bit */ @@ -109,6 +111,7 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, static int sharpsl_nand_probe(struct platform_device *pdev) { struct nand_chip *this; + struct mtd_info *mtd; struct resource *r; int err = 0; struct sharpsl_nand *sharpsl; @@ -143,8 +146,9 @@ static int sharpsl_nand_probe(struct platform_device *pdev) this = (struct nand_chip *)(&sharpsl->chip); /* Link the private data with the MTD structure */ - sharpsl->mtd.priv = this; - sharpsl->mtd.dev.parent = &pdev->dev; + mtd = nand_to_mtd(this); + mtd->priv = this; + mtd->dev.parent = &pdev->dev; platform_set_drvdata(pdev, sharpsl); @@ -173,14 +177,14 @@ static int sharpsl_nand_probe(struct platform_device *pdev) this->ecc.correct = nand_correct_data; /* Scan to find existence of the device */ - err = nand_scan(&sharpsl->mtd, 1); + err = nand_scan(mtd, 1); if (err) goto err_scan; /* Register the partitions */ - sharpsl->mtd.name = "sharpsl-nand"; + mtd->name = "sharpsl-nand"; - err = mtd_device_parse_register(&sharpsl->mtd, NULL, NULL, + err = mtd_device_parse_register(mtd, NULL, NULL, data->partitions, data->nr_partitions); if (err) goto err_add; @@ -189,7 +193,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) return 0; err_add: - nand_release(&sharpsl->mtd); + nand_release(mtd); err_scan: iounmap(sharpsl->io); @@ -207,7 +211,7 @@ static int sharpsl_nand_remove(struct platform_device *pdev) struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev); /* Release resources, unregister device */ - nand_release(&sharpsl->mtd); + nand_release(nand_to_mtd(&sharpsl->chip)); iounmap(sharpsl->io); -- cgit v1.1 From 32e9f2d8dd83f30019915f8393a470b3ff3fadbe Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:26 +0100 Subject: mtd: nand: sunxi: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/sunxi_nand.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 4ecd486..c29d659 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -234,7 +234,6 @@ struct sunxi_nand_hw_ecc { struct sunxi_nand_chip { struct list_head node; struct nand_chip nand; - struct mtd_info mtd; unsigned long clk_rate; u32 timing_cfg; u32 timing_ctl; @@ -991,6 +990,7 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip, struct device_node *np) { + struct mtd_info *mtd = nand_to_mtd(&chip->nand); const struct nand_sdr_timings *timings; int ret; int mode; @@ -1008,12 +1008,11 @@ static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip, feature[0] = mode; for (i = 0; i < chip->nsels; i++) { - chip->nand.select_chip(&chip->mtd, i); - ret = chip->nand.onfi_set_features(&chip->mtd, - &chip->nand, + chip->nand.select_chip(mtd, i); + ret = chip->nand.onfi_set_features(mtd, &chip->nand, ONFI_FEATURE_ADDR_TIMING_MODE, feature); - chip->nand.select_chip(&chip->mtd, -1); + chip->nand.select_chip(mtd, -1); if (ret) return ret; } @@ -1336,7 +1335,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, nand->write_buf = sunxi_nfc_write_buf; nand->read_byte = sunxi_nfc_read_byte; - mtd = &chip->mtd; + mtd = nand_to_mtd(nand); mtd->dev.parent = dev; mtd->priv = nand; @@ -1407,7 +1406,7 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc) while (!list_empty(&nfc->chips)) { chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip, node); - nand_release(&chip->mtd); + nand_release(nand_to_mtd(&chip->nand)); sunxi_nand_ecc_cleanup(&chip->nand.ecc); list_del(&chip->node); } -- cgit v1.1 From 66c9595d499e9a10bee27bf4026d91452cc78568 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:27 +0100 Subject: mtd: nand: tmio: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/tmio_nand.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index 6d0cbe9..e7b82e1 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c @@ -103,7 +103,6 @@ /*--------------------------------------------------------------------------*/ struct tmio_nand { - struct mtd_info mtd; struct nand_chip chip; struct platform_device *dev; @@ -119,7 +118,10 @@ struct tmio_nand { unsigned read_good:1; }; -#define mtd_to_tmio(m) container_of(m, struct tmio_nand, mtd) +static inline struct tmio_nand *mtd_to_tmio(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct tmio_nand, chip); +} /*--------------------------------------------------------------------------*/ @@ -378,8 +380,8 @@ static int tmio_probe(struct platform_device *dev) tmio->dev = dev; platform_set_drvdata(dev, tmio); - mtd = &tmio->mtd; nand_chip = &tmio->chip; + mtd = nand_to_mtd(nand_chip); mtd->priv = nand_chip; mtd->name = "tmio-nand"; mtd->dev.parent = &dev->dev; @@ -456,7 +458,7 @@ static int tmio_remove(struct platform_device *dev) { struct tmio_nand *tmio = platform_get_drvdata(dev); - nand_release(&tmio->mtd); + nand_release(nand_to_mtd(&tmio->chip)); tmio_hw_stop(dev, tmio); return 0; } -- cgit v1.1 From a3f5437788fde26f9354324cb711461bdc02c6e0 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:28 +0100 Subject: mtd: nand: txx9ndfmc: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/txx9ndfmc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index ff9afb1..da7fcbd 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c @@ -63,7 +63,6 @@ struct txx9ndfmc_priv { struct platform_device *dev; struct nand_chip chip; - struct mtd_info mtd; int cs; const char *mtdname; }; @@ -322,7 +321,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) if (!txx9_priv) continue; chip = &txx9_priv->chip; - mtd = &txx9_priv->mtd; + mtd = nand_to_mtd(chip); mtd->dev.parent = &dev->dev; mtd->priv = chip; -- cgit v1.1 From 960823a226b37eea01151d608636d09d1abac8f9 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:29 +0100 Subject: mtd: nand: vf610: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/vf610_nfc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 1c86c6b..1bbb93a 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -156,7 +156,6 @@ enum vf610_nfc_variant { }; struct vf610_nfc { - struct mtd_info mtd; struct nand_chip chip; struct device *dev; void __iomem *regs; @@ -171,7 +170,10 @@ struct vf610_nfc { u32 ecc_mode; }; -#define mtd_to_nfc(_mtd) container_of(_mtd, struct vf610_nfc, mtd) +static inline struct vf610_nfc *mtd_to_nfc(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct vf610_nfc, chip); +} static struct nand_ecclayout vf610_nfc_ecc45 = { .eccbytes = 45, @@ -674,8 +676,8 @@ static int vf610_nfc_probe(struct platform_device *pdev) return -ENOMEM; nfc->dev = &pdev->dev; - mtd = &nfc->mtd; chip = &nfc->chip; + mtd = nand_to_mtd(chip); mtd->priv = chip; mtd->owner = THIS_MODULE; -- cgit v1.1 From 7208b997b726522cdbea61f53a82c763704c015a Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:22 +0100 Subject: mtd: nand: s3c2410: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Reviewed-by: Krzysztof Kozlowski Signed-off-by: Brian Norris --- drivers/mtd/nand/s3c2410.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index e658b29..c074a49 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -104,7 +104,6 @@ struct s3c2410_nand_info; * @scan_res: The result from calling nand_scan_ident(). */ struct s3c2410_nand_mtd { - struct mtd_info mtd; struct nand_chip chip; struct s3c2410_nand_set *set; struct s3c2410_nand_info *info; @@ -168,7 +167,8 @@ struct s3c2410_nand_info { static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd) { - return container_of(mtd, struct s3c2410_nand_mtd, mtd); + return container_of(mtd_to_nand(mtd), struct s3c2410_nand_mtd, + chip); } static struct s3c2410_nand_info *s3c2410_nand_mtd_toinfo(struct mtd_info *mtd) @@ -745,7 +745,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev) for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) { pr_debug("releasing mtd %d (%p)\n", mtdno, ptr); - nand_release(&ptr->mtd); + nand_release(nand_to_mtd(&ptr->chip)); } } @@ -762,9 +762,11 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, struct s3c2410_nand_set *set) { if (set) { - mtd->mtd.name = set->name; + struct mtd_info *mtdinfo = nand_to_mtd(&mtd->chip); - return mtd_device_parse_register(&mtd->mtd, NULL, NULL, + mtdinfo->name = set->name; + + return mtd_device_parse_register(mtdinfo, NULL, NULL, set->partitions, set->nr_partitions); } @@ -786,6 +788,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, struct s3c2410_nand_set *set) { struct nand_chip *chip = &nmtd->chip; + struct mtd_info *mtd = nand_to_mtd(chip); void __iomem *regs = info->regs; chip->write_buf = s3c2410_nand_write_buf; @@ -831,7 +834,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->IO_ADDR_R = chip->IO_ADDR_W; nmtd->info = info; - nmtd->mtd.priv = chip; + mtd->priv = chip; nmtd->set = set; #ifdef CONFIG_MTD_NAND_S3C2410_HWECC @@ -1012,19 +1015,21 @@ static int s3c24xx_nand_probe(struct platform_device *pdev) nmtd = info->mtds; for (setno = 0; setno < nr_sets; setno++, nmtd++) { + struct mtd_info *mtd = nand_to_mtd(&nmtd->chip); + pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info); - nmtd->mtd.dev.parent = &pdev->dev; + mtd->dev.parent = &pdev->dev; s3c2410_nand_init_chip(info, nmtd, sets); - nmtd->scan_res = nand_scan_ident(&nmtd->mtd, + nmtd->scan_res = nand_scan_ident(mtd, (sets) ? sets->nr_chips : 1, NULL); if (nmtd->scan_res == 0) { s3c2410_nand_update_chip(info, nmtd); - nand_scan_tail(&nmtd->mtd); + nand_scan_tail(mtd); s3c2410_nand_add_partition(info, nmtd, sets); } -- cgit v1.1 From 2d3743944a6b425f3a3795a967499c13e0d8856c Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 18 Dec 2015 11:39:53 -0800 Subject: mtd: nand: docg4: simplify error case Other refactorings have left the 'fail' label much simpler, so it shouldn't have to handle the failed allocation case. This also fixes a -Wshadow warning. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/nand/docg4.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index cb6efad..24d478d 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c @@ -1353,14 +1353,10 @@ static int __init probe_docg4(struct platform_device *pdev) doc->mtd = mtd; return 0; - fail: - if (nand) { - /* re-declarations avoid compiler warning */ - struct docg4_priv *doc = nand->priv; - nand_release(mtd); /* deletes partitions and mtd devices */ - free_bch(doc->bch); - kfree(nand); - } +fail: + nand_release(mtd); /* deletes partitions and mtd devices */ + free_bch(doc->bch); + kfree(nand); fail_unmap: iounmap(virtadr); -- cgit v1.1 From 17dd20bd7d4389d3bc54d71e263088039203ea07 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 08:59:52 +0100 Subject: mtd: nand: bcm47xx: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h | 1 - drivers/mtd/nand/bcm47xxnflash/main.c | 10 ++++++---- drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h index c005a62..8ea7571 100644 --- a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h +++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h @@ -12,7 +12,6 @@ struct bcm47xxnflash { struct bcma_drv_cc *cc; struct nand_chip nand_chip; - struct mtd_info mtd; unsigned curr_command; int curr_page_addr; diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c index 0b3acc4..2c9bffb 100644 --- a/drivers/mtd/nand/bcm47xxnflash/main.c +++ b/drivers/mtd/nand/bcm47xxnflash/main.c @@ -27,6 +27,7 @@ static int bcm47xxnflash_probe(struct platform_device *pdev) { struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev); struct bcm47xxnflash *b47n; + struct mtd_info *mtd; int err = 0; b47n = devm_kzalloc(&pdev->dev, sizeof(*b47n), GFP_KERNEL); @@ -34,8 +35,9 @@ static int bcm47xxnflash_probe(struct platform_device *pdev) return -ENOMEM; b47n->nand_chip.priv = b47n; - b47n->mtd.dev.parent = &pdev->dev; - b47n->mtd.priv = &b47n->nand_chip; /* Required */ + mtd = nand_to_mtd(&b47n->nand_chip); + mtd->dev.parent = &pdev->dev; + mtd->priv = &b47n->nand_chip; /* Required */ b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash); if (b47n->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { @@ -51,7 +53,7 @@ static int bcm47xxnflash_probe(struct platform_device *pdev) platform_set_drvdata(pdev, b47n); - err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0); + err = mtd_device_parse_register(mtd, probes, NULL, NULL, 0); if (err) { pr_err("Failed to register MTD device: %d\n", err); return err; @@ -64,7 +66,7 @@ static int bcm47xxnflash_remove(struct platform_device *pdev) { struct bcm47xxnflash *nflash = platform_get_drvdata(pdev); - nand_release(&nflash->mtd); + nand_release(nand_to_mtd(&nflash->nand_chip)); return 0; } diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c index e5b2e48..6524780 100644 --- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c @@ -421,7 +421,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0)); /* Scan NAND */ - err = nand_scan(&b47n->mtd, 1); + err = nand_scan(nand_to_mtd(&b47n->nand_chip), 1); if (err) { pr_err("Could not scan NAND flash: %d\n", err); goto exit; -- cgit v1.1 From a723bf6a58b17379c27f869402baddf4b0d2c7dc Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Dec 2015 15:04:06 +0100 Subject: mtd: nand: socrates: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/socrates_nand.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index 2dfb1e0..925761c 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -30,7 +30,6 @@ struct socrates_nand_host { struct nand_chip nand_chip; - struct mtd_info mtd; void __iomem *io_base; struct device *dev; }; @@ -159,8 +158,8 @@ static int socrates_nand_probe(struct platform_device *ofdev) return -EIO; } - mtd = &host->mtd; nand_chip = &host->nand_chip; + mtd = nand_to_mtd(nand_chip); host->dev = &ofdev->dev; nand_chip->priv = host; /* link the private data structures */ @@ -216,7 +215,7 @@ out: static int socrates_nand_remove(struct platform_device *ofdev) { struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); - struct mtd_info *mtd = &host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); nand_release(mtd); -- cgit v1.1 From 442f201b93b5222ac2e4f7513be86fdbd00e9065 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 11 Dec 2015 15:06:00 +0100 Subject: mtd: nand: denali: use the mtd instance embedded in struct nand_chip struct nand_chip now embeds an mtd device. Make use of this mtd instance. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/denali.c | 69 ++++++++++++++++++++++++++--------------------- drivers/mtd/nand/denali.h | 1 - 2 files changed, 38 insertions(+), 32 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 9a5035c..b1dd172 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -75,7 +75,10 @@ MODULE_PARM_DESC(onfi_timing_mode, * this macro allows us to convert from an MTD structure to our own * device context (denali) structure. */ -#define mtd_to_denali(m) container_of(m, struct denali_nand_info, mtd) +static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand); +} /* * These constants are defined by the driver to enable common driver @@ -986,6 +989,8 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, * than one NAND connected. */ if (err_byte < ECC_SECTOR_SIZE) { + struct mtd_info *mtd = + nand_to_mtd(&denali->nand); int offset; offset = (err_sector * @@ -995,7 +1000,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, err_device; /* correct the ECC error */ buf[offset] ^= err_correction_value; - denali->mtd.ecc_stats.corrected++; + mtd->ecc_stats.corrected++; bitflips++; } } else { @@ -1062,7 +1067,7 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip, { struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; - size_t size = denali->mtd.writesize + denali->mtd.oobsize; + size_t size = mtd->writesize + mtd->oobsize; uint32_t irq_status; uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP | INTR_STATUS__PROGRAM_FAIL; @@ -1160,7 +1165,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; - size_t size = denali->mtd.writesize + denali->mtd.oobsize; + size_t size = mtd->writesize + mtd->oobsize; uint32_t irq_status; uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE | @@ -1193,14 +1198,14 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, denali_enable_dma(denali, false); if (check_erased_page) { - read_oob_data(&denali->mtd, chip->oob_poi, denali->page); + read_oob_data(mtd, chip->oob_poi, denali->page); /* check ECC failures that may have occurred on erased pages */ if (check_erased_page) { - if (!is_erased(buf, denali->mtd.writesize)) - denali->mtd.ecc_stats.failed++; - if (!is_erased(buf, denali->mtd.oobsize)) - denali->mtd.ecc_stats.failed++; + if (!is_erased(buf, mtd->writesize)) + mtd->ecc_stats.failed++; + if (!is_erased(buf, mtd->oobsize)) + mtd->ecc_stats.failed++; } } return max_bitflips; @@ -1211,7 +1216,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, { struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; - size_t size = denali->mtd.writesize + denali->mtd.oobsize; + size_t size = mtd->writesize + mtd->oobsize; uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP; if (page != denali->page) { @@ -1428,6 +1433,7 @@ static void denali_drv_init(struct denali_nand_info *denali) int denali_init(struct denali_nand_info *denali) { + struct mtd_info *mtd = nand_to_mtd(&denali->nand); int ret; if (denali->platform == INTEL_CE4100) { @@ -1447,7 +1453,7 @@ int denali_init(struct denali_nand_info *denali) if (!denali->buf.buf) return -ENOMEM; - denali->mtd.dev.parent = denali->dev; + mtd->dev.parent = denali->dev; denali_hw_init(denali); denali_drv_init(denali); @@ -1463,8 +1469,8 @@ int denali_init(struct denali_nand_info *denali) /* now that our ISR is registered, we can enable interrupts */ denali_set_intr_modes(denali, true); - denali->mtd.name = "denali-nand"; - denali->mtd.priv = &denali->nand; + mtd->name = "denali-nand"; + mtd->priv = &denali->nand; /* register the driver with the NAND core subsystem */ denali->nand.select_chip = denali_select_chip; @@ -1477,7 +1483,7 @@ int denali_init(struct denali_nand_info *denali) * this is the first stage in a two step process to register * with the nand subsystem */ - if (nand_scan_ident(&denali->mtd, denali->max_banks, NULL)) { + if (nand_scan_ident(mtd, denali->max_banks, NULL)) { ret = -ENXIO; goto failed_req_irq; } @@ -1485,7 +1491,7 @@ int denali_init(struct denali_nand_info *denali) /* allocate the right size buffer now */ devm_kfree(denali->dev, denali->buf.buf); denali->buf.buf = devm_kzalloc(denali->dev, - denali->mtd.writesize + denali->mtd.oobsize, + mtd->writesize + mtd->oobsize, GFP_KERNEL); if (!denali->buf.buf) { ret = -ENOMEM; @@ -1500,7 +1506,7 @@ int denali_init(struct denali_nand_info *denali) } denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf, - denali->mtd.writesize + denali->mtd.oobsize, + mtd->writesize + mtd->oobsize, DMA_BIDIRECTIONAL); if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) { dev_err(denali->dev, "Spectra: failed to map DMA buffer\n"); @@ -1521,10 +1527,10 @@ int denali_init(struct denali_nand_info *denali) denali->nand.bbt_erase_shift += (denali->devnum - 1); denali->nand.phys_erase_shift = denali->nand.bbt_erase_shift; denali->nand.chip_shift += (denali->devnum - 1); - denali->mtd.writesize <<= (denali->devnum - 1); - denali->mtd.oobsize <<= (denali->devnum - 1); - denali->mtd.erasesize <<= (denali->devnum - 1); - denali->mtd.size = denali->nand.numchips * denali->nand.chipsize; + mtd->writesize <<= (denali->devnum - 1); + mtd->oobsize <<= (denali->devnum - 1); + mtd->erasesize <<= (denali->devnum - 1); + mtd->size = denali->nand.numchips * denali->nand.chipsize; denali->bbtskipbytes *= denali->devnum; /* @@ -1551,16 +1557,16 @@ int denali_init(struct denali_nand_info *denali) * SLC if possible. * */ if (!nand_is_slc(&denali->nand) && - (denali->mtd.oobsize > (denali->bbtskipbytes + - ECC_15BITS * (denali->mtd.writesize / + (mtd->oobsize > (denali->bbtskipbytes + + ECC_15BITS * (mtd->writesize / ECC_SECTOR_SIZE)))) { /* if MLC OOB size is large enough, use 15bit ECC*/ denali->nand.ecc.strength = 15; denali->nand.ecc.layout = &nand_15bit_oob; denali->nand.ecc.bytes = ECC_15BITS; iowrite32(15, denali->flash_reg + ECC_CORRECTION); - } else if (denali->mtd.oobsize < (denali->bbtskipbytes + - ECC_8BITS * (denali->mtd.writesize / + } else if (mtd->oobsize < (denali->bbtskipbytes + + ECC_8BITS * (mtd->writesize / ECC_SECTOR_SIZE))) { pr_err("Your NAND chip OOB is not large enough to contain 8bit ECC correction codes"); goto failed_req_irq; @@ -1574,11 +1580,11 @@ int denali_init(struct denali_nand_info *denali) denali->nand.ecc.bytes *= denali->devnum; denali->nand.ecc.strength *= denali->devnum; denali->nand.ecc.layout->eccbytes *= - denali->mtd.writesize / ECC_SECTOR_SIZE; + mtd->writesize / ECC_SECTOR_SIZE; denali->nand.ecc.layout->oobfree[0].offset = denali->bbtskipbytes + denali->nand.ecc.layout->eccbytes; denali->nand.ecc.layout->oobfree[0].length = - denali->mtd.oobsize - denali->nand.ecc.layout->eccbytes - + mtd->oobsize - denali->nand.ecc.layout->eccbytes - denali->bbtskipbytes; /* @@ -1586,7 +1592,7 @@ int denali_init(struct denali_nand_info *denali) * contained by each nand chip. blksperchip will help driver to * know how many blocks is taken by FW. */ - denali->totalblks = denali->mtd.size >> denali->nand.phys_erase_shift; + denali->totalblks = mtd->size >> denali->nand.phys_erase_shift; denali->blksperchip = denali->totalblks / denali->nand.numchips; /* override the default read operations */ @@ -1599,12 +1605,12 @@ int denali_init(struct denali_nand_info *denali) denali->nand.ecc.write_oob = denali_write_oob; denali->nand.erase = denali_erase; - if (nand_scan_tail(&denali->mtd)) { + if (nand_scan_tail(mtd)) { ret = -ENXIO; goto failed_req_irq; } - ret = mtd_device_register(&denali->mtd, NULL, 0); + ret = mtd_device_register(mtd, NULL, 0); if (ret) { dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n", ret); @@ -1622,14 +1628,15 @@ EXPORT_SYMBOL(denali_init); /* driver exit point */ void denali_remove(struct denali_nand_info *denali) { + struct mtd_info *mtd = nand_to_mtd(&denali->nand); /* * Pre-compute DMA buffer size to avoid any problems in case * nand_release() ever changes in a way that mtd->writesize and * mtd->oobsize are not reliable after this call. */ - int bufsize = denali->mtd.writesize + denali->mtd.oobsize; + int bufsize = mtd->writesize + mtd->oobsize; - nand_release(&denali->mtd); + nand_release(mtd); denali_irq_cleanup(denali->irq, denali); dma_unmap_single(denali->dev, denali->buf.dma_buf, bufsize, DMA_BIDIRECTIONAL); diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 4b12cd3..e7ab486 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -450,7 +450,6 @@ struct nand_buf { #define DT 3 struct denali_nand_info { - struct mtd_info mtd; struct nand_chip nand; int flash_bank; /* currently selected chip */ int status; -- cgit v1.1 From 37f5a54646da0760306ab8570115e20d0ed615f5 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:34 +0100 Subject: mtd: nand: remove useless mtd->priv = chip assignments mtd_to_nand() now uses the container_of() approach to transform an mtd_info pointer into a nand_chip one. Drop useless mtd->priv assignments from NAND controller drivers. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/ams-delta.c | 3 --- drivers/mtd/nand/atmel_nand.c | 1 - drivers/mtd/nand/au1550nd.c | 1 - drivers/mtd/nand/bcm47xxnflash/main.c | 1 - drivers/mtd/nand/bf5xx_nand.c | 1 - drivers/mtd/nand/brcmnand/brcmnand.c | 1 - drivers/mtd/nand/cafe_nand.c | 1 - drivers/mtd/nand/cmx270_nand.c | 1 - drivers/mtd/nand/cs553x_nand.c | 1 - drivers/mtd/nand/davinci_nand.c | 1 - drivers/mtd/nand/denali.c | 1 - drivers/mtd/nand/diskonchip.c | 1 - drivers/mtd/nand/docg4.c | 1 - drivers/mtd/nand/fsl_elbc_nand.c | 1 - drivers/mtd/nand/fsl_ifc_nand.c | 1 - drivers/mtd/nand/fsl_upm.c | 1 - drivers/mtd/nand/fsmc_nand.c | 1 - drivers/mtd/nand/gpio.c | 1 - drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 1 - drivers/mtd/nand/hisi504_nand.c | 1 - drivers/mtd/nand/jz4740_nand.c | 1 - drivers/mtd/nand/lpc32xx_mlc.c | 1 - drivers/mtd/nand/lpc32xx_slc.c | 1 - drivers/mtd/nand/mpc5121_nfc.c | 1 - drivers/mtd/nand/mxc_nand.c | 1 - drivers/mtd/nand/nandsim.c | 1 - drivers/mtd/nand/ndfc.c | 1 - drivers/mtd/nand/nuc900_nand.c | 1 - drivers/mtd/nand/omap2.c | 1 - drivers/mtd/nand/orion_nand.c | 1 - drivers/mtd/nand/pasemi_nand.c | 1 - drivers/mtd/nand/plat_nand.c | 1 - drivers/mtd/nand/pxa3xx_nand.c | 1 - drivers/mtd/nand/r852.c | 1 - drivers/mtd/nand/s3c2410.c | 2 -- drivers/mtd/nand/sh_flctl.c | 1 - drivers/mtd/nand/sharpsl.c | 1 - drivers/mtd/nand/socrates_nand.c | 1 - drivers/mtd/nand/sunxi_nand.c | 1 - drivers/mtd/nand/tmio_nand.c | 1 - drivers/mtd/nand/txx9ndfmc.c | 2 -- drivers/mtd/nand/vf610_nfc.c | 1 - 42 files changed, 46 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 0f638c6..1a18938 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -193,9 +193,6 @@ static int ams_delta_init(struct platform_device *pdev) ams_delta_mtd = nand_to_mtd(this); ams_delta_mtd->owner = THIS_MODULE; - /* Link the private data with the MTD structure */ - ams_delta_mtd->priv = this; - /* * Don't try to request the memory region from here, * it should have been already requested from the diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 9ba28312..18c4e14 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -2128,7 +2128,6 @@ static int atmel_nand_probe(struct platform_device *pdev) } nand_chip->priv = host; /* link the private data structures */ - mtd->priv = nand_chip; mtd->dev.parent = &pdev->dev; /* Set address of NAND IO lines */ diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 280e5b6..341ea49 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -441,7 +441,6 @@ static int au1550nd_probe(struct platform_device *pdev) this = &ctx->chip; mtd = nand_to_mtd(this); - mtd->priv = this; mtd->dev.parent = &pdev->dev; /* figure out which CS# r->start belongs to */ diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c index 2c9bffb..b44f821 100644 --- a/drivers/mtd/nand/bcm47xxnflash/main.c +++ b/drivers/mtd/nand/bcm47xxnflash/main.c @@ -37,7 +37,6 @@ static int bcm47xxnflash_probe(struct platform_device *pdev) b47n->nand_chip.priv = b47n; mtd = nand_to_mtd(&b47n->nand_chip); mtd->dev.parent = &pdev->dev; - mtd->priv = &b47n->nand_chip; /* Required */ b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash); if (b47n->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 928d599..9514e13 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -782,7 +782,6 @@ static int bf5xx_nand_probe(struct platform_device *pdev) chip->chip_delay = 0; /* initialise mtd info data struct */ - mtd->priv = chip; mtd->dev.parent = &pdev->dev; /* initialise the hardware */ diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index c05723b..aea0881 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -1924,7 +1924,6 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) nand_set_flash_node(chip, dn); chip->priv = host; - mtd->priv = chip; mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d", host->cs); mtd->owner = THIS_MODULE; diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 7d6a142..00c15e2 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -611,7 +611,6 @@ static int cafe_nand_probe(struct pci_dev *pdev, mtd = nand_to_mtd(&cafe->nand); mtd->dev.parent = &pdev->dev; - mtd->priv = &cafe->nand; cafe->nand.priv = cafe; cafe->pdev = pdev; diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index 00fd0e9..6f97ebb 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c @@ -177,7 +177,6 @@ static int __init cmx270_init(void) /* Link the private data with the MTD structure */ cmx270_nand_mtd->owner = THIS_MODULE; - cmx270_nand_mtd->priv = this; /* insert callbacks */ this->IO_ADDR_R = cmx270_nand_io; diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 386ae83..a65e4e0 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -206,7 +206,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) new_mtd = nand_to_mtd(this); /* Link the private data with the MTD structure */ - new_mtd->priv = this; new_mtd->owner = THIS_MODULE; /* map physical address */ diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index b1f69f9..3b49fe8 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -685,7 +685,6 @@ static int nand_davinci_probe(struct platform_device *pdev) info->vaddr = vaddr; mtd = nand_to_mtd(&info->chip); - mtd->priv = &info->chip; mtd->dev.parent = &pdev->dev; nand_set_flash_node(&info->chip, pdev->dev.of_node); diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index b1dd172..30bf5f6 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1470,7 +1470,6 @@ int denali_init(struct denali_nand_info *denali) /* now that our ISR is registered, we can enable interrupts */ denali_set_intr_modes(denali, true); mtd->name = "denali-nand"; - mtd->priv = &denali->nand; /* register the driver with the NAND core subsystem */ denali->nand.select_chip = denali_select_chip; diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index fff7a4a..a5c0466 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -1569,7 +1569,6 @@ static int __init doc_probe(unsigned long physadr) nand->bbt_td = (struct nand_bbt_descr *) (doc + 1); nand->bbt_md = nand->bbt_td + 1; - mtd->priv = nand; mtd->owner = THIS_MODULE; nand->priv = doc; diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index 24d478d..95cd139 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c @@ -1314,7 +1314,6 @@ static int __init probe_docg4(struct platform_device *pdev) mtd = nand_to_mtd(nand); doc = (struct docg4_priv *) (nand + 1); - mtd->priv = nand; nand->priv = doc; mtd->dev.parent = &pdev->dev; doc->virtadr = virtadr; diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 7bde76a..e96d5bc 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -746,7 +746,6 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); /* Fill in fsl_elbc_mtd structure */ - mtd->priv = chip; mtd->dev.parent = priv->dev; nand_set_flash_node(chip, priv->dev->of_node); diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 3f5654f..9d2b4ed 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -881,7 +881,6 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) u32 csor; /* Fill in fsl_ifc_mtd structure */ - mtd->priv = chip; mtd->dev.parent = priv->dev; nand_set_flash_node(chip, priv->dev->of_node); diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 0379adc..cafd12d 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -176,7 +176,6 @@ static int fun_chip_init(struct fsl_upm_nand *fun, if (fun->rnb_gpio[0] >= 0) fun->chip.dev_ready = fun_chip_ready; - mtd->priv = &fun->chip; mtd->dev.parent = fun->dev; flash_np = of_get_next_child(upm_np, NULL); diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 4c68e7a..9a7c1f5 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -1009,7 +1009,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) /* Link all private pointers */ mtd = nand_to_mtd(&host->nand); nand = &host->nand; - mtd->priv = nand; nand->priv = host; nand_set_flash_node(nand, np); diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index 99dd74c..ded658f 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c @@ -278,7 +278,6 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->cmd_ctrl = gpio_nand_cmd_ctrl; mtd = nand_to_mtd(chip); - mtd->priv = chip; mtd->dev.parent = &pdev->dev; platform_set_drvdata(pdev, gpiomtd); diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 38b07c7..df61f49 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -1893,7 +1893,6 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) this->current_chip = -1; /* init the MTD data structures */ - mtd->priv = chip; mtd->name = "gpmi-nand"; mtd->dev.parent = this->dev; diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c index 6e6e482..2aee212 100644 --- a/drivers/mtd/nand/hisi504_nand.c +++ b/drivers/mtd/nand/hisi504_nand.c @@ -735,7 +735,6 @@ static int hisi_nfc_probe(struct platform_device *pdev) goto err_res; } - mtd->priv = chip; mtd->name = "hisi_nand"; mtd->dev.parent = &pdev->dev; diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 03239a5..a2363d3 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -433,7 +433,6 @@ static int jz_nand_probe(struct platform_device *pdev) chip = &nand->chip; mtd = nand_to_mtd(chip); - mtd->priv = chip; mtd->dev.parent = &pdev->dev; mtd->name = "jz4740-nand"; diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index 3400b3f..db59fa2 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -681,7 +681,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) nand_chip->priv = host; /* link the private data structures */ nand_set_flash_node(nand_chip, pdev->dev.of_node); - mtd->priv = nand_chip; mtd->dev.parent = &pdev->dev; /* Get NAND clock */ diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index 61b2961..ccd10b1 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c @@ -802,7 +802,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) mtd = nand_to_mtd(chip); chip->priv = host; nand_set_flash_node(chip, pdev->dev.of_node); - mtd->priv = chip; mtd->owner = THIS_MODULE; mtd->dev.parent = &pdev->dev; diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 8b4cd82..6d0ca33 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -656,7 +656,6 @@ static int mpc5121_nfc_probe(struct platform_device *op) chip = &prv->chip; mtd = nand_to_mtd(chip); - mtd->priv = chip; mtd->dev.parent = dev; chip->priv = prv; nand_set_flash_node(chip, dn); diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 9dd71af..9540099 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -1514,7 +1514,6 @@ static int mxcnd_probe(struct platform_device *pdev) /* structures must be linked */ this = &host->nand; mtd = nand_to_mtd(this); - mtd->priv = this; mtd->dev.parent = &pdev->dev; mtd->name = DRIVER_NAME; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 442eeaf..78de37d 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -2243,7 +2243,6 @@ static int __init ns_init_module(void) return -ENOMEM; } nsmtd = nand_to_mtd(chip); - nsmtd->priv = (void *)chip; nand = (struct nandsim *)(chip + 1); chip->priv = (void *)nand; diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 3a7168e..0709ea9 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -167,7 +167,6 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, chip->ecc.strength = 1; chip->priv = ndfc; - mtd->priv = chip; mtd->dev.parent = &ndfc->ofdev->dev; flash_np = of_get_next_child(node, NULL); diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 4dad170..220ddfc 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -245,7 +245,6 @@ static int nuc900_nand_probe(struct platform_device *pdev) chip = &(nuc900_nand->chip); mtd = nand_to_mtd(chip); - mtd->priv = chip; mtd->dev.parent = &pdev->dev; spin_lock_init(&nuc900_nand->lock); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index f9d0b58..e9cbbc6 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1672,7 +1672,6 @@ static int omap_nand_probe(struct platform_device *pdev) info->ecc_opt = pdata->ecc_opt; nand_chip = &info->nand; mtd = nand_to_mtd(nand_chip); - mtd->priv = &info->nand; mtd->dev.parent = &pdev->dev; nand_chip->ecc.priv = NULL; nand_set_flash_node(nand_chip, pdata->of_node); diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 087a040..2c2be612 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -122,7 +122,6 @@ static int __init orion_nand_probe(struct platform_device *pdev) board = dev_get_platdata(&pdev->dev); } - mtd->priv = nc; mtd->dev.parent = &pdev->dev; nc->priv = board; diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 4dd2985..3ab53ca 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -121,7 +121,6 @@ static int pasemi_nand_probe(struct platform_device *ofdev) pasemi_nand_mtd = nand_to_mtd(chip); /* Link the private data with the MTD structure */ - pasemi_nand_mtd->priv = chip; pasemi_nand_mtd->dev.parent = &ofdev->dev; chip->IO_ADDR_R = of_iomap(np, 0); diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 796eb7d..dc88a58 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -59,7 +59,6 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.priv = &data; nand_set_flash_node(&data->chip, pdev->dev.of_node); mtd = nand_to_mtd(&data->chip); - mtd->priv = &data->chip; mtd->dev.parent = &pdev->dev; data->chip.IO_ADDR_R = data->io_base; diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index c4d5788..10704ae 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1709,7 +1709,6 @@ static int alloc_nand_resource(struct platform_device *pdev) info->host[cs] = host; host->cs = cs; host->info_data = info; - mtd->priv = chip; mtd->dev.parent = &pdev->dev; /* FIXME: all chips use the same device tree partitions */ nand_set_flash_node(chip, np); diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 1ac8ef2..cb0bf09 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -638,7 +638,6 @@ static int r852_register_nand_device(struct r852_device *dev) WARN_ON(dev->card_registred); - mtd->priv = dev->chip; mtd->dev.parent = &dev->pci_dev->dev; if (dev->readonly) diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index c074a49..bc94c5d 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -788,7 +788,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, struct s3c2410_nand_set *set) { struct nand_chip *chip = &nmtd->chip; - struct mtd_info *mtd = nand_to_mtd(chip); void __iomem *regs = info->regs; chip->write_buf = s3c2410_nand_write_buf; @@ -834,7 +833,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->IO_ADDR_R = chip->IO_ADDR_W; nmtd->info = info; - mtd->priv = chip; nmtd->set = set; #ifdef CONFIG_MTD_NAND_S3C2410_HWECC diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 0ec4b04..c7126b7 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -1123,7 +1123,6 @@ static int flctl_probe(struct platform_device *pdev) nand = &flctl->chip; flctl_mtd = nand_to_mtd(nand); nand_set_flash_node(nand, pdev->dev.of_node); - flctl_mtd->priv = nand; flctl_mtd->dev.parent = &pdev->dev; flctl->pdev = pdev; flctl->hwecc = pdata->has_hwecc; diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 4b649fb..b7d1b55 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -147,7 +147,6 @@ static int sharpsl_nand_probe(struct platform_device *pdev) /* Link the private data with the MTD structure */ mtd = nand_to_mtd(this); - mtd->priv = this; mtd->dev.parent = &pdev->dev; platform_set_drvdata(pdev, sharpsl); diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index 925761c..d7e9d4d 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -164,7 +164,6 @@ static int socrates_nand_probe(struct platform_device *ofdev) nand_chip->priv = host; /* link the private data structures */ nand_set_flash_node(nand_chip, ofdev->dev.of_node); - mtd->priv = nand_chip; mtd->name = "socrates_nand"; mtd->dev.parent = &ofdev->dev; diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index c29d659..51e10a3 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -1337,7 +1337,6 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, mtd = nand_to_mtd(nand); mtd->dev.parent = dev; - mtd->priv = nand; ret = nand_scan_ident(mtd, nsels, NULL); if (ret) diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index e7b82e1..08b3054 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c @@ -382,7 +382,6 @@ static int tmio_probe(struct platform_device *dev) platform_set_drvdata(dev, tmio); nand_chip = &tmio->chip; mtd = nand_to_mtd(nand_chip); - mtd->priv = nand_chip; mtd->name = "tmio-nand"; mtd->dev.parent = &dev->dev; diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index da7fcbd..27488ee 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c @@ -324,8 +324,6 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) mtd = nand_to_mtd(chip); mtd->dev.parent = &dev->dev; - mtd->priv = chip; - chip->read_byte = txx9ndfmc_read_byte; chip->read_buf = txx9ndfmc_read_buf; chip->write_buf = txx9ndfmc_write_buf; diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 1bbb93a..034420f 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -679,7 +679,6 @@ static int vf610_nfc_probe(struct platform_device *pdev) chip = &nfc->chip; mtd = nand_to_mtd(chip); - mtd->priv = chip; mtd->owner = THIS_MODULE; mtd->dev.parent = nfc->dev; mtd->name = DRV_NAME; -- cgit v1.1 From 7194a29a9bf1e5abcda8b181bba771fbe0e95b6c Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:37 +0100 Subject: mtd: nand: simplify nand_dt_init() usage nand_dt_init() function requires 3 arguments where it actually needs one (dn and mtd can both be retrieved from chip). Drop these parameters. Testing for dn != NULL inside nand_dt_init() also helps simplifying the caller code. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5aec154..ae3fd2a 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3937,11 +3937,17 @@ ident_done: return type; } -static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, - struct device_node *dn) +static int nand_dt_init(struct nand_chip *chip) { + struct device_node *dn = nand_get_flash_node(chip); int ecc_mode, ecc_strength, ecc_step; + if (!dn) + return 0; + + /* MTD can automatically handle DT partitions, etc. */ + mtd_set_of_node(nand_to_mtd(chip), dn); + if (of_get_nand_bus_width(dn) == 16) chip->options |= NAND_BUSWIDTH_16; @@ -3989,14 +3995,9 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, struct nand_flash_dev *type; int ret; - if (nand_get_flash_node(chip)) { - /* MTD can automatically handle DT partitions, etc. */ - mtd_set_of_node(mtd, nand_get_flash_node(chip)); - - ret = nand_dt_init(mtd, chip, nand_get_flash_node(chip)); - if (ret) - return ret; - } + ret = nand_dt_init(chip); + if (ret) + return ret; /* Set the default functions */ nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16); -- cgit v1.1 From 29574ede097438c560e8115caff9b6b8668730be Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:38 +0100 Subject: mtd: nand: kill the chip->flash_node field Now that the nand_chip struct directly embeds an mtd_info struct we can get rid of the ->flash_node field and forward set/get_flash_node requests to the MTD layer. As a side effect, we no longer need the mtd_set_of_node() call done in nand_dt_init(). Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ae3fd2a..8bb8ebd6 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3945,9 +3945,6 @@ static int nand_dt_init(struct nand_chip *chip) if (!dn) return 0; - /* MTD can automatically handle DT partitions, etc. */ - mtd_set_of_node(nand_to_mtd(chip), dn); - if (of_get_nand_bus_width(dn) == 16) chip->options |= NAND_BUSWIDTH_16; -- cgit v1.1 From 8142b47ef33c655a34e08efd46b65732fe190675 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 14 Dec 2015 16:13:31 +0100 Subject: mtd: nand: remove unused and buggy get_platform_nandchip() helper function Nobody uses the get_platform_nandchip() helper function which is supposed to return a pointer to a platform_nand_chip struct from an mtd_info pointer. Moreover, this function is buggy since the introduction of the plat_nand layer (chip->priv is now storing a pointer to an intermediate plat_nand_data structure allocated in plat_nand_probe(), and we have no way to retrieve a pointer to the provided platform_nand_chip struct from this plat_nand_data pointer). While we are at it, remove the useless (and buggy, since it's pointing to something stored on the stack) data->chip.priv assignment. Signed-off-by: Boris Brezillon Fixes: 711fdf627ce1 ("[MTD] [NAND] platform NAND driver: add driver") Cc: Vitaly Wool Signed-off-by: Brian Norris --- drivers/mtd/nand/plat_nand.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index dc88a58..a0e26de 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -56,7 +56,6 @@ static int plat_nand_probe(struct platform_device *pdev) if (IS_ERR(data->io_base)) return PTR_ERR(data->io_base); - data->chip.priv = &data; nand_set_flash_node(&data->chip, pdev->dev.of_node); mtd = nand_to_mtd(&data->chip); mtd->dev.parent = &pdev->dev; -- cgit v1.1 From 80e1ca692107b0bc5b088fd9c4a20726fb1a66a2 Mon Sep 17 00:00:00 2001 From: Bayi Cheng Date: Fri, 18 Dec 2015 11:02:40 +0800 Subject: mtd: mtk-nor: adjust sequence of trigger function and assignment function Move write data register before excute command to avoid missing first byte write to nor flash Signed-off-by: Bayi Cheng Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/mtk-quadspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c index e1dd9fd..d5f850d 100644 --- a/drivers/mtd/spi-nor/mtk-quadspi.c +++ b/drivers/mtd/spi-nor/mtk-quadspi.c @@ -272,10 +272,10 @@ static int mt8173_nor_write_single_byte(struct mt8173_nor *mt8173_nor, mt8173_nor_set_addr(mt8173_nor, addr); for (i = 0; i < length; i++) { + writeb(*data++, mt8173_nor->base + MTK_NOR_WDATA_REG); ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PIO_WR_CMD); if (ret < 0) return ret; - writeb(*data++, mt8173_nor->base + MTK_NOR_WDATA_REG); } return 0; } -- cgit v1.1 From fdd9d27c8a47ea81daeaddfe6c0156ae7cf68096 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 10 Jun 2015 18:31:32 +0200 Subject: mtd: cfi_cmdset_0002: use swap() in cfi_cmdset_0002() Use kernel.h macro definition. Thanks to Julia Lawall for Coccinelle scripting support. Signed-off-by: Fabian Frederick Signed-off-by: Brian Norris --- drivers/mtd/chips/cfi_cmdset_0002.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index c3624eb..9dca881 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -615,11 +615,9 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) for (i=0; icfiq->NumEraseRegions / 2; i++) { int j = (cfi->cfiq->NumEraseRegions-1)-i; - __u32 swap; - swap = cfi->cfiq->EraseRegionInfo[i]; - cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j]; - cfi->cfiq->EraseRegionInfo[j] = swap; + swap(cfi->cfiq->EraseRegionInfo[i], + cfi->cfiq->EraseRegionInfo[j]); } } /* Set the default CFI lock/unlock addresses */ -- cgit v1.1 From 6166a76f5ef7619faa28b38d7817e5fe0e509942 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 10 Jun 2015 18:31:06 +0200 Subject: mtd: ftl: use swap() in copy_erase_unit() Use kernel.h macro definition. Thanks to Julia Lawall for Coccinelle scripting support. Signed-off-by: Fabian Frederick Signed-off-by: Brian Norris --- drivers/mtd/ftl.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index dabf084..9fb3b0d 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -571,12 +571,8 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit, /* Update the maps and usage stats*/ - i = xfer->EraseCount; - xfer->EraseCount = eun->EraseCount; - eun->EraseCount = i; - i = xfer->Offset; - xfer->Offset = eun->Offset; - eun->Offset = i; + swap(xfer->EraseCount, eun->EraseCount); + swap(xfer->Offset, eun->Offset); part->FreeTotal -= eun->Free; part->FreeTotal += free; eun->Free = free; -- cgit v1.1 From 44991b3d19cd71eabe68019ae7cb91df0c929614 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 9 Apr 2014 11:13:24 +0200 Subject: mtd: nand: Disable subpage writes for drivers without ecc->hwctl nand_write_subpage_hwecc causes a crash if the driver did not register ecc->hwctl or ecc->calculate. Fix this by disabling subpage writes if ecc->hwctl or ecc->calculate is not provided by the driver. This behavior was introduced in commit 837a6ba4f3b6d23026674e6af6b6849a4634fff9 "mtd: nand: subpage write support for hardware based ECC schemes". This fixes a crash with fsl_elbc_nand and maybe others: Unable to handle kernel paging request for instruction fetch Faulting instruction address: 0x00000000 Oops: Kernel access of bad area, sig: 11 [#1] SMP NR_CPUS=2 P1020 RDB Modules linked in: ath9k ath9k_common pppoe ppp_async option iptable_nat ath9k_hw ath usb_wwan pppox ppp_generic nf_nat_ipv4 nf_conntrack_ipv4 mac80211 ipt_MASQUERADE cfg80211 xt_time xt_tcpudp xt_state xt_quota xt_policy xt_pkttype xt_owner xt_nat xt_multiport xt_mh CPU: 1 PID: 2161 Comm: ubiformat Not tainted 3.10.26 #6 task: efbc2700 ti: c7950000 task.ti: c7950000 NIP: 00000000 LR: c01a495c CTR: 00000000 REGS: c7951cb0 TRAP: 0400 Not tainted (3.10.26) MSR: 00029000 CR: 24002028 XER: 00000000 GPR00: c01a4b6c c7951d60 efbc2700 ef84b000 00000001 00000000 000001ff c7800500 GPR08: 00000000 00000000 efae5e40 c01a4ae4 24002022 10023418 c7951e5c c7800500 GPR16: c017b6a8 00000000 0000003f c053404c 00000000 00000004 00000000 00000003 GPR24: 00000010 00000200 ef84b000 c7800d00 c7800000 c7800500 ef84b1c8 00000000 NIP [00000000] (null) LR [c01a495c] nand_write_subpage_hwecc+0x74/0x174 Call Trace: [c7951d60] [c7951d64] 0xc7951d64 (unreliable) [c7951da0] [c01a4b6c] nand_write_page+0x88/0x198 [c7951dd0] [c01a5f7c] nand_do_write_ops+0x2f4/0x39c [c7951e40] [c01a61e0] nand_write+0x58/0x84 [c7951e80] [c019e29c] mtdchar_write+0x1dc/0x28c [c7951ef0] [c00aba84] vfs_write+0xcc/0x1ac [c7951f10] [c00ac04c] SyS_write+0x4c/0x90 [c7951f40] [c000cd84] ret_from_syscall+0x0/0x3c --- Exception: c01 at 0x48050ed8 LR = 0x100071b8 Instruction dump: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX ---[ end trace 161d3c65a2a15cb8 ]--- Kernel panic - not syncing: Fatal exception [Brian: editorial note - we've applied a previous fix for the driver in question (fsl_elbc_nand) long ago: commit f034d87def51 ("mtd: eLBC NAND: fix subpage write support") but this still makes sense, and it could solve issues on some other unforseen driver.] Cc: Pekon Gupta Cc: Artem Bityutskiy Cc: David Woodhouse Signed-off-by: Helmut Schaa Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 8bb8ebd6..928081b 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4167,7 +4167,7 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->write_oob = nand_write_oob_std; if (!ecc->read_subpage) ecc->read_subpage = nand_read_subpage; - if (!ecc->write_subpage) + if (!ecc->write_subpage && ecc->hwctl && ecc->calculate) ecc->write_subpage = nand_write_subpage_hwecc; case NAND_ECC_HW_SYNDROME: -- cgit v1.1 From 0ed6ca3a22f871fdb7335194f6488d14b2dad96a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 16 Dec 2015 14:00:09 +0900 Subject: mtd: denali: make MTD_NAND_DENALI_DT dependent on OF The build passes even if CONFIG_OF is undefined, but it makes sense to let it depend on OF. Signed-off-by: Masahiro Yamada Signed-off-by: Brian Norris --- drivers/mtd/nand/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 6c71f62..95b8d2b 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -55,7 +55,7 @@ config MTD_NAND_DENALI_PCI config MTD_NAND_DENALI_DT tristate "Support Denali NAND controller as a DT device" select MTD_NAND_DENALI - depends on HAS_DMA && HAVE_CLK + depends on HAS_DMA && HAVE_CLK && OF help Enable the driver for NAND flash on platforms using a Denali NAND controller as a DT device. -- cgit v1.1 From 1873315fb156cbc8e46f28e8b128f17ff6c31728 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 8 Dec 2015 16:38:12 +0100 Subject: mtd: sh_flctl: pass FIFO as physical address By convention, the FIFO address we pass using dmaengine_slave_config is a physical address in the form that is understood by the DMA engine, as a dma_addr_t, phys_addr_t or resource_size_t. The sh_flctl driver however passes a virtual __iomem address that gets cast to dma_addr_t in the slave driver. This happens to work on shmobile because that platform sets up an identity mapping for its MMIO regions, but such code is not portable to other platforms, and prevents us from ever changing the platform mapping or reusing the driver on other architectures like ARM64 that might not have the mapping. We also get a warning about a type mismatch for the case that dma_addr_t is wider than a pointer, i.e. when CONFIG_LPAE is set: drivers/mtd/nand/sh_flctl.c: In function 'flctl_setup_dma': drivers/mtd/nand/sh_flctl.c:163:17: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] cfg.dst_addr = (dma_addr_t)FLDTFIFO(flctl); This changes the driver to instead pass the physical address of the FIFO that is extracted from the MMIO resource, making the code more portable and avoiding the warning. Signed-off-by: Arnd Bergmann Signed-off-by: Brian Norris --- drivers/mtd/nand/sh_flctl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index c7126b7..4814402 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -160,7 +160,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl) memset(&cfg, 0, sizeof(cfg)); cfg.direction = DMA_MEM_TO_DEV; - cfg.dst_addr = (dma_addr_t)FLDTFIFO(flctl); + cfg.dst_addr = flctl->fifo; cfg.src_addr = 0; ret = dmaengine_slave_config(flctl->chan_fifo0_tx, &cfg); if (ret < 0) @@ -176,7 +176,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl) cfg.direction = DMA_DEV_TO_MEM; cfg.dst_addr = 0; - cfg.src_addr = (dma_addr_t)FLDTFIFO(flctl); + cfg.src_addr = flctl->fifo; ret = dmaengine_slave_config(flctl->chan_fifo0_rx, &cfg); if (ret < 0) goto err; @@ -1095,6 +1095,7 @@ static int flctl_probe(struct platform_device *pdev) flctl->reg = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(flctl->reg)) return PTR_ERR(flctl->reg); + flctl->fifo = res->start + 0x24; /* FLDTFIFO */ irq = platform_get_irq(pdev, 0); if (irq < 0) { -- cgit v1.1 From 4802c5919a70661d5022710d88e311c3880cd0fd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 29 Dec 2015 14:55:33 -0500 Subject: drivers/mtd/maps/pcmciamtd.c: __iomem annotations Signed-off-by: Al Viro --- drivers/mtd/maps/pcmciamtd.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 3dad211..70bb403 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -30,7 +30,7 @@ struct pcmciamtd_dev { struct pcmcia_device *p_dev; - caddr_t win_base; /* ioremapped address of PCMCIA window */ + void __iomem *win_base; /* ioremapped address of PCMCIA window */ unsigned int win_size; /* size of window */ unsigned int offset; /* offset into card the window currently points at */ struct map_info pcmcia_map; @@ -80,7 +80,7 @@ MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)") /* read/write{8,16} copy_{from,to} routines with window remapping * to access whole card */ -static caddr_t remap_window(struct map_info *map, unsigned long to) +static void __iomem *remap_window(struct map_info *map, unsigned long to) { struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; struct resource *win = (struct resource *) map->map_priv_2; @@ -107,7 +107,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs) { - caddr_t addr; + void __iomem *addr; map_word d = {{0}}; addr = remap_window(map, ofs); @@ -122,7 +122,7 @@ static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs) static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs) { - caddr_t addr; + void __iomem *addr; map_word d = {{0}}; addr = remap_window(map, ofs); @@ -143,7 +143,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long pr_debug("to = %p from = %lu len = %zd\n", to, from, len); while(len) { int toread = win_size - (from & (win_size-1)); - caddr_t addr; + void __iomem *addr; if(toread > len) toread = len; @@ -163,7 +163,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long adr) { - caddr_t addr = remap_window(map, adr); + void __iomem *addr = remap_window(map, adr); if(!addr) return; @@ -175,7 +175,7 @@ static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long adr) { - caddr_t addr = remap_window(map, adr); + void __iomem *addr = remap_window(map, adr); if(!addr) return; @@ -192,7 +192,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v pr_debug("to = %lu from = %p len = %zd\n", to, from, len); while(len) { int towrite = win_size - (to & (win_size-1)); - caddr_t addr; + void __iomem *addr; if(towrite > len) towrite = len; @@ -216,7 +216,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) { - caddr_t win_base = (caddr_t)map->map_priv_2; + void __iomem *win_base = (void __iomem *)map->map_priv_2; map_word d = {{0}}; if(DEV_REMOVED(map)) @@ -231,7 +231,7 @@ static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) static map_word pcmcia_read16(struct map_info *map, unsigned long ofs) { - caddr_t win_base = (caddr_t)map->map_priv_2; + void __iomem *win_base = (void __iomem *)map->map_priv_2; map_word d = {{0}}; if(DEV_REMOVED(map)) @@ -246,7 +246,7 @@ static map_word pcmcia_read16(struct map_info *map, unsigned long ofs) static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) { - caddr_t win_base = (caddr_t)map->map_priv_2; + void __iomem *win_base = (void __iomem *)map->map_priv_2; if(DEV_REMOVED(map)) return; @@ -258,7 +258,7 @@ static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr) { - caddr_t win_base = (caddr_t)map->map_priv_2; + void __iomem *win_base = (void __iomem *)map->map_priv_2; if(DEV_REMOVED(map)) return; @@ -271,7 +271,7 @@ static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr) static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr) { - caddr_t win_base = (caddr_t)map->map_priv_2; + void __iomem *win_base = (void __iomem *)map->map_priv_2; if(DEV_REMOVED(map)) return; @@ -284,7 +284,7 @@ static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr) static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) { - caddr_t win_base = (caddr_t)map->map_priv_2; + void __iomem *win_base = (void __iomem *)map->map_priv_2; if(DEV_REMOVED(map)) return; -- cgit v1.1 From 472b444eef934eb7e90334efdd7fc7954cfe5132 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 11 Dec 2015 15:58:01 -0800 Subject: mtd: fix cmdlinepart parser, early naming for auto-filled MTD Commit 807f16d4db95 ("mtd: core: set some defaults when dev.parent is set") attempted to provide some default settings for MTDs that (a) assign the parent device and (b) don't provide their own name or owner However, this isn't a perfect drop-in replacement for the boilerplate found in some drivers, because the MTD name is used by partition parsers like cmdlinepart, but the name isn't set until add_mtd_device(), after the parsing is completed. This means cmdlinepart sees a NULL name and therefore will not work properly. Fix this by moving the default name and owner assignment to be first in the MTD registration process. [Note: this does not fix all reported issues, particularly with NAND drivers. Will require an additional fix for drivers/mtd/nand/] Fixes: 807f16d4db95 ("mtd: core: set some defaults when dev.parent is set") Reported-by: Heiko Schocher Signed-off-by: Brian Norris Cc: Heiko Schocher Cc: Frans Klaver --- drivers/mtd/mtdcore.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 95c13b2..ffa2884 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -426,15 +426,6 @@ int add_mtd_device(struct mtd_info *mtd) mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; - if (mtd->dev.parent) { - if (!mtd->owner && mtd->dev.parent->driver) - mtd->owner = mtd->dev.parent->driver->owner; - if (!mtd->name) - mtd->name = dev_name(mtd->dev.parent); - } else { - pr_debug("mtd device won't show a device symlink in sysfs\n"); - } - /* Some chips always power up locked. Unlock them now */ if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) { error = mtd_unlock(mtd, 0, mtd->size); @@ -549,6 +540,21 @@ static int mtd_add_device_partitions(struct mtd_info *mtd, return 0; } +/* + * Set a few defaults based on the parent devices, if not provided by the + * driver + */ +static void mtd_set_dev_defaults(struct mtd_info *mtd) +{ + if (mtd->dev.parent) { + if (!mtd->owner && mtd->dev.parent->driver) + mtd->owner = mtd->dev.parent->driver->owner; + if (!mtd->name) + mtd->name = dev_name(mtd->dev.parent); + } else { + pr_debug("mtd device won't show a device symlink in sysfs\n"); + } +} /** * mtd_device_parse_register - parse partitions and register an MTD device. @@ -587,6 +593,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, int ret; struct mtd_partition *real_parts = NULL; + mtd_set_dev_defaults(mtd); + ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data); if (ret <= 0 && nr_parts && parts) { real_parts = kmemdup(parts, sizeof(*parts) * nr_parts, -- cgit v1.1 From 887e9d3a1f3e93a1c64294649c0dd301035a7892 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 4 Jan 2016 10:32:54 -0800 Subject: mtd: nand: fix for drop unnecessary partition parser data From Stephen: Hi Brian, After merging the l2-mtd tree, today's linux-next build (powerpc ppc44x_defconfig) failed like this: drivers/mtd/nand/ndfc.c: In function 'ndfc_chip_init': drivers/mtd/nand/ndfc.c:177:2: error: 'ppdata' undeclared (first use in this function) ppdata.of_node = flash_np; ^ Caused by commit a61ae81a1907 ("mtd: nand: drop unnecessary partition parser data") The flash node is already correctly assigned using the new helper (nand_set_flash_node()) so the correct fix is indeed to simply drop this line. Fixes: a61ae81a1907 ("mtd: nand: drop unnecessary partition parser data") Signed-off-by: Stephen Rothwell Signed-off-by: Brian Norris --- drivers/mtd/nand/ndfc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 0709ea9..7d72f4f 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -174,7 +174,6 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, return -ENODEV; nand_set_flash_node(chip, flash_np); - ppdata.of_node = flash_np; mtd->name = kasprintf(GFP_KERNEL, "%s.%s", dev_name(&ndfc->ofdev->dev), flash_np->name); if (!mtd->name) { -- cgit v1.1 From 67b9bcd36906e12a15ffec19463afbbd6a41660e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 15 Dec 2015 10:48:20 -0800 Subject: mtd: spi-nor: fix Spansion regressions (aliased with Winbond) Spansion and Winbond have occasionally used the same manufacturer ID, and they don't support the same features. Particularly, writing SR=0 seems to break read access for Spansion's s25fl064k. Unfortunately, we don't currently have a way to differentiate these Spansion and Winbond parts, so rather than regressing support for these Spansion flash, let's drop the new Winbond lock/unlock support for now. We can try to address Winbond support during the next release cycle. Original discussion: http://patchwork.ozlabs.org/patch/549173/ http://patchwork.ozlabs.org/patch/553683/ Fixes: 357ca38d4751 ("mtd: spi-nor: support lock/unlock/is_locked for Winbond") Fixes: c6fc2171b249 ("mtd: spi-nor: disable protection for Winbond flash at startup") Signed-off-by: Brian Norris Reported-by: Felix Fietkau Cc: Felix Fietkau --- drivers/mtd/spi-nor/spi-nor.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 4988390..f5d59de 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1200,8 +1200,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || JEDEC_MFR(info) == SNOR_MFR_INTEL || - JEDEC_MFR(info) == SNOR_MFR_SST || - JEDEC_MFR(info) == SNOR_MFR_WINBOND) { + JEDEC_MFR(info) == SNOR_MFR_SST) { write_enable(nor); write_sr(nor, 0); } @@ -1217,8 +1216,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) mtd->_read = spi_nor_read; /* NOR protection support for STmicro/Micron chips and similar */ - if (JEDEC_MFR(info) == SNOR_MFR_MICRON || - JEDEC_MFR(info) == SNOR_MFR_WINBOND) { + if (JEDEC_MFR(info) == SNOR_MFR_MICRON) { nor->flash_lock = stm_lock; nor->flash_unlock = stm_unlock; nor->flash_is_locked = stm_is_locked; -- cgit v1.1 From a32d5b726ff8cf32bf491522b0ac8ae2545a063e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 15 Dec 2015 10:48:21 -0800 Subject: mtd: spi-nor: fix stm_is_locked_sr() parameters stm_is_locked_sr() takes the status register (SR) value as the last parameter, not the second. Reported-by: Bayi Cheng Signed-off-by: Brian Norris Cc: Bayi Cheng --- drivers/mtd/spi-nor/spi-nor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index f5d59de..32477c4 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -516,8 +516,8 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) status_old = read_sr(nor); /* Cannot unlock; would unlock larger region than requested */ - if (stm_is_locked_sr(nor, status_old, ofs - mtd->erasesize, - mtd->erasesize)) + if (stm_is_locked_sr(nor, ofs - mtd->erasesize, mtd->erasesize, + status_old)) return -EINVAL; /* -- cgit v1.1 From f7a8e38f07a17be90758559fe66fe7337096053f Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 5 Jan 2016 10:39:45 -0800 Subject: mtd: nand: assign reasonable default name for NAND drivers Commits such as commit 853f1c58c4b2 ("mtd: nand: omap2: show parent device structure in sysfs") attempt to rely on the core MTD code to set the MTD name based on the parent device. However, nand_base tries to set a different default name according to the flash name (e.g., extracted from the ONFI parameter page), which means NAND drivers will never make use of the MTD defaults. This is not the intention of commit 853f1c58c4b2. This results in problems when trying to use the cmdline partition parser, since the MTD name is different than expected. Let's fix this by providing a default NAND name, where possible. Note that this is not really a great default name in the long run, since this means that if there are multiple MTDs attached to the same controller device, they will have the same name. But that is an existing issue and requires future work on a better controller vs. flash chip abstraction to fix properly. Fixes: 853f1c58c4b2 ("mtd: nand: omap2: show parent device structure in sysfs") Reported-by: Heiko Schocher Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon Tested-by: Heiko Schocher Cc: Heiko Schocher Cc: Frans Klaver Cc: --- drivers/mtd/nand/nand_base.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 928081b..50514f2 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3996,6 +3996,9 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, if (ret) return ret; + if (!mtd->name && mtd->dev.parent) + mtd->name = dev_name(mtd->dev.parent); + /* Set the default functions */ nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16); -- cgit v1.1 From 6e75632ac34d2f63ab586880f7e9747bd9b708a6 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Thu, 31 Dec 2015 16:21:22 +0100 Subject: mtd: tests: consolidate kmalloc/memset 0 call to kzalloc This is an API consolidation only. The use of kmalloc + memset to 0 is equivalent to kzalloc. Signed-off-by: Nicholas Mc Guire Signed-off-by: Brian Norris --- drivers/mtd/tests/pagetest.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/tests/pagetest.c b/drivers/mtd/tests/pagetest.c index ba1890d..ff1e056 100644 --- a/drivers/mtd/tests/pagetest.c +++ b/drivers/mtd/tests/pagetest.c @@ -127,13 +127,12 @@ static int crosstest(void) unsigned char *pp1, *pp2, *pp3, *pp4; pr_info("crosstest\n"); - pp1 = kmalloc(pgsize * 4, GFP_KERNEL); + pp1 = kzalloc(pgsize * 4, GFP_KERNEL); if (!pp1) return -ENOMEM; pp2 = pp1 + pgsize; pp3 = pp2 + pgsize; pp4 = pp3 + pgsize; - memset(pp1, 0, pgsize * 4); addr0 = 0; for (i = 0; i < ebcnt && bbt[i]; ++i) -- cgit v1.1 From 32321e950d8a237d7e8f3a9b76220007dfa87544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Mon, 28 Dec 2015 17:54:51 -0300 Subject: mtd: spi-nor: wait until lock/unlock operations are ready On Micron and Numonyx devices, the status register write command (WRSR), raises a work-in-progress bit (WIP) on the status register. The datasheets for these devices specify that while the status register write is in progress, the status register WIP bit can still be read to check the end of the operation. This commit adds a wait_till_ready call on lock/unlock operations, which is required for Micron and Numonyx but should be harmless for others. This is needed to prevent applications from issuing erase or program operations before the unlock operation is completed. Reported-by: Stas Sergeev Signed-off-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/spi-nor.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index f8f36d4..ed0c19c 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -481,6 +481,7 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) int status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; + int ret; status_old = read_sr(nor); if (status_old < 0) @@ -519,7 +520,10 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) return -EINVAL; write_enable(nor); - return write_sr(nor, status_new); + ret = write_sr(nor, status_new); + if (ret) + return ret; + return spi_nor_wait_till_ready(nor); } /* @@ -533,6 +537,7 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) int status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; + int ret; status_old = read_sr(nor); if (status_old < 0) @@ -569,7 +574,10 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) return -EINVAL; write_enable(nor); - return write_sr(nor, status_new); + ret = write_sr(nor, status_new); + if (ret) + return ret; + return spi_nor_wait_till_ready(nor); } /* -- cgit v1.1 From 33853ebd746f0e6aa262745376fde5d4995e0a87 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Tue, 29 Dec 2015 13:45:09 -0500 Subject: mtd: cfi_cmdset_0001: fixing memory leak and handling failed kmalloc kmalloc needs to be handled when failing in memory pressure. Also, it has memory leak in error routine. Signed-off-by: Insu Yun Signed-off-by: Brian Norris --- drivers/mtd/chips/cfi_cmdset_0001.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 286b97a..5e1b68c 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -596,7 +596,7 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; - mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) + mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); if (!mtd->eraseregions) goto setup_err; @@ -614,6 +614,8 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize; mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum; mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap = kmalloc(ernum / 8 + 1, GFP_KERNEL); + if (!mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap) + goto setup_err; } offset += (ersize * ernum); } @@ -650,6 +652,10 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) return mtd; setup_err: + if (mtd->eraseregions) + for (i=0; icfiq->NumEraseRegions; i++) + for (j=0; jnumchips; j++) + kfree(mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap); kfree(mtd->eraseregions); kfree(mtd); kfree(cfi->cmdset_priv); -- cgit v1.1 From 6e9411923b8f4c0e568cbae0f35b7ee4eb989914 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 30 Dec 2015 20:32:03 +0100 Subject: mtd: nand: return consistent error codes in ecc.correct() implementations The error code returned by the ecc.correct() are not consistent over the all implementations. Document the expected behavior in include/linux/mtd/nand.h and fix offending implementations. [Brian: this looks like a bugfix for the ECC reporting in the bf5xx_nand driver, but we haven't seen any testing results for it] Signed-off-by: Boris Brezillon Tested-by: Franklin S Cooper Jr. Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 2 +- drivers/mtd/nand/bf5xx_nand.c | 20 ++++++++++++++------ drivers/mtd/nand/davinci_nand.c | 6 +++--- drivers/mtd/nand/jz4740_nand.c | 4 ++-- drivers/mtd/nand/mxc_nand.c | 4 ++-- drivers/mtd/nand/nand_bch.c | 2 +- drivers/mtd/nand/nand_ecc.c | 2 +- drivers/mtd/nand/omap2.c | 6 +++--- drivers/mtd/nand/r852.c | 4 ++-- 9 files changed, 29 insertions(+), 21 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 18c4e14..b216bf5 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1445,7 +1445,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, * We can't correct so many errors */ dev_dbg(host->dev, "atmel_nand : multiple errors detected." " Unable to correct.\n"); - return -EIO; + return -EBADMSG; } /* if there's a single bit error : we can correct it */ diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 9514e13..89d9414 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -252,7 +252,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat, */ if (hweight32(syndrome[0]) == 1) { dev_err(info->device, "ECC data was incorrect!\n"); - return 1; + return -EBADMSG; } syndrome[1] = (calced & 0x7FF) ^ (stored & 0x7FF); @@ -285,7 +285,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat, data = data ^ (0x1 << failing_bit); *(dat + failing_byte) = data; - return 0; + return 1; } /* @@ -298,26 +298,34 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat, dev_err(info->device, "Please discard data, mark bad block\n"); - return 1; + return -EBADMSG; } static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { struct nand_chip *chip = mtd_to_nand(mtd); - int ret; + int ret, bitflips = 0; ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); + if (ret < 0) + return ret; + + bitflips = ret; /* If ecc size is 512, correct second 256 bytes */ if (chip->ecc.size == 512) { dat += 256; read_ecc += 3; calc_ecc += 3; - ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); + ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); + if (ret < 0) + return ret; + + bitflips += ret; } - return ret; + return bitflips; } static void bf5xx_nand_enable_hwecc(struct mtd_info *mtd, int mode) diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 3b49fe8..ddb73c3 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -207,7 +207,7 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat, dat[diff >> (12 + 3)] ^= BIT((diff >> 12) & 7); return 1; } else { - return -1; + return -EBADMSG; } } else if (!(diff & (diff - 1))) { /* Single bit ECC error in the ECC itself, @@ -215,7 +215,7 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat, return 1; } else { /* Uncorrectable error */ - return -1; + return -EBADMSG; } } @@ -391,7 +391,7 @@ compare: return 0; case 1: /* five or more errors detected */ davinci_nand_readl(info, NAND_ERR_ERRVAL1_OFFSET); - return -EIO; + return -EBADMSG; case 2: /* error addresses computed */ case 3: num_errors = 1 + ((fsr >> 16) & 0x03); diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index a2363d3..adccae3 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -254,7 +254,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, } while (!(status & JZ_NAND_STATUS_DEC_FINISH) && --timeout); if (timeout == 0) - return -1; + return -ETIMEDOUT; reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL); reg &= ~JZ_NAND_ECC_CTRL_ENABLE; @@ -262,7 +262,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, if (status & JZ_NAND_STATUS_ERROR) { if (status & JZ_NAND_STATUS_UNCOR_ERROR) - return -1; + return -EBADMSG; error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 9540099..66e56bb 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -674,7 +674,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); - return -1; + return -EBADMSG; } return 0; @@ -701,7 +701,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, err = ecc_stat & ecc_bit_mask; if (err > err_limit) { printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); - return -1; + return -EBADMSG; } else { ret += err; } diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index e5758d8..a87c1b6 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c @@ -98,7 +98,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf, } } else if (count < 0) { printk(KERN_ERR "ecc unrecoverable error\n"); - count = -1; + count = -EBADMSG; } return count; } diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index e612985..d1770b0 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c @@ -507,7 +507,7 @@ int __nand_correct_data(unsigned char *buf, return 1; /* error in ECC data; no action needed */ pr_err("%s: uncorrectable ECC error\n", __func__); - return -1; + return -EBADMSG; } EXPORT_SYMBOL(__nand_correct_data); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index e9cbbc6..c553f78 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -826,12 +826,12 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ case 1: /* Uncorrectable error */ pr_debug("ECC UNCORRECTED_ERROR 1\n"); - return -1; + return -EBADMSG; case 11: /* UN-Correctable error */ pr_debug("ECC UNCORRECTED_ERROR B\n"); - return -1; + return -EBADMSG; case 12: /* Correctable error */ @@ -861,7 +861,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ return 0; } pr_debug("UNCORRECTED_ERROR default\n"); - return -1; + return -EBADMSG; } } diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index cb0bf09..5b15f2f 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -477,7 +477,7 @@ static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, if (dev->dma_error) { dev->dma_error = 0; - return -1; + return -EIO; } r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS); @@ -491,7 +491,7 @@ static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, /* ecc uncorrectable error */ if (ecc_status & R852_ECC_FAIL) { dbg("ecc: unrecoverable error, in half %d", i); - error = -1; + error = -EBADMSG; goto exit; } -- cgit v1.1 From 40cbe6eee97b706f27bcc4c6aa1018bbe4f1e577 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 30 Dec 2015 20:32:04 +0100 Subject: mtd: nand: use nand_check_erased_ecc_chunk in default ECC read functions The default NAND read functions are relying on the underlying controller driver to correct bitflips, but some of those controllers cannot properly fix bitflips in erased pages. Check for bitflips in erased pages in default core functions if the driver delegated the this check by setting the NAND_ECC_GENERIC_ERASED_CHECK flag. Signed-off-by: Boris Brezillon Tested-by: Franklin S Cooper Jr. Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 53 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 50514f2..f2c8ff3 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1426,6 +1426,16 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); + if (stat == -EBADMSG && + (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { + /* check for empty pages with bitflips */ + stat = nand_check_erased_ecc_chunk(p, chip->ecc.size, + &chip->buffers->ecccode[i], + chip->ecc.bytes, + NULL, 0, + chip->ecc.strength); + } + if (stat < 0) { mtd->ecc_stats.failed++; } else { @@ -1475,6 +1485,15 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, int stat; stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + if (stat == -EBADMSG && + (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { + /* check for empty pages with bitflips */ + stat = nand_check_erased_ecc_chunk(p, eccsize, + &ecc_code[i], eccbytes, + NULL, 0, + chip->ecc.strength); + } + if (stat < 0) { mtd->ecc_stats.failed++; } else { @@ -1527,6 +1546,15 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, chip->ecc.calculate(mtd, p, &ecc_calc[i]); stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); + if (stat == -EBADMSG && + (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { + /* check for empty pages with bitflips */ + stat = nand_check_erased_ecc_chunk(p, eccsize, + &ecc_code[i], eccbytes, + NULL, 0, + chip->ecc.strength); + } + if (stat < 0) { mtd->ecc_stats.failed++; } else { @@ -1554,6 +1582,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; + int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad; uint8_t *p = buf; uint8_t *oob = chip->oob_poi; unsigned int max_bitflips = 0; @@ -1573,19 +1602,29 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, chip->read_buf(mtd, oob, eccbytes); stat = chip->ecc.correct(mtd, p, oob, NULL); - if (stat < 0) { - mtd->ecc_stats.failed++; - } else { - mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } - oob += eccbytes; if (chip->ecc.postpad) { chip->read_buf(mtd, oob, chip->ecc.postpad); oob += chip->ecc.postpad; } + + if (stat == -EBADMSG && + (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { + /* check for empty pages with bitflips */ + stat = nand_check_erased_ecc_chunk(p, chip->ecc.size, + oob - eccpadbytes, + eccpadbytes, + NULL, 0, + chip->ecc.strength); + } + + if (stat < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += stat; + max_bitflips = max_t(unsigned int, max_bitflips, stat); + } } /* Calculate remaining oob bytes */ -- cgit v1.1 From bc29c95d2e51305ec611f29cc703c2fa0d2086de Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 30 Dec 2015 20:32:05 +0100 Subject: mtd: nand: davinci: remove custom 'erased check' implementation The davinci driver is manually checking for 'erased pages' while correcting ECC bytes. This logic can now done by the core infrastructure, and can thus be removed from this driver. Signed-off-by: Boris Brezillon Tested-by: Franklin S Cooper Jr. Signed-off-by: Brian Norris --- drivers/mtd/nand/davinci_nand.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index ddb73c3..8cb821b 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -317,14 +317,6 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd, unsigned num_errors, corrected; unsigned long timeo; - /* All bytes 0xff? It's an erased page; ignore its ECC. */ - for (i = 0; i < 10; i++) { - if (ecc_code[i] != 0xff) - goto compare; - } - return 0; - -compare: /* Unpack ten bytes into eight 10 bit values. We know we're * little-endian, and use type punning for less shifting/masking. */ @@ -749,6 +741,7 @@ static int nand_davinci_probe(struct platform_device *pdev) info->chip.ecc.correct = nand_davinci_correct_4bit; info->chip.ecc.hwctl = nand_davinci_hwctl_4bit; info->chip.ecc.bytes = 10; + info->chip.ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; } else { info->chip.ecc.calculate = nand_davinci_calculate_1bit; info->chip.ecc.correct = nand_davinci_correct_1bit; -- cgit v1.1 From cc01e6075c7f5fee72746bb0ec763b84a46c3778 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 30 Dec 2015 20:39:52 +0100 Subject: mtd: nand: diskonchip: remove custom 'erased check' implementation The diskonchip driver is manually checking for 'erased pages' while correcting ECC bytes. This logic can now done by the core infrastructure, and can thus be removed from this driver. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/diskonchip.c | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index a5c0466..4f4aa35 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -74,10 +74,6 @@ struct doc_priv { int (*late_init)(struct mtd_info *mtd); }; -/* This is the syndrome computed by the HW ecc generator upon reading an empty - page, one with all 0xff for data and stored ecc code. */ -static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; - /* This is the ecc value computed by the HW ecc generator upon writing an empty page, one with all 0xff for data. */ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; @@ -912,7 +908,6 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, void __iomem *docptr = doc->virtadr; uint8_t calc_ecc[6]; volatile u_char dummy; - int emptymatch = 1; /* flush the pipeline */ if (DoC_is_2000(doc)) { @@ -936,37 +931,9 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, calc_ecc[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i); else calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i); - if (calc_ecc[i] != empty_read_syndrome[i]) - emptymatch = 0; - } - /* If emptymatch=1, the read syndrome is consistent with an - all-0xff data and stored ecc block. Check the stored ecc. */ - if (emptymatch) { - for (i = 0; i < 6; i++) { - if (read_ecc[i] == 0xff) - continue; - emptymatch = 0; - break; - } } - /* If emptymatch still =1, check the data block. */ - if (emptymatch) { - /* Note: this somewhat expensive test should not be triggered - often. It could be optimized away by examining the data in - the readbuf routine, and remembering the result. */ - for (i = 0; i < 512; i++) { - if (dat[i] == 0xff) - continue; - emptymatch = 0; - break; - } - } - /* If emptymatch still =1, this is almost certainly a freshly- - erased block, in which case the ECC will not come out right. - We'll suppress the error and tell the caller everything's - OK. Because it is. */ - if (!emptymatch) - ret = doc_ecc_decode(rs_decoder, dat, calc_ecc); + + ret = doc_ecc_decode(rs_decoder, dat, calc_ecc); if (ret > 0) printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); } @@ -1586,6 +1553,7 @@ static int __init doc_probe(unsigned long physadr) nand->ecc.size = 512; nand->ecc.bytes = 6; nand->ecc.strength = 2; + nand->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; nand->bbt_options = NAND_BBT_USE_FLASH; /* Skip the automatic BBT scan so we can run it manually */ nand->options |= NAND_SKIP_BBTSCAN; -- cgit v1.1 From 48bf35de3133996fbac2be16430cd4ea00fa8d38 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 30 Dec 2015 20:41:29 +0100 Subject: mtd: nand: jz4740: remove custom 'erased check' implementation The jz4740 driver is manually checking for 'erased pages' while correcting ECC bytes. This logic can now done by the core infrastructure, and can thus be removed from this driver. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/jz4740_nand.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index adccae3..b19d2a9 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -224,24 +224,6 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, uint32_t t; unsigned int timeout = 1000; - t = read_ecc[0]; - - if (t == 0xff) { - for (i = 1; i < 9; ++i) - t &= read_ecc[i]; - - t &= dat[0]; - t &= dat[nand->chip.ecc.size / 2]; - t &= dat[nand->chip.ecc.size - 1]; - - if (t == 0xff) { - for (i = 1; i < nand->chip.ecc.size - 1; ++i) - t &= dat[i]; - if (t == 0xff) - return 0; - } - } - for (i = 0; i < 9; ++i) writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i); @@ -443,6 +425,7 @@ static int jz_nand_probe(struct platform_device *pdev) chip->ecc.size = 512; chip->ecc.bytes = 9; chip->ecc.strength = 4; + chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; if (pdata) chip->ecc.layout = pdata->ecc_layout; -- cgit v1.1 From ae02ab00aa3c282a362af8c4496496970747ddf4 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 4 Jan 2016 12:34:43 +0000 Subject: mtd: nand: jz4780: driver for NAND devices on JZ4780 SoCs Add a driver for NAND devices connected to the NEMC on JZ4780 SoCs, as well as the hardware BCH controller. DMA is not currently implemented. While older 47xx SoCs also have a BCH controller, they are incompatible with the one in the 4780 due to differing register/bit positions, which would make implementing a common driver for them quite messy. Signed-off-by: Alex Smith Cc: Zubair Lutfullah Kakakhel Cc: David Woodhouse Cc: linux-mtd@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Harvey Hunt Reviewed-by: Boris Brezillon [Brian: fixed a few small mistakes] Signed-off-by: Brian Norris --- drivers/mtd/nand/Kconfig | 7 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/jz4780_bch.c | 381 ++++++++++++++++++++++++++++++++++++ drivers/mtd/nand/jz4780_bch.h | 43 +++++ drivers/mtd/nand/jz4780_nand.c | 425 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 857 insertions(+) create mode 100644 drivers/mtd/nand/jz4780_bch.c create mode 100644 drivers/mtd/nand/jz4780_bch.h create mode 100644 drivers/mtd/nand/jz4780_nand.c (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 95b8d2b..20f01b3 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -519,6 +519,13 @@ config MTD_NAND_JZ4740 help Enables support for NAND Flash on JZ4740 SoC based boards. +config MTD_NAND_JZ4780 + tristate "Support for NAND on JZ4780 SoC" + depends on MACH_JZ4780 && JZ4780_NEMC + help + Enables support for NAND Flash connected to the NEMC on JZ4780 SoC + based boards, using the BCH controller for hardware error correction. + config MTD_NAND_FSMC tristate "Support for NAND on ST Micros FSMC" depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300 diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 2c7f014..9e36233 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o obj-$(CONFIG_MTD_NAND_VF610_NFC) += vf610_nfc.o obj-$(CONFIG_MTD_NAND_RICOH) += r852.o obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o +obj-$(CONFIG_MTD_NAND_JZ4780) += jz4780_nand.o jz4780_bch.o obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ diff --git a/drivers/mtd/nand/jz4780_bch.c b/drivers/mtd/nand/jz4780_bch.c new file mode 100644 index 0000000..5954fbf --- /dev/null +++ b/drivers/mtd/nand/jz4780_bch.c @@ -0,0 +1,381 @@ +/* + * JZ4780 BCH controller + * + * Copyright (c) 2015 Imagination Technologies + * Author: Alex Smith + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jz4780_bch.h" + +#define BCH_BHCR 0x0 +#define BCH_BHCCR 0x8 +#define BCH_BHCNT 0xc +#define BCH_BHDR 0x10 +#define BCH_BHPAR0 0x14 +#define BCH_BHERR0 0x84 +#define BCH_BHINT 0x184 +#define BCH_BHINTES 0x188 +#define BCH_BHINTEC 0x18c +#define BCH_BHINTE 0x190 + +#define BCH_BHCR_BSEL_SHIFT 4 +#define BCH_BHCR_BSEL_MASK (0x7f << BCH_BHCR_BSEL_SHIFT) +#define BCH_BHCR_ENCE BIT(2) +#define BCH_BHCR_INIT BIT(1) +#define BCH_BHCR_BCHE BIT(0) + +#define BCH_BHCNT_PARITYSIZE_SHIFT 16 +#define BCH_BHCNT_PARITYSIZE_MASK (0x7f << BCH_BHCNT_PARITYSIZE_SHIFT) +#define BCH_BHCNT_BLOCKSIZE_SHIFT 0 +#define BCH_BHCNT_BLOCKSIZE_MASK (0x7ff << BCH_BHCNT_BLOCKSIZE_SHIFT) + +#define BCH_BHERR_MASK_SHIFT 16 +#define BCH_BHERR_MASK_MASK (0xffff << BCH_BHERR_MASK_SHIFT) +#define BCH_BHERR_INDEX_SHIFT 0 +#define BCH_BHERR_INDEX_MASK (0x7ff << BCH_BHERR_INDEX_SHIFT) + +#define BCH_BHINT_ERRC_SHIFT 24 +#define BCH_BHINT_ERRC_MASK (0x7f << BCH_BHINT_ERRC_SHIFT) +#define BCH_BHINT_TERRC_SHIFT 16 +#define BCH_BHINT_TERRC_MASK (0x7f << BCH_BHINT_TERRC_SHIFT) +#define BCH_BHINT_DECF BIT(3) +#define BCH_BHINT_ENCF BIT(2) +#define BCH_BHINT_UNCOR BIT(1) +#define BCH_BHINT_ERR BIT(0) + +#define BCH_CLK_RATE (200 * 1000 * 1000) + +/* Timeout for BCH calculation/correction. */ +#define BCH_TIMEOUT_US 100000 + +struct jz4780_bch { + struct device *dev; + void __iomem *base; + struct clk *clk; + struct mutex lock; +}; + +static void jz4780_bch_init(struct jz4780_bch *bch, + struct jz4780_bch_params *params, bool encode) +{ + u32 reg; + + /* Clear interrupt status. */ + writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT); + + /* Set up BCH count register. */ + reg = params->size << BCH_BHCNT_BLOCKSIZE_SHIFT; + reg |= params->bytes << BCH_BHCNT_PARITYSIZE_SHIFT; + writel(reg, bch->base + BCH_BHCNT); + + /* Initialise and enable BCH. */ + reg = BCH_BHCR_BCHE | BCH_BHCR_INIT; + reg |= params->strength << BCH_BHCR_BSEL_SHIFT; + if (encode) + reg |= BCH_BHCR_ENCE; + writel(reg, bch->base + BCH_BHCR); +} + +static void jz4780_bch_disable(struct jz4780_bch *bch) +{ + writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT); + writel(BCH_BHCR_BCHE, bch->base + BCH_BHCCR); +} + +static void jz4780_bch_write_data(struct jz4780_bch *bch, const void *buf, + size_t size) +{ + size_t size32 = size / sizeof(u32); + size_t size8 = size % sizeof(u32); + const u32 *src32; + const u8 *src8; + + src32 = (const u32 *)buf; + while (size32--) + writel(*src32++, bch->base + BCH_BHDR); + + src8 = (const u8 *)src32; + while (size8--) + writeb(*src8++, bch->base + BCH_BHDR); +} + +static void jz4780_bch_read_parity(struct jz4780_bch *bch, void *buf, + size_t size) +{ + size_t size32 = size / sizeof(u32); + size_t size8 = size % sizeof(u32); + u32 *dest32; + u8 *dest8; + u32 val, offset = 0; + + dest32 = (u32 *)buf; + while (size32--) { + *dest32++ = readl(bch->base + BCH_BHPAR0 + offset); + offset += sizeof(u32); + } + + dest8 = (u8 *)dest32; + val = readl(bch->base + BCH_BHPAR0 + offset); + switch (size8) { + case 3: + dest8[2] = (val >> 16) & 0xff; + case 2: + dest8[1] = (val >> 8) & 0xff; + case 1: + dest8[0] = val & 0xff; + break; + } +} + +static bool jz4780_bch_wait_complete(struct jz4780_bch *bch, unsigned int irq, + u32 *status) +{ + u32 reg; + int ret; + + /* + * While we could use interrupts here and sleep until the operation + * completes, the controller works fairly quickly (usually a few + * microseconds) and so the overhead of sleeping until we get an + * interrupt quite noticeably decreases performance. + */ + ret = readl_poll_timeout(bch->base + BCH_BHINT, reg, + (reg & irq) == irq, 0, BCH_TIMEOUT_US); + if (ret) + return false; + + if (status) + *status = reg; + + writel(reg, bch->base + BCH_BHINT); + return true; +} + +/** + * jz4780_bch_calculate() - calculate ECC for a data buffer + * @bch: BCH device. + * @params: BCH parameters. + * @buf: input buffer with raw data. + * @ecc_code: output buffer with ECC. + * + * Return: 0 on success, -ETIMEDOUT if timed out while waiting for BCH + * controller. + */ +int jz4780_bch_calculate(struct jz4780_bch *bch, struct jz4780_bch_params *params, + const u8 *buf, u8 *ecc_code) +{ + int ret = 0; + + mutex_lock(&bch->lock); + jz4780_bch_init(bch, params, true); + jz4780_bch_write_data(bch, buf, params->size); + + if (jz4780_bch_wait_complete(bch, BCH_BHINT_ENCF, NULL)) { + jz4780_bch_read_parity(bch, ecc_code, params->bytes); + } else { + dev_err(bch->dev, "timed out while calculating ECC\n"); + ret = -ETIMEDOUT; + } + + jz4780_bch_disable(bch); + mutex_unlock(&bch->lock); + return ret; +} +EXPORT_SYMBOL(jz4780_bch_calculate); + +/** + * jz4780_bch_correct() - detect and correct bit errors + * @bch: BCH device. + * @params: BCH parameters. + * @buf: raw data read from the chip. + * @ecc_code: ECC read from the chip. + * + * Given the raw data and the ECC read from the NAND device, detects and + * corrects errors in the data. + * + * Return: the number of bit errors corrected, or -1 if there are too many + * errors to correct or we timed out waiting for the controller. + */ +int jz4780_bch_correct(struct jz4780_bch *bch, struct jz4780_bch_params *params, + u8 *buf, u8 *ecc_code) +{ + u32 reg, mask, index; + int i, ret, count; + + mutex_lock(&bch->lock); + + jz4780_bch_init(bch, params, false); + jz4780_bch_write_data(bch, buf, params->size); + jz4780_bch_write_data(bch, ecc_code, params->bytes); + + if (!jz4780_bch_wait_complete(bch, BCH_BHINT_DECF, ®)) { + dev_err(bch->dev, "timed out while correcting data\n"); + ret = -1; + goto out; + } + + if (reg & BCH_BHINT_UNCOR) { + dev_warn(bch->dev, "uncorrectable ECC error\n"); + ret = -1; + goto out; + } + + /* Correct any detected errors. */ + if (reg & BCH_BHINT_ERR) { + count = (reg & BCH_BHINT_ERRC_MASK) >> BCH_BHINT_ERRC_SHIFT; + ret = (reg & BCH_BHINT_TERRC_MASK) >> BCH_BHINT_TERRC_SHIFT; + + for (i = 0; i < count; i++) { + reg = readl(bch->base + BCH_BHERR0 + (i * 4)); + mask = (reg & BCH_BHERR_MASK_MASK) >> + BCH_BHERR_MASK_SHIFT; + index = (reg & BCH_BHERR_INDEX_MASK) >> + BCH_BHERR_INDEX_SHIFT; + buf[(index * 2) + 0] ^= mask; + buf[(index * 2) + 1] ^= mask >> 8; + } + } else { + ret = 0; + } + +out: + jz4780_bch_disable(bch); + mutex_unlock(&bch->lock); + return ret; +} +EXPORT_SYMBOL(jz4780_bch_correct); + +/** + * jz4780_bch_get() - get the BCH controller device + * @np: BCH device tree node. + * + * Gets the BCH controller device from the specified device tree node. The + * device must be released with jz4780_bch_release() when it is no longer being + * used. + * + * Return: a pointer to jz4780_bch, errors are encoded into the pointer. + * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. + */ +static struct jz4780_bch *jz4780_bch_get(struct device_node *np) +{ + struct platform_device *pdev; + struct jz4780_bch *bch; + + pdev = of_find_device_by_node(np); + if (!pdev || !platform_get_drvdata(pdev)) + return ERR_PTR(-EPROBE_DEFER); + + get_device(&pdev->dev); + + bch = platform_get_drvdata(pdev); + clk_prepare_enable(bch->clk); + + bch->dev = &pdev->dev; + return bch; +} + +/** + * of_jz4780_bch_get() - get the BCH controller from a DT node + * @of_node: the node that contains a bch-controller property. + * + * Get the bch-controller property from the given device tree + * node and pass it to jz4780_bch_get to do the work. + * + * Return: a pointer to jz4780_bch, errors are encoded into the pointer. + * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. + */ +struct jz4780_bch *of_jz4780_bch_get(struct device_node *of_node) +{ + struct jz4780_bch *bch = NULL; + struct device_node *np; + + np = of_parse_phandle(of_node, "ingenic,bch-controller", 0); + + if (np) { + bch = jz4780_bch_get(np); + of_node_put(np); + } + return bch; +} +EXPORT_SYMBOL(of_jz4780_bch_get); + +/** + * jz4780_bch_release() - release the BCH controller device + * @bch: BCH device. + */ +void jz4780_bch_release(struct jz4780_bch *bch) +{ + clk_disable_unprepare(bch->clk); + put_device(bch->dev); +} +EXPORT_SYMBOL(jz4780_bch_release); + +static int jz4780_bch_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct jz4780_bch *bch; + struct resource *res; + + bch = devm_kzalloc(dev, sizeof(*bch), GFP_KERNEL); + if (!bch) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + bch->base = devm_ioremap_resource(dev, res); + if (IS_ERR(bch->base)) + return PTR_ERR(bch->base); + + jz4780_bch_disable(bch); + + bch->clk = devm_clk_get(dev, NULL); + if (IS_ERR(bch->clk)) { + dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(bch->clk)); + return PTR_ERR(bch->clk); + } + + clk_set_rate(bch->clk, BCH_CLK_RATE); + + mutex_init(&bch->lock); + + bch->dev = dev; + platform_set_drvdata(pdev, bch); + + return 0; +} + +static const struct of_device_id jz4780_bch_dt_match[] = { + { .compatible = "ingenic,jz4780-bch" }, + {}, +}; +MODULE_DEVICE_TABLE(of, jz4780_bch_dt_match); + +static struct platform_driver jz4780_bch_driver = { + .probe = jz4780_bch_probe, + .driver = { + .name = "jz4780-bch", + .of_match_table = of_match_ptr(jz4780_bch_dt_match), + }, +}; +module_platform_driver(jz4780_bch_driver); + +MODULE_AUTHOR("Alex Smith "); +MODULE_AUTHOR("Harvey Hunt "); +MODULE_DESCRIPTION("Ingenic JZ4780 BCH error correction driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mtd/nand/jz4780_bch.h b/drivers/mtd/nand/jz4780_bch.h new file mode 100644 index 0000000..bf471808 --- /dev/null +++ b/drivers/mtd/nand/jz4780_bch.h @@ -0,0 +1,43 @@ +/* + * JZ4780 BCH controller + * + * Copyright (c) 2015 Imagination Technologies + * Author: Alex Smith + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef __DRIVERS_MTD_NAND_JZ4780_BCH_H__ +#define __DRIVERS_MTD_NAND_JZ4780_BCH_H__ + +#include + +struct device; +struct device_node; +struct jz4780_bch; + +/** + * struct jz4780_bch_params - BCH parameters + * @size: data bytes per ECC step. + * @bytes: ECC bytes per step. + * @strength: number of correctable bits per ECC step. + */ +struct jz4780_bch_params { + int size; + int bytes; + int strength; +}; + +int jz4780_bch_calculate(struct jz4780_bch *bch, + struct jz4780_bch_params *params, + const u8 *buf, u8 *ecc_code); +int jz4780_bch_correct(struct jz4780_bch *bch, + struct jz4780_bch_params *params, u8 *buf, + u8 *ecc_code); + +void jz4780_bch_release(struct jz4780_bch *bch); +struct jz4780_bch *of_jz4780_bch_get(struct device_node *np); + +#endif /* __DRIVERS_MTD_NAND_JZ4780_BCH_H__ */ diff --git a/drivers/mtd/nand/jz4780_nand.c b/drivers/mtd/nand/jz4780_nand.c new file mode 100644 index 0000000..17eb9f2 --- /dev/null +++ b/drivers/mtd/nand/jz4780_nand.c @@ -0,0 +1,425 @@ +/* + * JZ4780 NAND driver + * + * Copyright (c) 2015 Imagination Technologies + * Author: Alex Smith + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "jz4780_bch.h" + +#define DRV_NAME "jz4780-nand" + +#define OFFSET_DATA 0x00000000 +#define OFFSET_CMD 0x00400000 +#define OFFSET_ADDR 0x00800000 + +/* Command delay when there is no R/B pin. */ +#define RB_DELAY_US 100 + +struct jz4780_nand_cs { + unsigned int bank; + void __iomem *base; +}; + +struct jz4780_nand_controller { + struct device *dev; + struct jz4780_bch *bch; + struct nand_hw_control controller; + unsigned int num_banks; + struct list_head chips; + int selected; + struct jz4780_nand_cs cs[]; +}; + +struct jz4780_nand_chip { + struct nand_chip chip; + struct list_head chip_list; + + struct nand_ecclayout ecclayout; + + struct gpio_desc *busy_gpio; + struct gpio_desc *wp_gpio; + unsigned int reading: 1; +}; + +static inline struct jz4780_nand_chip *to_jz4780_nand_chip(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct jz4780_nand_chip, chip); +} + +static inline struct jz4780_nand_controller *to_jz4780_nand_controller(struct nand_hw_control *ctrl) +{ + return container_of(ctrl, struct jz4780_nand_controller, controller); +} + +static void jz4780_nand_select_chip(struct mtd_info *mtd, int chipnr) +{ + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); + struct jz4780_nand_cs *cs; + + /* Ensure the currently selected chip is deasserted. */ + if (chipnr == -1 && nfc->selected >= 0) { + cs = &nfc->cs[nfc->selected]; + jz4780_nemc_assert(nfc->dev, cs->bank, false); + } + + nfc->selected = chipnr; +} + +static void jz4780_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); + struct jz4780_nand_cs *cs; + + if (WARN_ON(nfc->selected < 0)) + return; + + cs = &nfc->cs[nfc->selected]; + + jz4780_nemc_assert(nfc->dev, cs->bank, ctrl & NAND_NCE); + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_ALE) + writeb(cmd, cs->base + OFFSET_ADDR); + else if (ctrl & NAND_CLE) + writeb(cmd, cs->base + OFFSET_CMD); +} + +static int jz4780_nand_dev_ready(struct mtd_info *mtd) +{ + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + + return !gpiod_get_value_cansleep(nand->busy_gpio); +} + +static void jz4780_nand_ecc_hwctl(struct mtd_info *mtd, int mode) +{ + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + + nand->reading = (mode == NAND_ECC_READ); +} + +static int jz4780_nand_ecc_calculate(struct mtd_info *mtd, const u8 *dat, + u8 *ecc_code) +{ + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); + struct jz4780_bch_params params; + + /* + * Don't need to generate the ECC when reading, BCH does it for us as + * part of decoding/correction. + */ + if (nand->reading) + return 0; + + params.size = nand->chip.ecc.size; + params.bytes = nand->chip.ecc.bytes; + params.strength = nand->chip.ecc.strength; + + return jz4780_bch_calculate(nfc->bch, ¶ms, dat, ecc_code); +} + +static int jz4780_nand_ecc_correct(struct mtd_info *mtd, u8 *dat, + u8 *read_ecc, u8 *calc_ecc) +{ + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); + struct jz4780_bch_params params; + + params.size = nand->chip.ecc.size; + params.bytes = nand->chip.ecc.bytes; + params.strength = nand->chip.ecc.strength; + + return jz4780_bch_correct(nfc->bch, ¶ms, dat, read_ecc); +} + +static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *dev) +{ + struct nand_chip *chip = &nand->chip; + struct mtd_info *mtd = nand_to_mtd(chip); + struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller); + struct nand_ecclayout *layout = &nand->ecclayout; + u32 start, i; + + chip->ecc.bytes = fls((1 + 8) * chip->ecc.size) * + (chip->ecc.strength / 8); + + if (nfc->bch && chip->ecc.mode == NAND_ECC_HW) { + chip->ecc.hwctl = jz4780_nand_ecc_hwctl; + chip->ecc.calculate = jz4780_nand_ecc_calculate; + chip->ecc.correct = jz4780_nand_ecc_correct; + } else if (!nfc->bch && chip->ecc.mode == NAND_ECC_HW) { + dev_err(dev, "HW BCH selected, but BCH controller not found\n"); + return -ENODEV; + } + + if (chip->ecc.mode == NAND_ECC_HW_SYNDROME) { + dev_err(dev, "ECC HW syndrome not supported\n"); + return -EINVAL; + } + + if (chip->ecc.mode != NAND_ECC_NONE) + dev_info(dev, "using %s (strength %d, size %d, bytes %d)\n", + (nfc->bch) ? "hardware BCH" : "software ECC", + chip->ecc.strength, chip->ecc.size, chip->ecc.bytes); + else + dev_info(dev, "not using ECC\n"); + + /* The NAND core will generate the ECC layout. */ + if (chip->ecc.mode == NAND_ECC_SOFT || chip->ecc.mode == NAND_ECC_SOFT_BCH) + return 0; + + /* Generate ECC layout. ECC codes are right aligned in the OOB area. */ + layout->eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes; + + if (layout->eccbytes > mtd->oobsize - 2) { + dev_err(dev, + "invalid ECC config: required %d ECC bytes, but only %d are available", + layout->eccbytes, mtd->oobsize - 2); + return -EINVAL; + } + + start = mtd->oobsize - layout->eccbytes; + for (i = 0; i < layout->eccbytes; i++) + layout->eccpos[i] = start + i; + + layout->oobfree[0].offset = 2; + layout->oobfree[0].length = mtd->oobsize - layout->eccbytes - 2; + + chip->ecc.layout = layout; + return 0; +} + +static int jz4780_nand_init_chip(struct platform_device *pdev, + struct jz4780_nand_controller *nfc, + struct device_node *np, + unsigned int chipnr) +{ + struct device *dev = &pdev->dev; + struct jz4780_nand_chip *nand; + struct jz4780_nand_cs *cs; + struct resource *res; + struct nand_chip *chip; + struct mtd_info *mtd; + const __be32 *reg; + int ret = 0; + + cs = &nfc->cs[chipnr]; + + reg = of_get_property(np, "reg", NULL); + if (!reg) + return -EINVAL; + + cs->bank = be32_to_cpu(*reg); + + jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND); + + res = platform_get_resource(pdev, IORESOURCE_MEM, chipnr); + cs->base = devm_ioremap_resource(dev, res); + if (IS_ERR(cs->base)) + return PTR_ERR(cs->base); + + nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL); + if (!nand) + return -ENOMEM; + + nand->busy_gpio = devm_gpiod_get_optional(dev, "rb", GPIOD_IN); + + if (IS_ERR(nand->busy_gpio)) { + ret = PTR_ERR(nand->busy_gpio); + dev_err(dev, "failed to request busy GPIO: %d\n", ret); + return ret; + } else if (nand->busy_gpio) { + nand->chip.dev_ready = jz4780_nand_dev_ready; + } + + nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW); + + if (IS_ERR(nand->wp_gpio)) { + ret = PTR_ERR(nand->wp_gpio); + dev_err(dev, "failed to request WP GPIO: %d\n", ret); + return ret; + } + + chip = &nand->chip; + mtd = nand_to_mtd(chip); + mtd->priv = chip; + mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), + cs->bank); + if (!mtd->name) + return -ENOMEM; + mtd->dev.parent = dev; + + chip->IO_ADDR_R = cs->base + OFFSET_DATA; + chip->IO_ADDR_W = cs->base + OFFSET_DATA; + chip->chip_delay = RB_DELAY_US; + chip->options = NAND_NO_SUBPAGE_WRITE; + chip->select_chip = jz4780_nand_select_chip; + chip->cmd_ctrl = jz4780_nand_cmd_ctrl; + chip->ecc.mode = NAND_ECC_HW; + chip->controller = &nfc->controller; + nand_set_flash_node(chip, np); + + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) + return ret; + + ret = jz4780_nand_init_ecc(nand, dev); + if (ret) + return ret; + + ret = nand_scan_tail(mtd); + if (ret) + return ret; + + ret = mtd_device_register(mtd, NULL, 0); + if (ret) { + nand_release(mtd); + return ret; + } + + list_add_tail(&nand->chip_list, &nfc->chips); + + return 0; +} + +static void jz4780_nand_cleanup_chips(struct jz4780_nand_controller *nfc) +{ + struct jz4780_nand_chip *chip; + + while (!list_empty(&nfc->chips)) { + chip = list_first_entry(&nfc->chips, struct jz4780_nand_chip, chip_list); + nand_release(nand_to_mtd(&chip->chip)); + list_del(&chip->chip_list); + } +} + +static int jz4780_nand_init_chips(struct jz4780_nand_controller *nfc, + struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np; + int i = 0; + int ret; + int num_chips = of_get_child_count(dev->of_node); + + if (num_chips > nfc->num_banks) { + dev_err(dev, "found %d chips but only %d banks\n", num_chips, nfc->num_banks); + return -EINVAL; + } + + for_each_child_of_node(dev->of_node, np) { + ret = jz4780_nand_init_chip(pdev, nfc, np, i); + if (ret) { + jz4780_nand_cleanup_chips(nfc); + return ret; + } + + i++; + } + + return 0; +} + +static int jz4780_nand_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + unsigned int num_banks; + struct jz4780_nand_controller *nfc; + int ret; + + num_banks = jz4780_nemc_num_banks(dev); + if (num_banks == 0) { + dev_err(dev, "no banks found\n"); + return -ENODEV; + } + + nfc = devm_kzalloc(dev, sizeof(*nfc) + (sizeof(nfc->cs[0]) * num_banks), GFP_KERNEL); + if (!nfc) + return -ENOMEM; + + /* + * Check for BCH HW before we call nand_scan_ident, to prevent us from + * having to call it again if the BCH driver returns -EPROBE_DEFER. + */ + nfc->bch = of_jz4780_bch_get(dev->of_node); + if (IS_ERR(nfc->bch)) + return PTR_ERR(nfc->bch); + + nfc->dev = dev; + nfc->num_banks = num_banks; + + spin_lock_init(&nfc->controller.lock); + INIT_LIST_HEAD(&nfc->chips); + init_waitqueue_head(&nfc->controller.wq); + + ret = jz4780_nand_init_chips(nfc, pdev); + if (ret) { + if (nfc->bch) + jz4780_bch_release(nfc->bch); + return ret; + } + + platform_set_drvdata(pdev, nfc); + return 0; +} + +static int jz4780_nand_remove(struct platform_device *pdev) +{ + struct jz4780_nand_controller *nfc = platform_get_drvdata(pdev); + + if (nfc->bch) + jz4780_bch_release(nfc->bch); + + jz4780_nand_cleanup_chips(nfc); + + return 0; +} + +static const struct of_device_id jz4780_nand_dt_match[] = { + { .compatible = "ingenic,jz4780-nand" }, + {}, +}; +MODULE_DEVICE_TABLE(of, jz4780_nand_dt_match); + +static struct platform_driver jz4780_nand_driver = { + .probe = jz4780_nand_probe, + .remove = jz4780_nand_remove, + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(jz4780_nand_dt_match), + }, +}; +module_platform_driver(jz4780_nand_driver); + +MODULE_AUTHOR("Alex Smith "); +MODULE_AUTHOR("Harvey Hunt "); +MODULE_DESCRIPTION("Ingenic JZ4780 NAND driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.1 From d699ed250c07384840263bbbf69cf7b90b45470c Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 10 Dec 2015 09:00:41 +0100 Subject: mtd: nand: make use of nand_set/get_controller_data() helpers New helpers have been added to avoid directly accessing chip->field. Use them where appropriate. Signed-off-by: Boris Brezillon [Brian: fixed a few rebase conflicts] Signed-off-by: Brian Norris --- drivers/mtd/nand/ams-delta.c | 6 +-- drivers/mtd/nand/atmel_nand.c | 55 +++++++++++----------- drivers/mtd/nand/bcm47xxnflash/main.c | 2 +- drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c | 16 +++---- drivers/mtd/nand/bf5xx_nand.c | 2 +- drivers/mtd/nand/brcmnand/brcmnand.c | 30 ++++++------ drivers/mtd/nand/cafe_nand.c | 24 +++++----- drivers/mtd/nand/diskonchip.c | 70 ++++++++++++++-------------- drivers/mtd/nand/docg4.c | 40 ++++++++-------- drivers/mtd/nand/fsl_elbc_nand.c | 22 ++++----- drivers/mtd/nand/fsl_ifc_nand.c | 26 +++++------ drivers/mtd/nand/fsmc_nand.c | 2 +- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 28 +++++------ drivers/mtd/nand/hisi504_nand.c | 20 ++++---- drivers/mtd/nand/lpc32xx_mlc.c | 19 ++++---- drivers/mtd/nand/lpc32xx_slc.c | 20 ++++---- drivers/mtd/nand/mpc5121_nfc.c | 24 +++++----- drivers/mtd/nand/mxc_nand.c | 36 +++++++------- drivers/mtd/nand/nandsim.c | 4 +- drivers/mtd/nand/ndfc.c | 16 +++---- drivers/mtd/nand/orion_nand.c | 4 +- drivers/mtd/nand/pxa3xx_nand.c | 22 ++++----- drivers/mtd/nand/r852.c | 6 +-- drivers/mtd/nand/s3c2410.c | 4 +- drivers/mtd/nand/socrates_nand.c | 11 +++-- drivers/mtd/nand/txx9ndfmc.c | 8 ++-- 26 files changed, 260 insertions(+), 257 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 1a18938..68b58c8 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -65,7 +65,7 @@ static struct mtd_partition partition_info[] = { static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) { struct nand_chip *this = mtd_to_nand(mtd); - void __iomem *io_base = this->priv; + void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); writew(0, io_base + OMAP_MPUIO_IO_CNTL); writew(byte, this->IO_ADDR_W); @@ -78,7 +78,7 @@ static u_char ams_delta_read_byte(struct mtd_info *mtd) { u_char res; struct nand_chip *this = mtd_to_nand(mtd); - void __iomem *io_base = this->priv; + void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0); ndelay(40); @@ -206,7 +206,7 @@ static int ams_delta_init(struct platform_device *pdev) goto out_free; } - this->priv = io_base; + nand_set_controller_data(this, (void *)io_base); /* Set address of NAND IO lines */ this->IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH; diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index b216bf5..bddcf83 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -182,7 +182,7 @@ static void atmel_nand_disable(struct atmel_nand_host *host) static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); if (ctrl & NAND_CTRL_CHANGE) { if (ctrl & NAND_NCE) @@ -205,7 +205,7 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl static int atmel_nand_device_ready(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); return gpio_get_value(host->board.rdy_pin) ^ !!host->board.rdy_pin_active_low; @@ -215,7 +215,7 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); int res = 0; if (gpio_is_valid(host->board.rdy_pin)) { @@ -267,7 +267,7 @@ static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd) static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { memcpy(buf, host->nfc->data_in_sram, len); @@ -280,7 +280,7 @@ static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { memcpy(buf, host->nfc->data_in_sram, len); @@ -354,7 +354,7 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, struct dma_async_tx_descriptor *tx = NULL; dma_cookie_t cookie; struct nand_chip *chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); void *p = buf; int err = -EIO; enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; @@ -427,7 +427,7 @@ err_buf: static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ @@ -443,7 +443,7 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ @@ -535,7 +535,7 @@ static int pmecc_data_alloc(struct atmel_nand_host *host) static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); int i; uint32_t value; @@ -552,7 +552,7 @@ static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector) static void pmecc_substitute(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); int16_t __iomem *alpha_to = host->pmecc_alpha_to; int16_t __iomem *index_of = host->pmecc_index_of; int16_t *partial_syn = host->pmecc_partial_syn; @@ -594,7 +594,7 @@ static void pmecc_substitute(struct mtd_info *mtd) static void pmecc_get_sigma(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); int16_t *lmu = host->pmecc_lmu; int16_t *si = host->pmecc_si; @@ -752,7 +752,7 @@ static void pmecc_get_sigma(struct mtd_info *mtd) static int pmecc_err_location(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); unsigned long end_time; const int cap = host->pmecc_corr_cap; const int num = 2 * cap + 1; @@ -804,7 +804,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, int sector_num, int extra_bytes, int err_nbr) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); int i = 0; int byte_pos, bit_pos, sector_size, pos; uint32_t tmp; @@ -850,7 +850,7 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, u8 *ecc) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); int i, err_nbr; uint8_t *buf_pos; int max_bitflips = 0; @@ -920,7 +920,7 @@ static void pmecc_enable(struct atmel_nand_host *host, int ecc_op) static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); int eccsize = chip->ecc.size * chip->ecc.steps; uint8_t *oob = chip->oob_poi; uint32_t *eccpos = chip->ecc.layout->eccpos; @@ -958,7 +958,7 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); uint32_t *eccpos = chip->ecc.layout->eccpos; int i, j; unsigned long end_time; @@ -994,7 +994,7 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, static void atmel_pmecc_core_init(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); uint32_t val = 0; struct nand_ecclayout *ecc_layout; @@ -1310,7 +1310,7 @@ static int atmel_nand_calculate(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); unsigned int ecc_value; /* get the first 2 ECC bytes */ @@ -1356,7 +1356,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, * Workaround: Reset the parity registers before reading the * actual data. */ - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); if (host->board.need_reset_workaround) ecc_writel(host->ecc, CR, ATMEL_ECC_RST); @@ -1414,7 +1414,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *isnull) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); unsigned int ecc_status; unsigned int ecc_word, ecc_bit; @@ -1480,7 +1480,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); if (host->board.need_reset_workaround) ecc_writel(host->ecc, CR, ATMEL_ECC_RST); @@ -1773,7 +1773,7 @@ static int nfc_device_ready(struct mtd_info *mtd) { u32 status, mask; struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); status = nfc_read_status(host); mask = nfc_readl(host->nfc->hsmc_regs, IMR); @@ -1789,7 +1789,7 @@ static int nfc_device_ready(struct mtd_info *mtd) static void nfc_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = nand_chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(nand_chip); if (chip == -1) nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_DISABLE); @@ -1841,7 +1841,7 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); unsigned long timeout; unsigned int nfc_addr_cmd = 0; @@ -1967,7 +1967,7 @@ static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip, { int cfg, len; int status = 0; - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); void *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host); /* Subpage write is not supported */ @@ -2028,7 +2028,7 @@ static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip, static int nfc_sram_init(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct atmel_nand_host *host = chip->priv; + struct atmel_nand_host *host = nand_get_controller_data(chip); int res = 0; /* Initialize the NFC CFG register */ @@ -2127,7 +2127,8 @@ static int atmel_nand_probe(struct platform_device *pdev) sizeof(struct atmel_nand_data)); } - nand_chip->priv = host; /* link the private data structures */ + /* link the private data structures */ + nand_set_controller_data(nand_chip, host); mtd->dev.parent = &pdev->dev; /* Set address of NAND IO lines */ diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c index b44f821..fb31429 100644 --- a/drivers/mtd/nand/bcm47xxnflash/main.c +++ b/drivers/mtd/nand/bcm47xxnflash/main.c @@ -34,7 +34,7 @@ static int bcm47xxnflash_probe(struct platform_device *pdev) if (!b47n) return -ENOMEM; - b47n->nand_chip.priv = b47n; + nand_set_controller_data(&b47n->nand_chip, b47n); mtd = nand_to_mtd(&b47n->nand_chip); mtd->dev.parent = &pdev->dev; b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash); diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c index 6524780..f1da4ea 100644 --- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c @@ -90,7 +90,7 @@ static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf, int len) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); u32 ctlcode; u32 *dest = (u32 *)buf; @@ -140,7 +140,7 @@ static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd, const uint8_t *buf, int len) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); struct bcma_drv_cc *cc = b47n->cc; u32 ctlcode; @@ -174,7 +174,7 @@ static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); u32 code = 0; if (cmd == NAND_CMD_NONE) @@ -200,7 +200,7 @@ static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd, static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY); } @@ -217,7 +217,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, int page_addr) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); struct bcma_drv_cc *cc = b47n->cc; u32 ctlcode; int i; @@ -313,7 +313,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); struct bcma_drv_cc *cc = b47n->cc; u32 tmp = 0; @@ -342,7 +342,7 @@ static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); switch (b47n->curr_command) { case NAND_CMD_READ0: @@ -358,7 +358,7 @@ static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); switch (b47n->curr_command) { case NAND_CMD_SEQIN: diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 89d9414..7f6b30e 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -781,7 +781,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev) chip->cmd_ctrl = bf5xx_nand_hwcontrol; chip->dev_ready = bf5xx_nand_devready; - chip->priv = mtd; + nand_set_controller_data(chip, mtd); chip->controller = &info->controller; chip->IO_ADDR_R = (void __iomem *) NFC_READ; diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index aea0881..844fc07 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -877,7 +877,7 @@ static struct nand_ecclayout *brcmstb_choose_ecc_layout( static void brcmnand_wp(struct mtd_info *mtd, int wp) { struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; if ((ctrl->features & BRCMNAND_HAS_WP) && wp_on == 1) { @@ -1043,7 +1043,7 @@ static void brcmnand_cmd_ctrl(struct mtd_info *mtd, int dat, static int brcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; unsigned long timeo = msecs_to_jiffies(100); @@ -1117,7 +1117,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; u64 addr = (u64)page_addr << chip->page_shift; int native_cmd = 0; @@ -1223,7 +1223,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, static uint8_t brcmnand_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; uint8_t ret = 0; int addr, offs; @@ -1290,7 +1290,7 @@ static void brcmnand_write_buf(struct mtd_info *mtd, const uint8_t *buf, { int i; struct nand_chip *chip = mtd_to_nand(mtd); - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); switch (host->last_cmd) { case NAND_CMD_SET_FEATURES: @@ -1400,7 +1400,7 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, u64 addr, unsigned int trans, u32 *buf, u8 *oob, u64 *err_addr) { - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; int i, j, ret = 0; @@ -1463,7 +1463,7 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, u64 addr, unsigned int trans, u32 *buf, u8 *oob) { - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; u64 err_addr = 0; int err; @@ -1513,7 +1513,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; return brcmnand_read(mtd, chip, host->last_addr, @@ -1523,7 +1523,7 @@ static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip, static int brcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; int ret; @@ -1545,7 +1545,7 @@ static int brcmnand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, static int brcmnand_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, int page) { - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); brcmnand_set_ecc_enabled(host, 0); brcmnand_read(mtd, chip, (u64)page << chip->page_shift, @@ -1558,7 +1558,7 @@ static int brcmnand_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, u64 addr, const u32 *buf, u8 *oob) { - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; unsigned int i, j, trans = mtd->writesize >> FC_SHIFT; int status, ret = 0; @@ -1629,7 +1629,7 @@ out: static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); void *oob = oob_required ? chip->oob_poi : NULL; brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); @@ -1640,7 +1640,7 @@ static int brcmnand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); void *oob = oob_required ? chip->oob_poi : NULL; brcmnand_set_ecc_enabled(host, 0); @@ -1659,7 +1659,7 @@ static int brcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, static int brcmnand_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, int page) { - struct brcmnand_host *host = chip->priv; + struct brcmnand_host *host = nand_get_controller_data(chip); int ret; brcmnand_set_ecc_enabled(host, 0); @@ -1923,7 +1923,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) chip = &host->chip; nand_set_flash_node(chip, dn); - chip->priv = host; + nand_set_controller_data(chip, host); mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d", host->cs); mtd->owner = THIS_MODULE; diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 00c15e2..aa1a616 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -102,7 +102,7 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; static int cafe_device_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000); uint32_t irqs = cafe_readl(cafe, NAND_IRQ); @@ -119,7 +119,7 @@ static int cafe_device_ready(struct mtd_info *mtd) static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); if (usedma) memcpy(cafe->dmabuf + cafe->datalen, buf, len); @@ -135,7 +135,7 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); if (usedma) memcpy(buf, cafe->dmabuf + cafe->datalen, len); @@ -150,7 +150,7 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static uint8_t cafe_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); uint8_t d; cafe_read_buf(mtd, &d, 1); @@ -163,7 +163,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); int adrbytes = 0; uint32_t ctl1; uint32_t doneint = 0x80000000; @@ -319,7 +319,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, static void cafe_select_chip(struct mtd_info *mtd, int chipnr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); @@ -335,7 +335,7 @@ static irqreturn_t cafe_nand_interrupt(int irq, void *id) { struct mtd_info *mtd = id; struct nand_chip *chip = mtd_to_nand(mtd); - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); uint32_t irqs = cafe_readl(cafe, NAND_IRQ); cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ); if (!irqs) @@ -384,7 +384,7 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); unsigned int max_bitflips = 0; cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", @@ -526,7 +526,7 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd, const uint8_t *buf, int oob_required, int page) { - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); chip->write_buf(mtd, buf, mtd->writesize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -611,7 +611,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, mtd = nand_to_mtd(&cafe->nand); mtd->dev.parent = &pdev->dev; - cafe->nand.priv = cafe; + nand_set_controller_data(&cafe->nand, cafe); cafe->pdev = pdev; cafe->mmio = pci_iomap(pdev, 0, 0); @@ -800,7 +800,7 @@ static void cafe_nand_remove(struct pci_dev *pdev) { struct mtd_info *mtd = pci_get_drvdata(pdev); struct nand_chip *chip = mtd_to_nand(mtd); - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); /* Disable NAND IRQ in global IRQ mask register */ cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); @@ -828,7 +828,7 @@ static int cafe_nand_resume(struct pci_dev *pdev) uint32_t ctrl; struct mtd_info *mtd = pci_get_drvdata(pdev); struct nand_chip *chip = mtd_to_nand(mtd); - struct cafe_priv *cafe = chip->priv; + struct cafe_priv *cafe = nand_get_controller_data(chip); /* Start off by resetting the NAND controller completely */ cafe_writel(cafe, 1, NAND_RESET); diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 4f4aa35..f170f3c 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -296,7 +296,7 @@ static inline int DoC_WaitReady(struct doc_priv *doc) static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; if (debug) @@ -308,7 +308,7 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) static u_char doc2000_read_byte(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; u_char ret; @@ -323,7 +323,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd) static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; if (debug) @@ -340,7 +340,7 @@ static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -355,7 +355,7 @@ static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -376,7 +376,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len) static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); uint16_t ret; doc200x_select_chip(mtd, nr); @@ -422,7 +422,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) static void __init doc2000_count_chips(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); uint16_t mfrid; int i; @@ -443,7 +443,7 @@ static void __init doc2000_count_chips(struct mtd_info *mtd) static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this) { - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); int status; @@ -458,7 +458,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this) static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; WriteDOC(datum, docptr, CDSNSlowIO); @@ -469,7 +469,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) static u_char doc2001_read_byte(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; //ReadDOC(docptr, CDSNSlowIO); @@ -483,7 +483,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -496,7 +496,7 @@ static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -513,7 +513,7 @@ static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) static u_char doc2001plus_read_byte(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; u_char ret; @@ -528,7 +528,7 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd) static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -546,7 +546,7 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int le static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -577,7 +577,7 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len) static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int floor = 0; @@ -604,7 +604,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) static void doc200x_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int floor = 0; @@ -635,7 +635,7 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; if (ctrl & NAND_CTRL_CHANGE) { @@ -658,7 +658,7 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; /* @@ -764,7 +764,7 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu static int doc200x_dev_ready(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; if (DoC_is_MillenniumPlus(doc)) { @@ -804,7 +804,7 @@ static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ @@ -823,7 +823,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ @@ -843,7 +843,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; int emptymatch = 1; @@ -904,7 +904,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, { int i, ret = 0; struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; uint8_t calc_ecc[6]; volatile u_char dummy; @@ -975,7 +975,7 @@ static struct nand_ecclayout doc200x_oobinfo = { static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); unsigned offs; int ret; size_t retlen; @@ -1018,7 +1018,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); int ret = 0; u_char *buf; struct NFTLMediaHeader *mh; @@ -1120,7 +1120,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); int ret = 0; u_char *buf; struct INFTLMediaHeader *mh; @@ -1240,7 +1240,7 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd) { int ret, numparts; struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); struct mtd_partition parts[2]; memset((char *)parts, 0, sizeof(parts)); @@ -1275,7 +1275,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) { int ret, numparts; struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); struct mtd_partition parts[5]; if (this->numchips > doc->chips_per_floor) { @@ -1328,7 +1328,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) static inline int __init doc2000_init(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); this->read_byte = doc2000_read_byte; this->write_buf = doc2000_writebuf; @@ -1344,7 +1344,7 @@ static inline int __init doc2000_init(struct mtd_info *mtd) static inline int __init doc2001_init(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); this->read_byte = doc2001_read_byte; this->write_buf = doc2001_writebuf; @@ -1374,7 +1374,7 @@ static inline int __init doc2001_init(struct mtd_info *mtd) static inline int __init doc2001plus_init(struct mtd_info *mtd) { struct nand_chip *this = mtd_to_nand(mtd); - struct doc_priv *doc = this->priv; + struct doc_priv *doc = nand_get_controller_data(this); this->read_byte = doc2001plus_read_byte; this->write_buf = doc2001plus_writebuf; @@ -1491,7 +1491,7 @@ static int __init doc_probe(unsigned long physadr) unsigned char oldval; unsigned char newval; nand = mtd_to_nand(mtd); - doc = nand->priv; + doc = nand_get_controller_data(nand); /* Use the alias resolution register to determine if this is in fact the same DOC aliased to a new address. If writes to one chip's alias resolution register change the value on @@ -1538,7 +1538,7 @@ static int __init doc_probe(unsigned long physadr) mtd->owner = THIS_MODULE; - nand->priv = doc; + nand_set_controller_data(nand, doc); nand->select_chip = doc200x_select_chip; nand->cmd_ctrl = doc200x_hwcontrol; nand->dev_ready = doc200x_dev_ready; @@ -1611,7 +1611,7 @@ static void release_nanddoc(void) for (mtd = doclist; mtd; mtd = nextmtd) { nand = mtd_to_nand(mtd); - doc = nand->priv; + doc = nand_get_controller_data(nand); nextmtd = doc->nextdoc; nand_release(mtd); diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index 95cd139..df4165b 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c @@ -297,7 +297,7 @@ static int poll_status(struct docg4_priv *doc) static int docg4_wait(struct mtd_info *mtd, struct nand_chip *nand) { - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); int status = NAND_STATUS_WP; /* inverse logic?? */ dev_dbg(doc->dev, "%s...\n", __func__); @@ -319,7 +319,7 @@ static void docg4_select_chip(struct mtd_info *mtd, int chip) * not yet supported, so the only valid non-negative value is 0. */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; dev_dbg(doc->dev, "%s: chip %d\n", __func__, chip); @@ -338,7 +338,7 @@ static void reset(struct mtd_info *mtd) /* full device reset */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; writew(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN, @@ -376,7 +376,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page) */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; int i, numerrs, errpos[4]; const uint8_t blank_read_hwecc[8] = { @@ -465,7 +465,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page) static uint8_t docg4_read_byte(struct mtd_info *mtd) { struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); dev_dbg(doc->dev, "%s\n", __func__); @@ -546,7 +546,7 @@ static int pageprog(struct mtd_info *mtd) */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; int retval = 0; @@ -583,7 +583,7 @@ static void sequence_reset(struct mtd_info *mtd) /* common starting sequence for all operations */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; writew(DOC_CTRL_UNKNOWN | DOC_CTRL_CE, docptr + DOC_FLASHCONTROL); @@ -600,7 +600,7 @@ static void read_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr) /* first step in reading a page */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; dev_dbg(doc->dev, @@ -627,7 +627,7 @@ static void write_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr) /* first step in writing a page */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; dev_dbg(doc->dev, @@ -692,7 +692,7 @@ static void docg4_command(struct mtd_info *mtd, unsigned command, int column, /* handle standard nand commands */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); uint32_t g4_addr = mtd_to_docg4_address(page_addr, column); dev_dbg(doc->dev, "%s %x, page_addr=%x, column=%x\n", @@ -756,7 +756,7 @@ static void docg4_command(struct mtd_info *mtd, unsigned command, int column, static int read_page(struct mtd_info *mtd, struct nand_chip *nand, uint8_t *buf, int page, bool use_ecc) { - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; uint16_t status, edc_err, *buf16; int bits_corrected = 0; @@ -836,7 +836,7 @@ static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand, static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, int page) { - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; uint16_t status; @@ -875,7 +875,7 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, static int docg4_erase_block(struct mtd_info *mtd, int page) { struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; uint16_t g4_page; @@ -923,7 +923,7 @@ static int docg4_erase_block(struct mtd_info *mtd, int page) static int write_page(struct mtd_info *mtd, struct nand_chip *nand, const uint8_t *buf, bool use_ecc) { - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; uint8_t ecc_buf[8]; @@ -1003,7 +1003,7 @@ static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand, */ /* note that bytes 7..14 are hw generated hamming/ecc and overwritten */ - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); doc->oob_page = page; memcpy(doc->oob_buf, nand->oob_poi, 16); return 0; @@ -1017,7 +1017,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0); uint8_t *buf; int i, block; @@ -1090,7 +1090,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) int ret, i; uint8_t *buf; struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); struct nand_bbt_descr *bbtd = nand->badblock_pattern; int page = (int)(ofs >> nand->page_shift); uint32_t g4_addr = mtd_to_docg4_address(page, 0); @@ -1203,7 +1203,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd) */ struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); mtd->size = DOCG4_CHIP_SIZE; mtd->name = "Msys_Diskonchip_G4"; @@ -1262,7 +1262,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd) static int __init read_id_reg(struct mtd_info *mtd) { struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand->priv; + struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; uint16_t id1, id2; @@ -1314,7 +1314,7 @@ static int __init probe_docg4(struct platform_device *pdev) mtd = nand_to_mtd(nand); doc = (struct docg4_priv *) (nand + 1); - nand->priv = doc; + nand_set_controller_data(nand, doc); mtd->dev.parent = &pdev->dev; doc->virtadr = virtadr; doc->dev = dev; diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index e96d5bc..059d5f7 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -144,7 +144,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_lbc_regs __iomem *lbc = ctrl->regs; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; @@ -195,7 +195,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) static int fsl_elbc_run_command(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; struct fsl_lbc_regs __iomem *lbc = ctrl->regs; @@ -267,7 +267,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) static void fsl_elbc_do_read(struct nand_chip *chip, int oob) { - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_lbc_regs __iomem *lbc = ctrl->regs; @@ -300,7 +300,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; struct fsl_lbc_regs __iomem *lbc = ctrl->regs; @@ -525,7 +525,7 @@ static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip) static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; unsigned int bufsize = mtd->writesize + mtd->oobsize; @@ -563,7 +563,7 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) static u8 fsl_elbc_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; /* If there are still bytes in the FCM, then use the next byte. */ @@ -580,7 +580,7 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd) static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; int avail; @@ -604,7 +604,7 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) */ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) { - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; if (elbc_fcm_ctrl->status != LTESR_CC) @@ -619,7 +619,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_lbc_regs __iomem *lbc = ctrl->regs; unsigned int al; @@ -696,7 +696,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; @@ -770,7 +770,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->bbt_options = NAND_BBT_USE_FLASH; chip->controller = &elbc_fcm_ctrl->controller; - chip->priv = priv; + nand_set_controller_data(chip, priv); chip->ecc.read_page = fsl_elbc_read_page; chip->ecc.write_page = fsl_elbc_write_page; diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 9d2b4ed..43f5a3a 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -230,7 +230,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_regs __iomem *ifc = ctrl->regs; int buf_num; @@ -253,7 +253,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) static int is_blank(struct mtd_info *mtd, unsigned int bufnum) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2); u32 __iomem *mainarea = (u32 __iomem *)addr; u8 __iomem *oob = addr + mtd->writesize; @@ -292,7 +292,7 @@ static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl, static void fsl_ifc_run_command(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; struct fsl_ifc_regs __iomem *ifc = ctrl->regs; @@ -369,7 +369,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip, int oob, struct mtd_info *mtd) { - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_regs __iomem *ifc = ctrl->regs; @@ -409,7 +409,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip, static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_regs __iomem *ifc = ctrl->regs; @@ -624,7 +624,7 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip) static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); unsigned int bufsize = mtd->writesize + mtd->oobsize; if (len <= 0) { @@ -650,7 +650,7 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); unsigned int offset; /* @@ -673,7 +673,7 @@ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd) static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); uint16_t data; /* @@ -696,7 +696,7 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); int avail; if (len < 0) { @@ -721,7 +721,7 @@ static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len) */ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) { - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_regs __iomem *ifc = ctrl->regs; u32 nand_fsr; @@ -750,7 +750,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; @@ -782,7 +782,7 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__, chip->numchips); @@ -914,7 +914,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) } chip->controller = &ifc_nand_ctrl->controller; - chip->priv = priv; + nand_set_controller_data(chip, priv); chip->ecc.read_page = fsl_ifc_read_page; chip->ecc.write_page = fsl_ifc_write_page; diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 9a7c1f5..1bdcd4f 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -1009,7 +1009,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) /* Link all private pointers */ mtd = nand_to_mtd(&host->nand); nand = &host->nand; - nand->priv = host; + nand_set_controller_data(nand, host); nand_set_flash_node(nand, np); mtd->dev.parent = &pdev->dev; diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index df61f49..235ddcb 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -857,7 +857,7 @@ error_alloc: static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) { struct nand_chip *chip = mtd_to_nand(mtd); - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); int ret; /* @@ -891,7 +891,7 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) static int gpmi_dev_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); return gpmi_is_ready(this, this->current_chip); } @@ -899,7 +899,7 @@ static int gpmi_dev_ready(struct mtd_info *mtd) static void gpmi_select_chip(struct mtd_info *mtd, int chipnr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); if ((this->current_chip < 0) && (chipnr >= 0)) gpmi_begin(this); @@ -912,7 +912,7 @@ static void gpmi_select_chip(struct mtd_info *mtd, int chipnr) static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); dev_dbg(this->dev, "len is %d\n", len); this->upper_buf = buf; @@ -924,7 +924,7 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); dev_dbg(this->dev, "len is %d\n", len); this->upper_buf = (uint8_t *)buf; @@ -936,7 +936,7 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) static uint8_t gpmi_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); uint8_t *buf = this->data_buffer_dma; gpmi_read_buf(mtd, buf, 1); @@ -994,7 +994,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this, static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; void *payload_virt; dma_addr_t payload_phys; @@ -1074,7 +1074,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offs, uint32_t len, uint8_t *buf, int page) { - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); void __iomem *bch_regs = this->resources.bch_regs; struct bch_geometry old_geo = this->bch_geometry; struct bch_geometry *geo = &this->bch_geometry; @@ -1162,7 +1162,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; const void *payload_virt; dma_addr_t payload_phys; @@ -1298,7 +1298,7 @@ exit_auxiliary: static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) { - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); dev_dbg(this->dev, "page number is %d\n", page); /* clear the OOB buffer */ @@ -1359,7 +1359,7 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; int eccsize = nfc_geo->ecc_chunk_size; int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len; @@ -1448,7 +1448,7 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd, const uint8_t *buf, int oob_required, int page) { - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; int eccsize = nfc_geo->ecc_chunk_size; int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len; @@ -1539,7 +1539,7 @@ static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) { struct nand_chip *chip = mtd_to_nand(mtd); - struct gpmi_nand_data *this = chip->priv; + struct gpmi_nand_data *this = nand_get_controller_data(chip); int ret = 0; uint8_t *block_mark; int column, page, status, chipnr; @@ -1897,7 +1897,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) mtd->dev.parent = this->dev; /* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */ - chip->priv = this; + nand_set_controller_data(chip, this); nand_set_flash_node(chip, this->pdev->dev.of_node); chip->select_chip = gpmi_select_chip; chip->cmd_ctrl = gpmi_cmd_ctrl; diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c index 2aee212..f8d37f3 100644 --- a/drivers/mtd/nand/hisi504_nand.c +++ b/drivers/mtd/nand/hisi504_nand.c @@ -357,7 +357,7 @@ static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect) static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect) { struct nand_chip *chip = mtd_to_nand(mtd); - struct hinfc_host *host = chip->priv; + struct hinfc_host *host = nand_get_controller_data(chip); if (chipselect < 0) return; @@ -368,7 +368,7 @@ static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect) static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct hinfc_host *host = chip->priv; + struct hinfc_host *host = nand_get_controller_data(chip); if (host->command == NAND_CMD_STATUS) return *(uint8_t *)(host->mmio); @@ -384,7 +384,7 @@ static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd) static u16 hisi_nfc_read_word(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct hinfc_host *host = chip->priv; + struct hinfc_host *host = nand_get_controller_data(chip); host->offset += 2; return *(u16 *)(host->buffer + host->offset - 2); @@ -394,7 +394,7 @@ static void hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct hinfc_host *host = chip->priv; + struct hinfc_host *host = nand_get_controller_data(chip); memcpy(host->buffer + host->offset, buf, len); host->offset += len; @@ -403,7 +403,7 @@ hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct hinfc_host *host = chip->priv; + struct hinfc_host *host = nand_get_controller_data(chip); memcpy(buf, host->buffer + host->offset, len); host->offset += len; @@ -412,7 +412,7 @@ static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void set_addr(struct mtd_info *mtd, int column, int page_addr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct hinfc_host *host = chip->priv; + struct hinfc_host *host = nand_get_controller_data(chip); unsigned int command = host->command; host->addr_cycle = 0; @@ -448,7 +448,7 @@ static void hisi_nfc_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct hinfc_host *host = chip->priv; + struct hinfc_host *host = nand_get_controller_data(chip); int is_cache_invalid = 1; unsigned int flag = 0; @@ -542,7 +542,7 @@ static irqreturn_t hinfc_irq_handle(int irq, void *devid) static int hisi_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct hinfc_host *host = chip->priv; + struct hinfc_host *host = nand_get_controller_data(chip); int max_bitflips = 0, stat = 0, stat_max = 0, status_ecc; int stat_1, stat_2; @@ -574,7 +574,7 @@ static int hisi_nand_read_page_hwecc(struct mtd_info *mtd, static int hisi_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) { - struct hinfc_host *host = chip->priv; + struct hinfc_host *host = nand_get_controller_data(chip); chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -738,7 +738,7 @@ static int hisi_nfc_probe(struct platform_device *pdev) mtd->name = "hisi_nand"; mtd->dev.parent = &pdev->dev; - chip->priv = host; + nand_set_controller_data(chip, host); nand_set_flash_node(chip, np); chip->cmdfunc = hisi_nfc_cmdfunc; chip->select_chip = hisi_nfc_select_chip; diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index db59fa2..9bc435d 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -275,7 +275,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = nand_chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip); if (cmd != NAND_CMD_NONE) { if (ctrl & NAND_CLE) @@ -291,7 +291,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, static int lpc32xx_nand_device_ready(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = nand_chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip); if ((readb(MLC_ISR(host->io_base)) & (MLCISR_CONTROLLER_READY | MLCISR_NAND_READY)) == @@ -317,7 +317,7 @@ static irqreturn_t lpc3xxx_nand_irq(int irq, struct lpc32xx_nand_host *host) static int lpc32xx_waitfunc_nand(struct mtd_info *mtd, struct nand_chip *chip) { - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); if (readb(MLC_ISR(host->io_base)) & MLCISR_NAND_READY) goto exit; @@ -337,7 +337,7 @@ exit: static int lpc32xx_waitfunc_controller(struct mtd_info *mtd, struct nand_chip *chip) { - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); if (readb(MLC_ISR(host->io_base)) & MLCISR_CONTROLLER_READY) goto exit; @@ -389,7 +389,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len, enum dma_transfer_direction dir) { struct nand_chip *chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); struct dma_async_tx_descriptor *desc; int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; int res; @@ -430,7 +430,7 @@ out1: static int lpc32xx_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); int i, j; uint8_t *oobbuf = chip->oob_poi; uint32_t mlc_isr; @@ -497,7 +497,7 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd, const uint8_t *buf, int oob_required, int page) { - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); const uint8_t *oobbuf = chip->oob_poi; uint8_t *dma_buf = (uint8_t *)buf; int res; @@ -542,7 +542,7 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd, static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) { - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); /* Read whole page - necessary with MLC controller! */ lpc32xx_read_page(mtd, chip, host->dummy_buf, 1, page); @@ -679,7 +679,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) host->pdata = dev_get_platdata(&pdev->dev); - nand_chip->priv = host; /* link the private data structures */ + /* link the private data structures */ + nand_set_controller_data(nand_chip, host); nand_set_flash_node(nand_chip, pdev->dev.of_node); mtd->dev.parent = &pdev->dev; diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index ccd10b1..3b8f373 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c @@ -260,7 +260,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, { uint32_t tmp; struct nand_chip *chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); /* Does CE state need to be changed? */ tmp = readl(SLC_CFG(host->io_base)); @@ -284,7 +284,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, static int lpc32xx_nand_device_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); int rdy = 0; if ((readl(SLC_STAT(host->io_base)) & SLCSTAT_NAND_READY) != 0) @@ -339,7 +339,7 @@ static int lpc32xx_nand_ecc_calculate(struct mtd_info *mtd, static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); return (uint8_t)readl(SLC_DATA(host->io_base)); } @@ -350,7 +350,7 @@ static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd) static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); /* Direct device read with no ECC */ while (len-- > 0) @@ -363,7 +363,7 @@ static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); /* Direct device write with no ECC */ while (len-- > 0) @@ -428,7 +428,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, dma_addr_t dma, void *mem, int len, enum dma_transfer_direction dir) { struct nand_chip *chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); struct dma_async_tx_descriptor *desc; int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; int res; @@ -488,7 +488,7 @@ static int lpc32xx_xfer(struct mtd_info *mtd, uint8_t *buf, int eccsubpages, int read) { struct nand_chip *chip = mtd_to_nand(mtd); - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); int i, status = 0; unsigned long timeout; int res; @@ -603,7 +603,7 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); int stat, i, status; uint8_t *oobecc, tmpecc[LPC32XX_ECC_SAVE_SIZE]; @@ -665,7 +665,7 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd, const uint8_t *buf, int oob_required, int page) { - struct lpc32xx_nand_host *host = chip->priv; + struct lpc32xx_nand_host *host = nand_get_controller_data(chip); uint8_t *pb = chip->oob_poi + chip->ecc.layout->eccpos[0]; int error; @@ -800,7 +800,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) chip = &host->nand_chip; mtd = nand_to_mtd(chip); - chip->priv = host; + nand_set_controller_data(chip, host); nand_set_flash_node(chip, pdev->dev.of_node); mtd->owner = THIS_MODULE; mtd->dev.parent = &pdev->dev; diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 6d0ca33..6b93e89 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -135,7 +135,7 @@ static void mpc5121_nfc_done(struct mtd_info *mtd); static inline u16 nfc_read(struct mtd_info *mtd, uint reg) { struct nand_chip *chip = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = chip->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); return in_be16(prv->regs + reg); } @@ -144,7 +144,7 @@ static inline u16 nfc_read(struct mtd_info *mtd, uint reg) static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val) { struct nand_chip *chip = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = chip->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); out_be16(prv->regs + reg, val); } @@ -214,7 +214,7 @@ static irqreturn_t mpc5121_nfc_irq(int irq, void *data) { struct mtd_info *mtd = data; struct nand_chip *chip = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = chip->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); nfc_set(mtd, NFC_CONFIG1, NFC_INT_MASK); wake_up(&prv->irq_waitq); @@ -226,7 +226,7 @@ static irqreturn_t mpc5121_nfc_irq(int irq, void *data) static void mpc5121_nfc_done(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = chip->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); int rv; if ((nfc_read(mtd, NFC_CONFIG2) & NFC_INT) == 0) { @@ -281,7 +281,7 @@ static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip) static int ads5121_chipselect_init(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = chip->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); struct device_node *dn; dn = of_find_compatible_node(NULL, NULL, "fsl,mpc5121ads-cpld"); @@ -303,7 +303,7 @@ static int ads5121_chipselect_init(struct mtd_info *mtd) static void ads5121_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *nand = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = nand->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand); u8 v; v = in_8(prv->csreg); @@ -333,7 +333,7 @@ static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command, int column, int page) { struct nand_chip *chip = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = chip->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); prv->column = (column >= 0) ? column : 0; prv->spareonly = 0; @@ -406,7 +406,7 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset, u8 *buffer, uint size, int wr) { struct nand_chip *nand = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = nand->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand); uint o, s, sbsize, blksize; /* @@ -458,7 +458,7 @@ static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len, int wr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = chip->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); uint c = prv->column; uint l; @@ -536,7 +536,7 @@ static u16 mpc5121_nfc_read_word(struct mtd_info *mtd) static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = chip->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); struct mpc512x_reset_module *rm; struct device_node *rmnode; uint rcw_pagesize = 0; @@ -615,7 +615,7 @@ out: static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct mpc5121_nfc_prv *prv = chip->priv; + struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); if (prv->clk) clk_disable_unprepare(prv->clk); @@ -657,7 +657,7 @@ static int mpc5121_nfc_probe(struct platform_device *op) mtd = nand_to_mtd(chip); mtd->dev.parent = dev; - chip->priv = prv; + nand_set_controller_data(chip, prv); nand_set_flash_node(chip, dn); prv->dev = dev; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 66e56bb..854c832 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -532,7 +532,7 @@ static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islas static void send_page_v3(struct mtd_info *mtd, unsigned int ops) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); uint32_t tmp; tmp = readl(NFC_V3_CONFIG1); @@ -548,7 +548,7 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops) static void send_page_v2(struct mtd_info *mtd, unsigned int ops) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); /* NANDFC buffer 0 is used for page read/write */ writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); @@ -562,7 +562,7 @@ static void send_page_v2(struct mtd_info *mtd, unsigned int ops) static void send_page_v1(struct mtd_info *mtd, unsigned int ops) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); int bufs, i; if (mtd->writesize > 512) @@ -663,7 +663,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); /* * 1-Bit errors are automatically corrected in HW. No need for @@ -684,7 +684,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); u32 ecc_stat, err; int no_subpages = 1; int ret = 0; @@ -722,7 +722,7 @@ static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, static u_char mxc_nand_read_byte(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); uint8_t ret; /* Check for status request */ @@ -746,7 +746,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) static uint16_t mxc_nand_read_word(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); uint16_t ret; ret = *(uint16_t *)(host->data_buf + host->buf_start); @@ -762,7 +762,7 @@ static void mxc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); u16 col = host->buf_start; int n = mtd->oobsize + mtd->writesize - col; @@ -780,7 +780,7 @@ static void mxc_nand_write_buf(struct mtd_info *mtd, static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); u16 col = host->buf_start; int n = mtd->oobsize + mtd->writesize - col; @@ -796,7 +796,7 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); if (chip == -1) { /* Disable the NFC clock */ @@ -817,7 +817,7 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); if (chip == -1) { /* Disable the NFC clock */ @@ -850,7 +850,7 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) static void copy_spare(struct mtd_info *mtd, bool bfrom) { struct nand_chip *this = mtd_to_nand(mtd); - struct mxc_nand_host *host = this->priv; + struct mxc_nand_host *host = nand_get_controller_data(this); u16 i, oob_chunk_size; u16 num_chunks = mtd->writesize / 512; @@ -893,7 +893,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); /* Write out column address, if necessary */ if (column != -1) { @@ -979,7 +979,7 @@ static void ecc_8bit_layout_4k(struct nand_ecclayout *layout) static void preset_v1(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); uint16_t config1 = 0; if (nand_chip->ecc.mode == NAND_ECC_HW && mtd->writesize) @@ -1007,7 +1007,7 @@ static void preset_v1(struct mtd_info *mtd) static void preset_v2(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); uint16_t config1 = 0; config1 |= NFC_V2_CONFIG1_FP_INT; @@ -1053,7 +1053,7 @@ static void preset_v2(struct mtd_info *mtd) static void preset_v3(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(chip); uint32_t config2, config3; int i, addr_phases; @@ -1124,7 +1124,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_chip->priv; + struct mxc_nand_host *host = nand_get_controller_data(nand_chip); pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", command, column, page_addr); @@ -1520,7 +1520,7 @@ static int mxcnd_probe(struct platform_device *pdev) /* 50 us command delay time */ this->chip_delay = 5; - this->priv = host; + nand_set_controller_data(this, host); nand_set_flash_node(this, pdev->dev.of_node), this->dev_ready = mxc_nand_dev_ready; this->cmdfunc = mxc_nand_command; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 78de37d..f57f461 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -667,7 +667,7 @@ static char *get_partition_name(int i) static int init_nandsim(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct nandsim *ns = chip->priv; + struct nandsim *ns = nand_get_controller_data(chip); int i, ret = 0; uint64_t remains; uint64_t next_offset; @@ -2244,7 +2244,7 @@ static int __init ns_init_module(void) } nsmtd = nand_to_mtd(chip); nand = (struct nandsim *)(chip + 1); - chip->priv = (void *)nand; + nand_set_controller_data(chip, (void *)nand); /* * Register simulator's callbacks. diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 7d72f4f..218c789 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -48,7 +48,7 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip) { uint32_t ccr; struct nand_chip *nchip = mtd_to_nand(mtd); - struct ndfc_controller *ndfc = nchip->priv; + struct ndfc_controller *ndfc = nand_get_controller_data(nchip); ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); if (chip >= 0) { @@ -62,7 +62,7 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip) static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *chip = mtd_to_nand(mtd); - struct ndfc_controller *ndfc = chip->priv; + struct ndfc_controller *ndfc = nand_get_controller_data(chip); if (cmd == NAND_CMD_NONE) return; @@ -76,7 +76,7 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) static int ndfc_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct ndfc_controller *ndfc = chip->priv; + struct ndfc_controller *ndfc = nand_get_controller_data(chip); return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; } @@ -85,7 +85,7 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) { uint32_t ccr; struct nand_chip *chip = mtd_to_nand(mtd); - struct ndfc_controller *ndfc = chip->priv; + struct ndfc_controller *ndfc = nand_get_controller_data(chip); ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); ccr |= NDFC_CCR_RESET_ECC; @@ -97,7 +97,7 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { struct nand_chip *chip = mtd_to_nand(mtd); - struct ndfc_controller *ndfc = chip->priv; + struct ndfc_controller *ndfc = nand_get_controller_data(chip); uint32_t ecc; uint8_t *p = (uint8_t *)&ecc; @@ -121,7 +121,7 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd, static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct ndfc_controller *ndfc = chip->priv; + struct ndfc_controller *ndfc = nand_get_controller_data(chip); uint32_t *p = (uint32_t *) buf; for(;len > 0; len -= 4) @@ -131,7 +131,7 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct ndfc_controller *ndfc = chip->priv; + struct ndfc_controller *ndfc = nand_get_controller_data(chip); uint32_t *p = (uint32_t *) buf; for(;len > 0; len -= 4) @@ -165,7 +165,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, chip->ecc.size = 256; chip->ecc.bytes = 3; chip->ecc.strength = 1; - chip->priv = ndfc; + nand_set_controller_data(chip, ndfc); mtd->dev.parent = &ndfc->ofdev->dev; diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 2c2be612..d4614bf 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -26,7 +26,7 @@ static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *nc = mtd_to_nand(mtd); - struct orion_nand_data *board = nc->priv; + struct orion_nand_data *board = nand_get_controller_data(nc); u32 offs; if (cmd == NAND_CMD_NONE) @@ -124,7 +124,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; - nc->priv = board; + nand_set_controller_data(nc, board); nand_set_flash_node(nc, pdev->dev.of_node); nc->IO_ADDR_R = nc->IO_ADDR_W = io_base; nc->cmd_ctrl = orion_nand_cmd_ctrl; diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 10704ae..86fc245 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1114,7 +1114,7 @@ static void nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct pxa3xx_nand_host *host = chip->priv; + struct pxa3xx_nand_host *host = nand_get_controller_data(chip); struct pxa3xx_nand_info *info = host->info_data; int exec_cmd; @@ -1163,7 +1163,7 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, int column, int page_addr) { struct nand_chip *chip = mtd_to_nand(mtd); - struct pxa3xx_nand_host *host = chip->priv; + struct pxa3xx_nand_host *host = nand_get_controller_data(chip); struct pxa3xx_nand_info *info = host->info_data; int exec_cmd, ext_cmd_type; @@ -1283,7 +1283,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct pxa3xx_nand_host *host = chip->priv; + struct pxa3xx_nand_host *host = nand_get_controller_data(chip); struct pxa3xx_nand_info *info = host->info_data; chip->read_buf(mtd, buf, mtd->writesize); @@ -1310,7 +1310,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct pxa3xx_nand_host *host = chip->priv; + struct pxa3xx_nand_host *host = nand_get_controller_data(chip); struct pxa3xx_nand_info *info = host->info_data; char retval = 0xFF; @@ -1324,7 +1324,7 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct pxa3xx_nand_host *host = chip->priv; + struct pxa3xx_nand_host *host = nand_get_controller_data(chip); struct pxa3xx_nand_info *info = host->info_data; u16 retval = 0xFFFF; @@ -1338,7 +1338,7 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct pxa3xx_nand_host *host = chip->priv; + struct pxa3xx_nand_host *host = nand_get_controller_data(chip); struct pxa3xx_nand_info *info = host->info_data; int real_len = min_t(size_t, len, info->buf_count - info->buf_start); @@ -1350,7 +1350,7 @@ static void pxa3xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); - struct pxa3xx_nand_host *host = chip->priv; + struct pxa3xx_nand_host *host = nand_get_controller_data(chip); struct pxa3xx_nand_info *info = host->info_data; int real_len = min_t(size_t, len, info->buf_count - info->buf_start); @@ -1366,7 +1366,7 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip) static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { struct nand_chip *chip = mtd_to_nand(mtd); - struct pxa3xx_nand_host *host = chip->priv; + struct pxa3xx_nand_host *host = nand_get_controller_data(chip); struct pxa3xx_nand_info *info = host->info_data; if (info->need_wait) { @@ -1573,7 +1573,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, static int pxa3xx_nand_scan(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct pxa3xx_nand_host *host = chip->priv; + struct pxa3xx_nand_host *host = nand_get_controller_data(chip); struct pxa3xx_nand_info *info = host->info_data; struct platform_device *pdev = info->pdev; struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -1704,7 +1704,7 @@ static int alloc_nand_resource(struct platform_device *pdev) for (cs = 0; cs < pdata->num_cs; cs++) { host = (void *)&info[1] + sizeof(*host) * cs; chip = &host->chip; - chip->priv = host; + nand_set_controller_data(chip, host); mtd = nand_to_mtd(chip); info->host[cs] = host; host->cs = cs; @@ -1713,7 +1713,7 @@ static int alloc_nand_resource(struct platform_device *pdev) /* FIXME: all chips use the same device tree partitions */ nand_set_flash_node(chip, np); - chip->priv = host; + nand_set_controller_data(chip, host); chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; chip->controller = &info->controller; diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 5b15f2f..fc9287a 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -65,7 +65,7 @@ static inline void r852_write_reg_dword(struct r852_device *dev, static inline struct r852_device *r852_get_dev(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - return chip->priv; + return nand_get_controller_data(chip); } @@ -361,7 +361,7 @@ static void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl) */ static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) { - struct r852_device *dev = chip->priv; + struct r852_device *dev = nand_get_controller_data(chip); unsigned long timeout; int status; @@ -879,7 +879,7 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) if (!dev) goto error5; - chip->priv = dev; + nand_set_controller_data(chip, dev); dev->chip = chip; dev->pci_dev = pci_dev; pci_set_drvdata(pci_dev, dev); diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index bc94c5d..01ac74f 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -385,7 +385,7 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) struct nand_chip *this = mtd_to_nand(mtd); unsigned long cur; - nmtd = this->priv; + nmtd = nand_get_controller_data(this); info = nmtd->info; if (chip != -1) @@ -794,7 +794,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->read_buf = s3c2410_nand_read_buf; chip->select_chip = s3c2410_nand_select_chip; chip->chip_delay = 50; - chip->priv = nmtd; + nand_set_controller_data(chip, nmtd); chip->options = set->options; chip->controller = &info->controller; diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index d7e9d4d..e3305f9 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -45,7 +45,7 @@ static void socrates_nand_write_buf(struct mtd_info *mtd, { int i; struct nand_chip *this = mtd_to_nand(mtd); - struct socrates_nand_host *host = this->priv; + struct socrates_nand_host *host = nand_get_controller_data(this); for (i = 0; i < len; i++) { out_be32(host->io_base, FPGA_NAND_ENABLE | @@ -64,7 +64,7 @@ static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { int i; struct nand_chip *this = mtd_to_nand(mtd); - struct socrates_nand_host *host = this->priv; + struct socrates_nand_host *host = nand_get_controller_data(this); uint32_t val; val = FPGA_NAND_ENABLE | FPGA_NAND_CMD_READ; @@ -105,7 +105,7 @@ static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct socrates_nand_host *host = nand_chip->priv; + struct socrates_nand_host *host = nand_get_controller_data(nand_chip); uint32_t val; if (cmd == NAND_CMD_NONE) @@ -130,7 +130,7 @@ static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, static int socrates_nand_device_ready(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct socrates_nand_host *host = nand_chip->priv; + struct socrates_nand_host *host = nand_get_controller_data(nand_chip); if (in_be32(host->io_base) & FPGA_NAND_BUSY) return 0; /* busy */ @@ -162,7 +162,8 @@ static int socrates_nand_probe(struct platform_device *ofdev) mtd = nand_to_mtd(nand_chip); host->dev = &ofdev->dev; - nand_chip->priv = host; /* link the private data structures */ + /* link the private data structures */ + nand_set_controller_data(nand_chip, host); nand_set_flash_node(nand_chip, ofdev->dev.of_node); mtd->name = "socrates_nand"; mtd->dev.parent = &ofdev->dev; diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index 27488ee..04d63f5 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c @@ -79,7 +79,7 @@ struct txx9ndfmc_drvdata { static struct platform_device *mtd_to_platdev(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); - struct txx9ndfmc_priv *txx9_priv = chip->priv; + struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip); return txx9_priv->dev; } @@ -135,7 +135,7 @@ static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *chip = mtd_to_nand(mtd); - struct txx9ndfmc_priv *txx9_priv = chip->priv; + struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip); struct platform_device *dev = txx9_priv->dev; struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); @@ -340,7 +340,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) chip->chip_delay = 100; chip->controller = &drvdata->hw_control; - chip->priv = txx9_priv; + nand_set_controller_data(chip, txx9_priv); txx9_priv->dev = dev; if (plat->ch_mask != 1) { @@ -389,7 +389,7 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev) if (!mtd) continue; chip = mtd_to_nand(mtd); - txx9_priv = chip->priv; + txx9_priv = nand_get_controller_data(chip); nand_release(mtd); kfree(txx9_priv->mtdname); -- cgit v1.1 From f118902490aa1c3a361e485dd38a7b28cd130d71 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 7 Jan 2016 10:02:59 -0800 Subject: mtd: jz4780_nand: remove useless mtd->priv = chip assignment As of commit 2d3b77bac34b ("mtd: nand: update mtd_to_nand()"), this assignment isn't necessary, since struct mtd_info is embedded in struct nand_chip. Signed-off-by: Brian Norris Cc: Harvey Hunt Cc: Alex Smith Reviewed-by: Boris Brezillon --- drivers/mtd/nand/jz4780_nand.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/jz4780_nand.c b/drivers/mtd/nand/jz4780_nand.c index 17eb9f2..6156c55 100644 --- a/drivers/mtd/nand/jz4780_nand.c +++ b/drivers/mtd/nand/jz4780_nand.c @@ -270,7 +270,6 @@ static int jz4780_nand_init_chip(struct platform_device *pdev, chip = &nand->chip; mtd = nand_to_mtd(chip); - mtd->priv = chip; mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), cs->bank); if (!mtd->name) -- cgit v1.1 From c66b651ce60bb82d8f6fe8ca35e70f323e3a260c Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 7 Jan 2016 11:06:46 -0800 Subject: mtd: nandsim: use nand_get_controller_data() Commit d699ed250c07 ("mtd: nand: make use of nand_set/get_controller_data() helpers") overlooked some uses of nand_chip::priv. Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon --- drivers/mtd/nand/nandsim.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index f57f461..1fd5195 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -1908,7 +1908,8 @@ static void switch_state(struct nandsim *ns) static u_char ns_nand_read_byte(struct mtd_info *mtd) { - struct nandsim *ns = mtd_to_nand(mtd)->priv; + struct nand_chip *chip = mtd_to_nand(mtd); + struct nandsim *ns = nand_get_controller_data(chip); u_char outb = 0x00; /* Sanity and correctness checks */ @@ -1969,7 +1970,8 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd) static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) { - struct nandsim *ns = mtd_to_nand(mtd)->priv; + struct nand_chip *chip = mtd_to_nand(mtd); + struct nandsim *ns = nand_get_controller_data(chip); /* Sanity and correctness checks */ if (!ns->lines.ce) { @@ -2123,7 +2125,8 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask) { - struct nandsim *ns = mtd_to_nand(mtd)->priv; + struct nand_chip *chip = mtd_to_nand(mtd); + struct nandsim *ns = nand_get_controller_data(chip); ns->lines.cle = bitmask & NAND_CLE ? 1 : 0; ns->lines.ale = bitmask & NAND_ALE ? 1 : 0; @@ -2150,7 +2153,8 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd) static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { - struct nandsim *ns = mtd_to_nand(mtd)->priv; + struct nand_chip *chip = mtd_to_nand(mtd); + struct nandsim *ns = nand_get_controller_data(chip); /* Check that chip is expecting data input */ if (!(ns->state & STATE_DATAIN_MASK)) { @@ -2177,7 +2181,8 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { - struct nandsim *ns = mtd_to_nand(mtd)->priv; + struct nand_chip *chip = mtd_to_nand(mtd); + struct nandsim *ns = nand_get_controller_data(chip); /* Sanity and correctness checks */ if (!ns->lines.ce) { @@ -2404,7 +2409,8 @@ module_init(ns_init_module); */ static void __exit ns_cleanup_module(void) { - struct nandsim *ns = mtd_to_nand(nsmtd)->priv; + struct nand_chip *chip = mtd_to_nand(nsmtd); + struct nandsim *ns = nand_get_controller_data(chip); int i; nandsim_debugfs_remove(ns); -- cgit v1.1 From 6c1207b5b8422cdddf467b9fbef922c4c374d382 Mon Sep 17 00:00:00 2001 From: Harvey Hunt Date: Fri, 8 Jan 2016 16:45:17 +0000 Subject: mtd: nand: jz4780: Update ecc correction error codes Update jz4780_bch_ecc_correct's return codes with appropriate values, as specified in /include/linux/mtd/nand.h. Signed-off-by: Harvey Hunt Cc: Alex Smith Cc: Boris Brezillon Cc: linux-kernel@vger.kernel.org Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/jz4780_bch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/jz4780_bch.c b/drivers/mtd/nand/jz4780_bch.c index 5954fbf..755499c 100644 --- a/drivers/mtd/nand/jz4780_bch.c +++ b/drivers/mtd/nand/jz4780_bch.c @@ -210,8 +210,8 @@ EXPORT_SYMBOL(jz4780_bch_calculate); * Given the raw data and the ECC read from the NAND device, detects and * corrects errors in the data. * - * Return: the number of bit errors corrected, or -1 if there are too many - * errors to correct or we timed out waiting for the controller. + * Return: the number of bit errors corrected, -EBADMSG if there are too many + * errors to correct or -ETIMEDOUT if we timed out waiting for the controller. */ int jz4780_bch_correct(struct jz4780_bch *bch, struct jz4780_bch_params *params, u8 *buf, u8 *ecc_code) @@ -227,13 +227,13 @@ int jz4780_bch_correct(struct jz4780_bch *bch, struct jz4780_bch_params *params, if (!jz4780_bch_wait_complete(bch, BCH_BHINT_DECF, ®)) { dev_err(bch->dev, "timed out while correcting data\n"); - ret = -1; + ret = -ETIMEDOUT; goto out; } if (reg & BCH_BHINT_UNCOR) { dev_warn(bch->dev, "uncorrectable ECC error\n"); - ret = -1; + ret = -EBADMSG; goto out; } -- cgit v1.1 From 9146cbd52b11d4ade62dba8f238ec5e421c3fa2b Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 7 Jan 2016 09:53:08 -0800 Subject: mtd: jz4780_nand: replace if/else blocks with switch/case Using switch/case helps make this logic more clear and more robust. With this structure: * it's clear that this driver only support ECC_{HW,SOFT,SOFT_BCH}; and * we can sanely handle new ECC unsupported modes (right now, this code makes incorrect assumptions about the possible values in the nand_ecc_modes_t enum; e.g., what happens with NAND_ECC_HW_OOB_FIRST?) Signed-off-by: Brian Norris Cc: Alex Smith Reviewed-by: Boris Brezillon Tested-by: Harvey Hunt Acked-by: Harvey Hunt --- drivers/mtd/nand/jz4780_nand.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/jz4780_nand.c b/drivers/mtd/nand/jz4780_nand.c index 6156c55..e1c016c 100644 --- a/drivers/mtd/nand/jz4780_nand.c +++ b/drivers/mtd/nand/jz4780_nand.c @@ -171,29 +171,33 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de chip->ecc.bytes = fls((1 + 8) * chip->ecc.size) * (chip->ecc.strength / 8); - if (nfc->bch && chip->ecc.mode == NAND_ECC_HW) { + switch (chip->ecc.mode) { + case NAND_ECC_HW: + if (!nfc->bch) { + dev_err(dev, "HW BCH selected, but BCH controller not found\n"); + return -ENODEV; + } + chip->ecc.hwctl = jz4780_nand_ecc_hwctl; chip->ecc.calculate = jz4780_nand_ecc_calculate; chip->ecc.correct = jz4780_nand_ecc_correct; - } else if (!nfc->bch && chip->ecc.mode == NAND_ECC_HW) { - dev_err(dev, "HW BCH selected, but BCH controller not found\n"); - return -ENODEV; - } - - if (chip->ecc.mode == NAND_ECC_HW_SYNDROME) { - dev_err(dev, "ECC HW syndrome not supported\n"); - return -EINVAL; - } - - if (chip->ecc.mode != NAND_ECC_NONE) + /* fall through */ + case NAND_ECC_SOFT: + case NAND_ECC_SOFT_BCH: dev_info(dev, "using %s (strength %d, size %d, bytes %d)\n", (nfc->bch) ? "hardware BCH" : "software ECC", chip->ecc.strength, chip->ecc.size, chip->ecc.bytes); - else + break; + case NAND_ECC_NONE: dev_info(dev, "not using ECC\n"); + break; + default: + dev_err(dev, "ECC mode %d not supported\n", chip->ecc.mode); + return -EINVAL; + } - /* The NAND core will generate the ECC layout. */ - if (chip->ecc.mode == NAND_ECC_SOFT || chip->ecc.mode == NAND_ECC_SOFT_BCH) + /* The NAND core will generate the ECC layout for SW ECC */ + if (chip->ecc.mode != NAND_ECC_HW) return 0; /* Generate ECC layout. ECC codes are right aligned in the OOB area. */ -- cgit v1.1 From 34b89df90374b631692132640c6b3dbef52f808d Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Thu, 26 Nov 2015 21:23:50 +0100 Subject: mtd: ubi: wl: avoid erasing a PEB which is empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wear_leveling_worker() currently unconditionally puts a PEB on erase in the error case even it just been taken from the free_list and never used. In case the PEB was never used it can be put back on the free list saving a precious erase cycle. v1…v2: - to_leb_clean -> dst_leb_clean - use the nested option for ensure_wear_leveling() - do_sync_erase() can't go -ENOMEM so we can just go into RO-mode now. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/wl.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 5606563..17ec948 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -628,6 +628,7 @@ static int do_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, return __erase_worker(ubi, &wl_wrk); } +static int ensure_wear_leveling(struct ubi_device *ubi, int nested); /** * wear_leveling_worker - wear-leveling worker function. * @ubi: UBI device description object @@ -649,6 +650,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, #endif struct ubi_wl_entry *e1, *e2; struct ubi_vid_hdr *vid_hdr; + int dst_leb_clean = 0; kfree(wrk); if (shutdown) @@ -753,6 +755,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0); if (err && err != UBI_IO_BITFLIPS) { + dst_leb_clean = 1; if (err == UBI_IO_FF) { /* * We are trying to move PEB without a VID header. UBI @@ -798,10 +801,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, * protection queue. */ protect = 1; + dst_leb_clean = 1; goto out_not_moved; } if (err == MOVE_RETRY) { scrubbing = 1; + dst_leb_clean = 1; goto out_not_moved; } if (err == MOVE_TARGET_BITFLIPS || err == MOVE_TARGET_WR_ERR || @@ -827,6 +832,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ubi->erroneous_peb_count); goto out_error; } + dst_leb_clean = 1; erroneous = 1; goto out_not_moved; } @@ -897,15 +903,24 @@ out_not_moved: wl_tree_add(e1, &ubi->scrub); else wl_tree_add(e1, &ubi->used); + if (dst_leb_clean) { + wl_tree_add(e2, &ubi->free); + ubi->free_count++; + } + ubi_assert(!ubi->move_to_put); ubi->move_from = ubi->move_to = NULL; ubi->wl_scheduled = 0; spin_unlock(&ubi->wl_lock); ubi_free_vid_hdr(ubi, vid_hdr); - err = do_sync_erase(ubi, e2, vol_id, lnum, torture); - if (err) - goto out_ro; + if (dst_leb_clean) { + ensure_wear_leveling(ubi, 1); + } else { + err = do_sync_erase(ubi, e2, vol_id, lnum, torture); + if (err) + goto out_ro; + } mutex_unlock(&ubi->move_mutex); return 0; -- cgit v1.1 From 92752d9974882e2e5384e92668f02a134f9c7463 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jan 2016 14:46:29 +0100 Subject: mtd: mtk-nor: Drop bogus __init from mtk_nor_init() WARNING: drivers/mtd/spi-nor/mtk-quadspi.o(.text+0x77e): Section mismatch in reference from the function mtk_nor_drv_probe() to the function .init.text:mtk_nor_init() The function mtk_nor_drv_probe() references the function __init mtk_nor_init(). This is often because mtk_nor_drv_probe lacks a __init annotation or the annotation of mtk_nor_init is wrong. Drop the bogus __init from mtk_nor_init() to kill this warning. Signed-off-by: Geert Uytterhoeven Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/mtk-quadspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c index d5f850d..8bed1a4c 100644 --- a/drivers/mtd/spi-nor/mtk-quadspi.c +++ b/drivers/mtd/spi-nor/mtk-quadspi.c @@ -371,8 +371,8 @@ static int mt8173_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, return ret; } -static int __init mtk_nor_init(struct mt8173_nor *mt8173_nor, - struct device_node *flash_node) +static int mtk_nor_init(struct mt8173_nor *mt8173_nor, + struct device_node *flash_node) { int ret; struct spi_nor *nor; -- cgit v1.1 From f9bdbd6c46c8ce0bb95f5b708a4a4a4b6b9a5917 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 22:38:08 +0100 Subject: mtd: nuc900_nand: read correct SMISR register The nuc900_nand driver has always passed an incorrect register address in its nuc900_check_rb() function, which cannot possibly work, and in some configurations gives us a build warning: drivers/mtd/nand/nuc900_nand.c: In function 'nuc900_check_rb': drivers/mtd/nand/nuc900_nand.c:27:23: warning: passing argument 1 of '__raw_readl' makes pointer from integer without a cast [-Wint-conversion] #define REG_SMISR 0xac drivers/mtd/nand/nuc900_nand.c:118:20: note: in expansion of macro 'REG_SMISR' val = __raw_readl(REG_SMISR); This makes sure we actually read from the register rather than from (void *)0x000000ac in user space. I suspect nobody noticed this before because the nuc900_nand_devready() function never gets called, or nobody uses this driver on an upstream kernel. Possibly even both. Signed-off-by: Arnd Bergmann Signed-off-by: Brian Norris --- drivers/mtd/nand/nuc900_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 220ddfc..dbc5b57 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -113,7 +113,7 @@ static int nuc900_check_rb(struct nuc900_nand *nand) { unsigned int val; spin_lock(&nand->lock); - val = __raw_readl(REG_SMISR); + val = __raw_readl(nand->reg + REG_SMISR); val &= READYBUSY; spin_unlock(&nand->lock); -- cgit v1.1 From 5955102c9984fa081b2d570cfac75c97eecf8f3b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 22 Jan 2016 15:40:57 -0500 Subject: wrappers for ->i_mutex access parallel to mutex_{lock,unlock,trylock,is_locked,lock_nested}, inode_foo(inode) being mutex_foo(&inode->i_mutex). Please, use those for access to ->i_mutex; over the coming cycle ->i_mutex will become rwsem, with ->lookup() done with it held only shared. Signed-off-by: Al Viro --- drivers/mtd/ubi/cdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 54e056d..ee2b74d 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -174,9 +174,9 @@ static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end, struct ubi_device *ubi = desc->vol->ubi; struct inode *inode = file_inode(file); int err; - mutex_lock(&inode->i_mutex); + inode_lock(inode); err = ubi_sync(ubi->ubi_num); - mutex_unlock(&inode->i_mutex); + inode_unlock(inode); return err; } -- cgit v1.1 From 23819f2eaab87080b0190ed94a0728fc8ea84711 Mon Sep 17 00:00:00 2001 From: Christophe Jaillet Date: Sun, 10 Jan 2016 07:46:39 +0100 Subject: mtd: nand: mpc5121: use 'of_machine_is_compatible' to simplify code The current code is the same as 'of_machine_is_compatible'. So use it in order to remove a few lines of code and to be more consistent with other parts of the kernel. Signed-off-by: Christophe JAILLET Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/mpc5121_nfc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 6b93e89..5d7843f 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -626,7 +626,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) static int mpc5121_nfc_probe(struct platform_device *op) { - struct device_node *rootnode, *dn = op->dev.of_node; + struct device_node *dn = op->dev.of_node; struct clk *clk; struct device *dev = &op->dev; struct mpc5121_nfc_prv *prv; @@ -712,18 +712,15 @@ static int mpc5121_nfc_probe(struct platform_device *op) chip->ecc.mode = NAND_ECC_SOFT; /* Support external chip-select logic on ADS5121 board */ - rootnode = of_find_node_by_path("/"); - if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) { + if (of_machine_is_compatible("fsl,mpc5121ads")) { retval = ads5121_chipselect_init(mtd); if (retval) { dev_err(dev, "Chipselect init error!\n"); - of_node_put(rootnode); return retval; } chip->select_chip = ads5121_select_chip; } - of_node_put(rootnode); /* Enable NFC clock */ clk = devm_clk_get(dev, "ipg"); -- cgit v1.1 From 8ebc5637154dc58378c85ea7d0047fbc72cfc2d7 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 2 Dec 2015 12:01:06 +0100 Subject: mtd: nand: add NAND_NEED_SCRAMBLING flag to the H27UCG8T2ATR-BC definition The H27UCG8T2ATR-BC requires an external data scrambler. Reflect this constraint in the nand_flash_ids definition. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_ids.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index a8804a3..ccc05f5 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -50,8 +50,8 @@ struct nand_flash_dev nand_flash_ids[] = { SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) }, {"H27UCG8T2ATR-BC 64G 3.3V 8-bit", { .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} }, - SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K), - 4 }, + SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640, + NAND_ECC_INFO(40, SZ_1K), 4 }, LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), -- cgit v1.1 From 4be4e03efc7f45ec002e8eddc83c22f80fed392c Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 2 Dec 2015 12:01:07 +0100 Subject: mtd: nand: sunxi: add randomizer support Add support for the randomizer engine available in Allwinner's NFC IP. Randomization is useful to support modern NAND chips which are sensitive to repeated patterns. On such NANDs you might experience an unexpectedly high number of bitflips when you repeat the same pattern all over a given NAND block. Randomizing input data mitigate this problem by avoiding such repeated patterns. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/sunxi_nand.c | 287 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 261 insertions(+), 26 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 51e10a3..5f70071 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -60,6 +60,7 @@ #define NFC_REG_ECC_ERR_CNT(x) ((0x0040 + (x)) & ~0x3) #define NFC_REG_USER_DATA(x) (0x0050 + ((x) * 4)) #define NFC_REG_SPARE_AREA 0x00A0 +#define NFC_REG_PAT_ID 0x00A4 #define NFC_RAM0_BASE 0x0400 #define NFC_RAM1_BASE 0x0800 @@ -538,6 +539,174 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); } +/* These seed values have been extracted from Allwinner's BSP */ +static const u16 sunxi_nfc_randomizer_page_seeds[] = { + 0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72, + 0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436, + 0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d, + 0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130, + 0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56, + 0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55, + 0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb, + 0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17, + 0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62, + 0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064, + 0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126, + 0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e, + 0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3, + 0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b, + 0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d, + 0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db, +}; + +/* + * sunxi_nfc_randomizer_ecc512_seeds and sunxi_nfc_randomizer_ecc1024_seeds + * have been generated using + * sunxi_nfc_randomizer_step(seed, (step_size * 8) + 15), which is what + * the randomizer engine does internally before de/scrambling OOB data. + * + * Those tables are statically defined to avoid calculating randomizer state + * at runtime. + */ +static const u16 sunxi_nfc_randomizer_ecc512_seeds[] = { + 0x3346, 0x367f, 0x1f18, 0x769a, 0x4f64, 0x068c, 0x2ef1, 0x6b64, + 0x28a9, 0x15d7, 0x30f8, 0x3659, 0x53db, 0x7c5f, 0x71d4, 0x4409, + 0x26eb, 0x03cc, 0x655d, 0x47d4, 0x4daa, 0x0877, 0x712d, 0x3617, + 0x3264, 0x49aa, 0x7f9e, 0x588e, 0x4fbc, 0x7176, 0x7f91, 0x6c6d, + 0x4b95, 0x5fb7, 0x3844, 0x4037, 0x0184, 0x081b, 0x0ee8, 0x5b91, + 0x293d, 0x1f71, 0x0e6f, 0x402b, 0x5122, 0x1e52, 0x22be, 0x3d2d, + 0x75bc, 0x7c60, 0x6291, 0x1a2f, 0x61d4, 0x74aa, 0x4140, 0x29ab, + 0x472d, 0x2852, 0x017e, 0x15e8, 0x5ec2, 0x17cf, 0x7d0f, 0x06b8, + 0x117a, 0x6b94, 0x789b, 0x3126, 0x6ac5, 0x5be7, 0x150f, 0x51f8, + 0x7889, 0x0aa5, 0x663d, 0x77e8, 0x0b87, 0x3dcb, 0x360d, 0x218b, + 0x512f, 0x7dc9, 0x6a4d, 0x630a, 0x3547, 0x1dd2, 0x5aea, 0x69a5, + 0x7bfa, 0x5e4f, 0x1519, 0x6430, 0x3a0e, 0x5eb3, 0x5425, 0x0c7a, + 0x5540, 0x3670, 0x63c1, 0x31e9, 0x5a39, 0x2de7, 0x5979, 0x2891, + 0x1562, 0x014b, 0x5b05, 0x2756, 0x5a34, 0x13aa, 0x6cb5, 0x2c36, + 0x5e72, 0x1306, 0x0861, 0x15ef, 0x1ee8, 0x5a37, 0x7ac4, 0x45dd, + 0x44c4, 0x7266, 0x2f41, 0x3ccc, 0x045e, 0x7d40, 0x7c66, 0x0fa0, +}; + +static const u16 sunxi_nfc_randomizer_ecc1024_seeds[] = { + 0x2cf5, 0x35f1, 0x63a4, 0x5274, 0x2bd2, 0x778b, 0x7285, 0x32b6, + 0x6a5c, 0x70d6, 0x757d, 0x6769, 0x5375, 0x1e81, 0x0cf3, 0x3982, + 0x6787, 0x042a, 0x6c49, 0x1925, 0x56a8, 0x40a9, 0x063e, 0x7bd9, + 0x4dbf, 0x55ec, 0x672e, 0x7334, 0x5185, 0x4d00, 0x232a, 0x7e07, + 0x445d, 0x6b92, 0x528f, 0x4255, 0x53ba, 0x7d82, 0x2a2e, 0x3a4e, + 0x75eb, 0x450c, 0x6844, 0x1b5d, 0x581a, 0x4cc6, 0x0379, 0x37b2, + 0x419f, 0x0e92, 0x6b27, 0x5624, 0x01e3, 0x07c1, 0x44a5, 0x130c, + 0x13e8, 0x5910, 0x0876, 0x60c5, 0x54e3, 0x5b7f, 0x2269, 0x509f, + 0x7665, 0x36fd, 0x3e9a, 0x0579, 0x6295, 0x14ef, 0x0a81, 0x1bcc, + 0x4b16, 0x64db, 0x0514, 0x4f07, 0x0591, 0x3576, 0x6853, 0x0d9e, + 0x259f, 0x38b7, 0x64fb, 0x3094, 0x4693, 0x6ddd, 0x29bb, 0x0bc8, + 0x3f47, 0x490e, 0x0c0e, 0x7933, 0x3c9e, 0x5840, 0x398d, 0x3e68, + 0x4af1, 0x71f5, 0x57cf, 0x1121, 0x64eb, 0x3579, 0x15ac, 0x584d, + 0x5f2a, 0x47e2, 0x6528, 0x6eac, 0x196e, 0x6b96, 0x0450, 0x0179, + 0x609c, 0x06e1, 0x4626, 0x42c7, 0x273e, 0x486f, 0x0705, 0x1601, + 0x145b, 0x407e, 0x062b, 0x57a5, 0x53f9, 0x5659, 0x4410, 0x3ccd, +}; + +static u16 sunxi_nfc_randomizer_step(u16 state, int count) +{ + state &= 0x7fff; + + /* + * This loop is just a simple implementation of a Fibonacci LFSR using + * the x16 + x15 + 1 polynomial. + */ + while (count--) + state = ((state >> 1) | + (((state ^ (state >> 1)) & 1) << 14)) & 0x7fff; + + return state; +} + +static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc) +{ + const u16 *seeds = sunxi_nfc_randomizer_page_seeds; + int mod = mtd->erasesize / mtd->writesize; + + if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds)) + mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds); + + if (ecc) { + if (mtd->ecc_step_size == 512) + seeds = sunxi_nfc_randomizer_ecc512_seeds; + else + seeds = sunxi_nfc_randomizer_ecc1024_seeds; + } + + return seeds[page % mod]; +} + +static void sunxi_nfc_randomizer_config(struct mtd_info *mtd, + int page, bool ecc) +{ + struct nand_chip *nand = mtd->priv; + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); + u16 state; + + if (!(nand->options & NAND_NEED_SCRAMBLING)) + return; + + ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); + state = sunxi_nfc_randomizer_state(mtd, page, ecc); + ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK; + writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL); +} + +static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd) +{ + struct nand_chip *nand = mtd->priv; + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + if (!(nand->options & NAND_NEED_SCRAMBLING)) + return; + + writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN, + nfc->regs + NFC_REG_ECC_CTL); +} + +static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd) +{ + struct nand_chip *nand = mtd->priv; + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + + if (!(nand->options & NAND_NEED_SCRAMBLING)) + return; + + writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN, + nfc->regs + NFC_REG_ECC_CTL); +} + +static void sunxi_nfc_randomize_bbm(struct mtd_info *mtd, int page, u8 *bbm) +{ + u16 state = sunxi_nfc_randomizer_state(mtd, page, true); + + bbm[0] ^= state; + bbm[1] ^= sunxi_nfc_randomizer_step(state, 8); +} + +static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd, + const uint8_t *buf, int len, + bool ecc, int page) +{ + sunxi_nfc_randomizer_config(mtd, page, ecc); + sunxi_nfc_randomizer_enable(mtd); + sunxi_nfc_write_buf(mtd, buf, len); + sunxi_nfc_randomizer_disable(mtd); +} + +static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf, + int len, bool ecc, int page) +{ + sunxi_nfc_randomizer_config(mtd, page, ecc); + sunxi_nfc_randomizer_enable(mtd); + sunxi_nfc_read_buf(mtd, buf, len); + sunxi_nfc_randomizer_disable(mtd); +} + static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd) { struct nand_chip *nand = mtd_to_nand(mtd); @@ -574,18 +743,20 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, u8 *data, int data_off, u8 *oob, int oob_off, int *cur_off, - unsigned int *max_bitflips) + unsigned int *max_bitflips, + bool bbm, int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; + int raw_mode = 0; u32 status; int ret; if (*cur_off != data_off) nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1); - sunxi_nfc_read_buf(mtd, NULL, ecc->size); + sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page); if (data_off + ecc->size != oob_off) nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); @@ -594,25 +765,54 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, if (ret) return ret; + sunxi_nfc_randomizer_enable(mtd); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, nfc->regs + NFC_REG_CMD); ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + sunxi_nfc_randomizer_disable(mtd); if (ret) return ret; + *cur_off = oob_off + ecc->bytes + 4; + status = readl(nfc->regs + NFC_REG_ECC_ST); + if (status & NFC_ECC_PAT_FOUND(0)) { + u8 pattern = 0xff; + + if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) + pattern = 0x0; + + memset(data, pattern, ecc->size); + memset(oob, pattern, ecc->bytes + 4); + + return 1; + } + ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0))); memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); - sunxi_nfc_read_buf(mtd, oob, ecc->bytes + 4); + sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page); if (status & NFC_ECC_ERR(0)) { + /* + * Re-read the data with the randomizer disabled to identify + * bitflips in erased pages. + */ + if (nand->options & NAND_NEED_SCRAMBLING) { + nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1); + nand->read_buf(mtd, data, ecc->size); + nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); + nand->read_buf(mtd, oob, ecc->bytes + 4); + } + ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, ecc->bytes + 4, NULL, 0, ecc->strength); + if (ret >= 0) + raw_mode = 1; } else { /* * The engine protects 4 bytes of OOB data per chunk. @@ -620,6 +820,10 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, */ sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(0)), oob); + + /* De-randomize the Bad Block Marker. */ + if (bbm && nand->options & NAND_NEED_SCRAMBLING) + sunxi_nfc_randomize_bbm(mtd, page, oob); } if (ret < 0) { @@ -629,13 +833,12 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, *max_bitflips = max_t(unsigned int, *max_bitflips, ret); } - *cur_off = oob_off + ecc->bytes + 4; - - return 0; + return raw_mode; } static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, - u8 *oob, int *cur_off) + u8 *oob, int *cur_off, + bool randomize, int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &nand->ecc; @@ -649,7 +852,11 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, nand->cmdfunc(mtd, NAND_CMD_RNDOUT, offset + mtd->writesize, -1); - sunxi_nfc_read_buf(mtd, oob + offset, len); + if (!randomize) + sunxi_nfc_read_buf(mtd, oob + offset, len); + else + sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len, + false, page); *cur_off = mtd->oobsize + mtd->writesize; } @@ -662,7 +869,8 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf) static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, const u8 *data, int data_off, const u8 *oob, int oob_off, - int *cur_off) + int *cur_off, bool bbm, + int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); @@ -672,11 +880,20 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, if (data_off != *cur_off) nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1); - sunxi_nfc_write_buf(mtd, data, ecc->size); + sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page); /* Fill OOB data in */ - writel(sunxi_nfc_buf_to_user_data(oob), - nfc->regs + NFC_REG_USER_DATA(0)); + if ((nand->options & NAND_NEED_SCRAMBLING) && bbm) { + u8 user_data[4]; + + memcpy(user_data, oob, 4); + sunxi_nfc_randomize_bbm(mtd, page, user_data); + writel(sunxi_nfc_buf_to_user_data(user_data), + nfc->regs + NFC_REG_USER_DATA(0)); + } else { + writel(sunxi_nfc_buf_to_user_data(oob), + nfc->regs + NFC_REG_USER_DATA(0)); + } if (data_off + ecc->size != oob_off) nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1); @@ -685,11 +902,13 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, if (ret) return ret; + sunxi_nfc_randomizer_enable(mtd); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | NFC_ECC_OP, nfc->regs + NFC_REG_CMD); ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + sunxi_nfc_randomizer_disable(mtd); if (ret) return ret; @@ -699,7 +918,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, } static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, - u8 *oob, int *cur_off) + u8 *oob, int *cur_off, + int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &nand->ecc; @@ -713,7 +933,7 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, nand->cmdfunc(mtd, NAND_CMD_RNDIN, offset + mtd->writesize, -1); - sunxi_nfc_write_buf(mtd, oob + offset, len); + sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page); *cur_off = mtd->oobsize + mtd->writesize; } @@ -725,6 +945,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc = &chip->ecc; unsigned int max_bitflips = 0; int ret, i, cur_off = 0; + bool raw_mode = false; sunxi_nfc_hw_ecc_enable(mtd); @@ -736,13 +957,17 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, - &cur_off, &max_bitflips); - if (ret) + &cur_off, &max_bitflips, + !i, page); + if (ret < 0) return ret; + else if (ret) + raw_mode = true; } if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off); + sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off, + !raw_mode, page); sunxi_nfc_hw_ecc_disable(mtd); @@ -767,13 +992,14 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd, ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, - &cur_off); + &cur_off, !i, page); if (ret) return ret; } - if (oob_required) - sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, &cur_off); + if (oob_required || (chip->options & NAND_NEED_SCRAMBLING)) + sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, + &cur_off, page); sunxi_nfc_hw_ecc_disable(mtd); @@ -788,6 +1014,7 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc = &chip->ecc; unsigned int max_bitflips = 0; int ret, i, cur_off = 0; + bool raw_mode = false; sunxi_nfc_hw_ecc_enable(mtd); @@ -799,13 +1026,16 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd, ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off, &cur_off, - &max_bitflips); - if (ret) + &max_bitflips, !i, page); + if (ret < 0) return ret; + else if (ret) + raw_mode = true; } if (oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off); + sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off, + !raw_mode, page); sunxi_nfc_hw_ecc_disable(mtd); @@ -829,13 +1059,15 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd, const u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4)); ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, - oob, oob_off, &cur_off); + oob, oob_off, &cur_off, + false, page); if (ret) return ret; } - if (oob_required) - sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, &cur_off); + if (oob_required || (chip->options & NAND_NEED_SCRAMBLING)) + sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, + &cur_off, page); sunxi_nfc_hw_ecc_disable(mtd); @@ -1345,6 +1577,9 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, if (nand->bbt_options & NAND_BBT_USE_FLASH) nand->bbt_options |= NAND_BBT_NO_OOB; + if (nand->options & NAND_NEED_SCRAMBLING) + nand->options |= NAND_NO_SUBPAGE_WRITE; + ret = sunxi_nand_chip_init_timings(chip, np); if (ret) { dev_err(dev, "could not configure chip timings: %d\n", ret); -- cgit v1.1 From 12197bf21c26e23053fa6223f3a731a965542986 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Wed, 13 Jan 2016 17:34:13 +0100 Subject: mtd: atmel_nand: Do not warn on bitflips When using multi-bit ECC, it is normal for the NAND Flash driver to correct bit errors during the life of the product. Those errors will only be cleared once a threshold has been reached, and corrections can occur regularly before this. Use only dev_dbg and not dev_info to report the bitflips, to keep the system log clean when everything works correctly. Signed-off-by: Romain Izard Acked-by: Wenyou Yang Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index bddcf83..0ae6cba 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -825,7 +825,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, *(buf + byte_pos) ^= (1 << bit_pos); pos = sector_num * host->pmecc_sector_size + byte_pos; - dev_info(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", + dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", pos, bit_pos, err_byte, *(buf + byte_pos)); } else { /* Bit flip in OOB area */ @@ -835,7 +835,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, ecc[tmp] ^= (1 << bit_pos); pos = tmp + nand_chip->ecc.layout->eccpos[0]; - dev_info(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", + dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", pos, bit_pos, err_byte, ecc[tmp]); } -- cgit v1.1 From 46c135c208a3a80bd7f12dee0032bbc6d507a0d9 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 22 Jan 2016 18:57:13 -0800 Subject: mtd: nand: sunxi: use mtd_div_by_ws() helper Suggested-by: Richard Weinberger Signed-off-by: Brian Norris Acked-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 5f70071..b5ea6b3 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -624,7 +624,7 @@ static u16 sunxi_nfc_randomizer_step(u16 state, int count) static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc) { const u16 *seeds = sunxi_nfc_randomizer_page_seeds; - int mod = mtd->erasesize / mtd->writesize; + int mod = mtd_div_by_ws(mtd->erasesize, mtd); if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds)) mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds); -- cgit v1.1 From 54ca3cd594db58d65b3670f2af452c1104b09ac6 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 14 Jan 2016 15:44:49 +0100 Subject: mtd: nand: remove EXPORT_SYMBOL of nand_scan_bbt() Since commit 17799359e7b3fa6ef4f2bf926cd6821cf7903ecf ("mtd: nand_bbt: make nand_scan_bbt() static"), the nand_scan_bbt() function is marked as static but is still exported using EXPORT_SYMBOL(), which doesn't make much sense. This commit gets rid of the useless EXPORT_SYMBOL. Signed-off-by: Thomas Petazzoni Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_bbt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 4b6a708..2fbb523 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -1373,5 +1373,3 @@ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs) return ret; } - -EXPORT_SYMBOL(nand_scan_bbt); -- cgit v1.1 From fd2a2f20c7a8173acd4858e5178eb40fd7c025b9 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 14 Jan 2016 15:44:50 +0100 Subject: mtd: onenand: make onenand_scan_bbt() static Like was done in commit 17799359e7b3fa6ef4f2bf926cd6821cf7903ecf ("mtd: nand_bbt: make nand_scan_bbt() static") for the NAND code, this commit makes the onenand_scan_bbt() function static in the OneNAND code, since it is only used in onenand_bbt.c itself. Consequently, the EXPORT_SYMBOL() and declaration in bbm.h are also removed. Signed-off-by: Thomas Petazzoni Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/onenand/onenand_bbt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 08d0085..5f8d470 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -179,7 +179,7 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) * by the onenand_release function. * */ -int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) +static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) { struct onenand_chip *this = mtd->priv; struct bbm_info *bbm = this->bbm; @@ -248,5 +248,4 @@ int onenand_default_bbt(struct mtd_info *mtd) return onenand_scan_bbt(mtd, bbm->badblock_pattern); } -EXPORT_SYMBOL(onenand_scan_bbt); EXPORT_SYMBOL(onenand_default_bbt); -- cgit v1.1 From d652436102b1580d8d968a2047decbb737cc4e6d Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 14 Jan 2016 15:44:51 +0100 Subject: mtd: onenand: unexport onenand_default_bbt() The onenand_default_bbt() function is only used by the OneNAND core and not by drivers, so there is no real need to export it. Additionally, the corresponding nand_default_bbt() for regular NANDs is not exported either, so for consistency reasons, this commit removes the EXPORT_SYMBOL on onenand_default_bbt(). Signed-off-by: Thomas Petazzoni Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/onenand/onenand_bbt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 5f8d470..680188a 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -247,5 +247,3 @@ int onenand_default_bbt(struct mtd_info *mtd) return onenand_scan_bbt(mtd, bbm->badblock_pattern); } - -EXPORT_SYMBOL(onenand_default_bbt); -- cgit v1.1 From 2a36a5c30eab9cd1c9d2d08bd27cd763325d70c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 5 Dec 2015 02:09:43 +0100 Subject: mtd: bcm47xxpart: limit scanned flash area on BCM47XX (MIPS) only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We allowed using bcm47xxpart on BCM5301X arch with commit: 9e3afa5f5c7 ("mtd: bcm47xxpart: allow enabling on ARCH_BCM_5301X") BCM5301X devices may contain some partitions in higher memory, e.g. Netgear R8000 has board_data at 0x2600000. To detect them we should use size limit on MIPS only. Signed-off-by: Rafał Miłecki Signed-off-by: Brian Norris --- drivers/mtd/bcm47xxpart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index 8282f47..b06d4c4 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c @@ -118,8 +118,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, /* Parse block by block looking for magics */ for (offset = 0; offset <= master->size - blocksize; offset += blocksize) { - /* Nothing more in higher memory */ - if (offset >= 0x2000000) + /* Nothing more in higher memory on BCM47XX (MIPS) */ + if (config_enabled(CONFIG_BCM47XX) && offset >= 0x2000000) break; if (curr_part >= BCM47XXPART_MAX_PARTS) { -- cgit v1.1 From 36bcc0c9c2bc8f56569cd735ba531a51358d7c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 6 Dec 2015 11:31:38 +0100 Subject: mtd: bcm47xxpart: don't fail because of bit-flips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bit-flip errors may occur on NAND flashes and are harmless. Handle them gracefully as read content is still reliable and can be parsed. Signed-off-by: Rafał Miłecki Signed-off-by: Brian Norris --- drivers/mtd/bcm47xxpart.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index b06d4c4..845dd27 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c @@ -66,11 +66,13 @@ static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, { uint32_t buf; size_t bytes_read; + int err; - if (mtd_read(master, offset, sizeof(buf), &bytes_read, - (uint8_t *)&buf) < 0) { - pr_err("mtd_read error while parsing (offset: 0x%X)!\n", - offset); + err = mtd_read(master, offset, sizeof(buf), &bytes_read, + (uint8_t *)&buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", + offset, err); goto out_default; } @@ -95,6 +97,7 @@ static int bcm47xxpart_parse(struct mtd_info *master, int trx_part = -1; int last_trx_part = -1; int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; + int err; /* * Some really old flashes (like AT45DB*) had smaller erasesize-s, but @@ -128,10 +131,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } /* Read beginning of the block */ - if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, - &bytes_read, (uint8_t *)buf) < 0) { - pr_err("mtd_read error while parsing (offset: 0x%X)!\n", - offset); + err = mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, + &bytes_read, (uint8_t *)buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", + offset, err); continue; } @@ -254,10 +258,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } /* Read middle of the block */ - if (mtd_read(master, offset + 0x8000, 0x4, - &bytes_read, (uint8_t *)buf) < 0) { - pr_err("mtd_read error while parsing (offset: 0x%X)!\n", - offset); + err = mtd_read(master, offset + 0x8000, 0x4, &bytes_read, + (uint8_t *)buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", + offset, err); continue; } @@ -277,10 +282,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } offset = master->size - possible_nvram_sizes[i]; - if (mtd_read(master, offset, 0x4, &bytes_read, - (uint8_t *)buf) < 0) { - pr_err("mtd_read error while reading at offset 0x%X!\n", - offset); + err = mtd_read(master, offset, 0x4, &bytes_read, + (uint8_t *)buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while reading (offset 0x%X): %d\n", + offset, err); continue; } -- cgit v1.1 From 026918e71111afe88382f8d800a852d3e36bf3d4 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 2 Dec 2015 16:47:40 -0600 Subject: mtd: nand: gpmi: add gpmi dsm supend/resume support i.MX6SX supports deep sleep mode(DSM) that may turn off GPMI/BCH power during suspend, add gpmi nand suspend/resume function to release DMA channel in suspend function and re-init GPMI/BCH controller during resume function. Although it is not necessary to restore GPMI/BCH registers value for i.MX6QDL, the code doesn't distinguish different platforms to keep the code simple. Signed-off-by: Huang Shijie Signed-off-by: Han Xu Signed-off-by: Brian Norris --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 47 +++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 235ddcb..9c311b0 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -1,7 +1,7 @@ /* * Freescale GPMI NAND Flash Driver * - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. * Copyright (C) 2008 Embedded Alley Solutions, Inc. * * This program is free software; you can redistribute it and/or modify @@ -2033,9 +2033,54 @@ static int gpmi_nand_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int gpmi_pm_suspend(struct device *dev) +{ + struct gpmi_nand_data *this = dev_get_drvdata(dev); + + release_dma_channels(this); + return 0; +} + +static int gpmi_pm_resume(struct device *dev) +{ + struct gpmi_nand_data *this = dev_get_drvdata(dev); + int ret; + + ret = acquire_dma_channels(this); + if (ret < 0) + return ret; + + /* re-init the GPMI registers */ + this->flags &= ~GPMI_TIMING_INIT_OK; + ret = gpmi_init(this); + if (ret) { + dev_err(this->dev, "Error setting GPMI : %d\n", ret); + return ret; + } + + /* re-init the BCH registers */ + ret = bch_set_geometry(this); + if (ret) { + dev_err(this->dev, "Error setting BCH : %d\n", ret); + return ret; + } + + /* re-init others */ + gpmi_extra_init(this); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops gpmi_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(gpmi_pm_suspend, gpmi_pm_resume) +}; + static struct platform_driver gpmi_nand_driver = { .driver = { .name = "gpmi-nand", + .pm = &gpmi_pm_ops, .of_match_table = gpmi_nand_id_table, }, .probe = gpmi_nand_probe, -- cgit v1.1 From b8b0e465ddb0c9cb16089ddfed68a8569e006465 Mon Sep 17 00:00:00 2001 From: Han Xu Date: Wed, 2 Dec 2015 16:47:43 -0600 Subject: mtd: nand: gpmi: may use minimum required ecc for 744 oobsize NAND By default NAND driver will choose the highest ecc strength that oob could contain, in this case, for some 8K+744 NAND flash, the ecc strength will be up to 52bit, which beyonds the i.MX6QDL BCH capability (40bit). This patch allows the NAND driver try to use minimum required ecc strength if it failed to use the highest ecc, even without explicitly claiming "fsl,use-minimum-ecc" in dts. Signed-off-by: Han Xu Acked-by: Huang Shijie Signed-off-by: Brian Norris --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 9c311b0..8122c69 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -136,7 +136,7 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this) * * We may have available oob space in this case. */ -static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) +static int set_geometry_by_ecc_info(struct gpmi_nand_data *this) { struct bch_geometry *geo = &this->bch_geometry; struct nand_chip *chip = &this->nand; @@ -145,7 +145,7 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) unsigned int block_mark_bit_offset; if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) - return false; + return -EINVAL; switch (chip->ecc_step_ds) { case SZ_512: @@ -158,19 +158,19 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) dev_err(this->dev, "unsupported nand chip. ecc bits : %d, ecc size : %d\n", chip->ecc_strength_ds, chip->ecc_step_ds); - return false; + return -EINVAL; } geo->ecc_chunk_size = chip->ecc_step_ds; geo->ecc_strength = round_up(chip->ecc_strength_ds, 2); if (!gpmi_check_ecc(this)) - return false; + return -EINVAL; /* Keep the C >= O */ if (geo->ecc_chunk_size < mtd->oobsize) { dev_err(this->dev, "unsupported nand chip. ecc size: %d, oob size : %d\n", chip->ecc_step_ds, mtd->oobsize); - return false; + return -EINVAL; } /* The default value, see comment in the legacy_set_geometry(). */ @@ -242,7 +242,7 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) + ALIGN(geo->ecc_chunk_count, 4); if (!this->swap_block_mark) - return true; + return 0; /* For bit swap. */ block_mark_bit_offset = mtd->writesize * 8 - @@ -251,7 +251,7 @@ static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) geo->block_mark_byte_offset = block_mark_bit_offset / 8; geo->block_mark_bit_offset = block_mark_bit_offset % 8; - return true; + return 0; } static int legacy_set_geometry(struct gpmi_nand_data *this) @@ -285,7 +285,8 @@ static int legacy_set_geometry(struct gpmi_nand_data *this) geo->ecc_strength = get_ecc_strength(this); if (!gpmi_check_ecc(this)) { dev_err(this->dev, - "required ecc strength of the NAND chip: %d is not supported by the GPMI controller (%d)\n", + "ecc strength: %d cannot be supported by the controller (%d)\n" + "try to use minimum ecc strength that NAND chip required\n", geo->ecc_strength, this->devdata->bch_max_ecc_strength); return -EINVAL; @@ -366,10 +367,11 @@ static int legacy_set_geometry(struct gpmi_nand_data *this) int common_nfc_set_geometry(struct gpmi_nand_data *this) { - if (of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc") - && set_geometry_by_ecc_info(this)) - return 0; - return legacy_set_geometry(this); + if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc")) + || legacy_set_geometry(this)) + return set_geometry_by_ecc_info(this); + + return 0; } struct dma_chan *get_dma_chan(struct gpmi_nand_data *this) -- cgit v1.1 From e88b7f7d6ca47531af602cfb6abdb31ea13eabc3 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Fri, 15 Jan 2016 11:34:56 +0100 Subject: mtd: atmel_nand: Simplify error messages The error messages when the ECC controller is misconfigured through the device tree are very precise. As a result they can (and will) get obsolete when new revisions of the controller appear. Simplify them before adding the support for the new revision. Signed-off-by: Romain Izard Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 0ae6cba..ad9f4b0 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1550,7 +1550,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host, if ((val != 2) && (val != 4) && (val != 8) && (val != 12) && (val != 24)) { dev_err(host->dev, - "Unsupported PMECC correction capability: %d; should be 2, 4, 8, 12 or 24\n", + "Required ECC strength not supported: %u\n", val); return -EINVAL; } @@ -1560,7 +1560,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host, if (of_property_read_u32(np, "atmel,pmecc-sector-size", &val) == 0) { if ((val != 512) && (val != 1024)) { dev_err(host->dev, - "Unsupported PMECC sector size: %d; should be 512 or 1024 bytes\n", + "Required ECC sector size not supported: %u\n", val); return -EINVAL; } -- cgit v1.1 From 8ce06d379a06b4d5c9f944bb60e80b084d16bfc0 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Fri, 15 Jan 2016 11:34:57 +0100 Subject: mtd: atmel_nand: Use of_device_get_match_data Remove the need for forward declaration and the risk for a null pointer when accessing the private part of the compatible match table, by using the newly introduced of_device_get_match_data function. Signed-off-by: Romain Izard Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index ad9f4b0..affe7a7 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1486,8 +1486,6 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) ecc_writel(host->ecc, CR, ATMEL_ECC_RST); } -static const struct of_device_id atmel_nand_dt_ids[]; - static int atmel_of_init_port(struct atmel_nand_host *host, struct device_node *np) { @@ -1498,7 +1496,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host, enum of_gpio_flags flags = 0; host->caps = (struct atmel_nand_caps *) - of_match_device(atmel_nand_dt_ids, host->dev)->data; + of_device_get_match_data(host->dev); if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { if (val >= 32) { -- cgit v1.1 From 8fce60b8d0c62363c29d64efb0cceb98519f0350 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 13 Dec 2015 22:46:59 +0000 Subject: MIPS: bcm963xx: Move Broadcom BCM963xx image tag data structure Move Broadcom BCM963xx image tag data structure to include/linux/ so that drivers outside of mach-bcm63xx can use it. Signed-off-by: Simon Arlott Cc: David Woodhouse Cc: Brian Norris Cc: Kevin Cernekee Cc: Florian Fainelli Cc: Jonas Gorski Cc: Linux Kernel Mailing List Cc: MIPS Mailing List Cc: MTD Maling List Patchwork: https://patchwork.linux-mips.org/patch/11832/ Signed-off-by: Ralf Baechle --- drivers/mtd/bcm63xxpart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index b2443f7..8b86ed6 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -24,6 +24,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -34,7 +35,6 @@ #include #include -#include #include #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ -- cgit v1.1 From 1f29cb19cb7c3bea870d7da02ec23823af9d636e Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 13 Dec 2015 22:47:55 +0000 Subject: MIPS: bcm963xx: Move extended flash address to bcm_tag header file The extended flash address needs to be subtracted from bcm_tag flash image offsets. Move this value to the bcm_tag header file. Renamed define name to consistently use bcm963xx for flash layout which should be considered a property of the board and not the SoC (i.e. bcm63xx could theoretically be used on a board without CFE or any flash). Signed-off-by: Simon Arlott Cc: David Woodhouse Cc: Brian Norris Cc: Kevin Cernekee Cc: Florian Fainelli Cc: Jonas Gorski Cc: Linux Kernel Mailing List Cc: MIPS Mailing List Cc: MTD Maling List Patchwork: https://patchwork.linux-mips.org/patch/11833/ Signed-off-by: Ralf Baechle --- drivers/mtd/bcm63xxpart.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index 8b86ed6..0aa66c3 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -37,8 +37,6 @@ #include #include -#define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ - #define BCM63XX_CFE_BLOCK_SIZE SZ_64K /* always at least 64KiB */ #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0 @@ -123,8 +121,8 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, pr_info("CFE boot tag found with version %s and board type %s\n", tagversion, boardid); - kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; - rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE; + kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE; + rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE; spareaddr = roundup(totallen, master->erasesize) + cfelen; if (rootfsaddr < kerneladdr) { -- cgit v1.1 From f88f44cbf10cf5bd42d6e46ea6625d9bfa5f155d Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:25:59 +0100 Subject: mtd: nand: s3c2410: kill the ->ecc_layout field The s3c2410 is allowing board data to overload the default ECC layout defined inside the driver, but this feature is not used by board specific definitions. Kill this field so that we can easily move to a model where ecclayout are dynamically allocated by the NAND controller driver. Signed-off-by: Boris Brezillon Acked-by: Krzysztof Kozlowski Signed-off-by: Brian Norris --- drivers/mtd/nand/s3c2410.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 01ac74f..9c9397b 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -861,9 +861,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->ecc.mode = NAND_ECC_SOFT; #endif - if (set->ecc_layout != NULL) - chip->ecc.layout = set->ecc_layout; - if (set->disable_ecc) chip->ecc.mode = NAND_ECC_NONE; -- cgit v1.1 From d5e83ea7dc510fe8e7b4a54e5a93f3dd760f6d7e Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:26:00 +0100 Subject: mtd: nand: jz4740: kill the ->ecc_layout field ->ecc_layout is not used by any board file. Kill this field to avoid any confusion. New boards are encouraged to use the default ECC layout defined in NAND core. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/jz4740_nand.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index b19d2a9..673ceb2 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -427,9 +427,6 @@ static int jz_nand_probe(struct platform_device *pdev) chip->ecc.strength = 4; chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; - if (pdata) - chip->ecc.layout = pdata->ecc_layout; - chip->chip_delay = 50; chip->cmd_ctrl = jz_nand_cmd_ctrl; chip->select_chip = jz_nand_select_chip; -- cgit v1.1 From 02db97a9de1c80bd5551ba46d901cb4d912f78f2 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:26:01 +0100 Subject: mtd: nand: kill unused ->ecclayout field in platform_nand_chip struct This field is not set in any board file and can thus be dropped. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/plat_nand.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index a0e26de..e4e50da 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -73,7 +73,6 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.bbt_options |= pdata->chip.bbt_options; data->chip.ecc.hwctl = pdata->ctrl.hwcontrol; - data->chip.ecc.layout = pdata->chip.ecclayout; data->chip.ecc.mode = NAND_ECC_SOFT; platform_set_drvdata(pdev, data); -- cgit v1.1 From f771749e3a4905e631dafa073543ef429c7cc855 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:26:03 +0100 Subject: mtd: nand: lpc32xx_mlc: fix ecc.size According to the ECC layout description the actual ecc.size is 512 bytes and not mtd->writesize. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/lpc32xx_mlc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index 9bc435d..d8c3e7a 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -750,7 +750,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) } nand_chip->ecc.mode = NAND_ECC_HW; - nand_chip->ecc.size = mtd->writesize; + nand_chip->ecc.size = 512; nand_chip->ecc.layout = &lpc32xx_nand_oob; host->mlcsubpages = mtd->writesize / 512; -- cgit v1.1 From 420b4629b5b9d08893c459b55a7a266caa734ebd Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Dec 2015 23:26:04 +0100 Subject: mtd: nand: vf610: remove useless mtd->ecclayout assignment The NAND core layer is already taking care of ecclayout propagation. Remove this useless assignment. Signed-off-by: Boris Brezillon Acked-by: Stefan Agner Signed-off-by: Brian Norris --- drivers/mtd/nand/vf610_nfc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 034420f..293feb1 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -795,8 +795,6 @@ static int vf610_nfc_probe(struct platform_device *pdev) goto error; } - /* propagate ecc.layout to mtd_info */ - mtd->ecclayout = chip->ecc.layout; chip->ecc.read_page = vf610_nfc_read_page; chip->ecc.write_page = vf610_nfc_write_page; -- cgit v1.1 From 15c0be7bec002f9a529dd0966d0db96dde176fd0 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:10 +0100 Subject: mtd: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Acked-by: Geert Uytterhoeven Signed-off-by: Brian Norris --- drivers/mtd/nand/Kconfig | 2 ++ drivers/mtd/spi-nor/Kconfig | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 20f01b3..545d82b 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -74,6 +74,7 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR config MTD_NAND_GPIO tristate "GPIO assisted NAND Flash driver" depends on GPIOLIB || COMPILE_TEST + depends on HAS_IOMEM help This enables a NAND flash driver where control signals are connected to GPIO pins, and commands and data are communicated @@ -463,6 +464,7 @@ config MTD_NAND_MPC5121_NFC config MTD_NAND_VF610_NFC tristate "Support for Freescale NFC for VF610/MPC5125" depends on (SOC_VF610 || COMPILE_TEST) + depends on HAS_IOMEM help Enables support for NAND Flash Controller on some Freescale processors like the VF610, MPC5125, MCF54418 or Kinetis K70. diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index 0dc9275..83befab 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -9,6 +9,7 @@ if MTD_SPI_NOR config MTD_MT81xx_NOR tristate "Mediatek MT81xx SPI NOR flash controller" + depends on HAS_IOMEM help This enables access to SPI NOR flash, using MT81xx SPI NOR flash controller. This controller does not support generic SPI BUS, it only -- cgit v1.1 From 02c3b0bd69a537557484e46a5937874a2d2ad454 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:20 +0100 Subject: mtd: cs553x: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory nor can this driver ever work on UML/i386. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Signed-off-by: Brian Norris --- drivers/mtd/nand/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 545d82b..b253654 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -311,6 +311,7 @@ config MTD_NAND_CAFE config MTD_NAND_CS553X tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" depends on X86_32 + depends on !UML && HAS_IOMEM help The CS553x companion chips for the AMD Geode processor include NAND flash controllers with built-in hardware ECC -- cgit v1.1 From 26d072e36c732e6fe7eebdceb5e0497ddf256ded Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 25 Jan 2016 21:29:45 +0100 Subject: mtd: nand: pxa3xx_nand: add register access debug Add verbose debug for register accesses. This enables easier debugging by following where and how hardware is stimulated, and how it answers. Signed-off-by: Robert Jarzmik Acked-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 86fc245..e42496a 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -131,11 +131,23 @@ #define READ_ID_BYTES 7 /* macros for registers read/write */ -#define nand_writel(info, off, val) \ - writel_relaxed((val), (info)->mmio_base + (off)) - -#define nand_readl(info, off) \ - readl_relaxed((info)->mmio_base + (off)) +#define nand_writel(info, off, val) \ + do { \ + dev_vdbg(&info->pdev->dev, \ + "%s():%d nand_writel(0x%x, 0x%04x)\n", \ + __func__, __LINE__, (val), (off)); \ + writel_relaxed((val), (info)->mmio_base + (off)); \ + } while (0) + +#define nand_readl(info, off) \ + ({ \ + unsigned int _v; \ + _v = readl_relaxed((info)->mmio_base + (off)); \ + dev_vdbg(&info->pdev->dev, \ + "%s():%d nand_readl(0x%04x) = 0x%x\n", \ + __func__, __LINE__, (off), _v); \ + _v; \ + }) /* error code and state */ enum { -- cgit v1.1 From 5ddc7bd43ccc77173f149483fa27a0b8f85e09e5 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Wed, 10 Feb 2016 10:56:23 +0100 Subject: mtd: atmel_nand: Support variable RB_EDGE interrupts The NFC controller used to accelerate the NAND transfers on SAMA5 chips can use either RB_EDGE0 or RB_EDGE3 as its ready/busy interrupt bit. Use the controller's compatible string to select the correct bit. For the binding: Acked-by: Rob Herring Reviewed-by: Wenyou Yang Tested-by: Wenyou Yang Reviewed-by: Boris Brezillon Signed-off-by: Romain Izard Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 35 +++++++++++++++++++++++++++-------- drivers/mtd/nand/atmel_nand_nfc.h | 3 ++- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index affe7a7..06a3e11 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -67,6 +67,10 @@ struct atmel_nand_caps { bool pmecc_correct_erase_page; }; +struct atmel_nand_nfc_caps { + uint32_t rb_mask; +}; + /* oob layout for large page size * bad block info is on bytes 0 and 1 * the bytes have to be consecutives to avoid @@ -111,6 +115,7 @@ struct atmel_nfc { /* Point to the sram bank which include readed data via NFC */ void *data_in_sram; bool will_write_sram; + const struct atmel_nand_nfc_caps *caps; }; static struct atmel_nfc nand_nfc; @@ -1675,9 +1680,9 @@ static irqreturn_t hsmc_interrupt(int irq, void *dev_id) nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE); ret = IRQ_HANDLED; } - if (pending & NFC_SR_RB_EDGE) { + if (pending & host->nfc->caps->rb_mask) { complete(&host->nfc->comp_ready); - nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE); + nfc_writel(host->nfc->hsmc_regs, IDR, host->nfc->caps->rb_mask); ret = IRQ_HANDLED; } if (pending & NFC_SR_CMD_DONE) { @@ -1695,7 +1700,7 @@ static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag) if (flag & NFC_SR_XFR_DONE) init_completion(&host->nfc->comp_xfer_done); - if (flag & NFC_SR_RB_EDGE) + if (flag & host->nfc->caps->rb_mask) init_completion(&host->nfc->comp_ready); if (flag & NFC_SR_CMD_DONE) @@ -1713,7 +1718,7 @@ static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag) if (flag & NFC_SR_XFR_DONE) comp[index++] = &host->nfc->comp_xfer_done; - if (flag & NFC_SR_RB_EDGE) + if (flag & host->nfc->caps->rb_mask) comp[index++] = &host->nfc->comp_ready; if (flag & NFC_SR_CMD_DONE) @@ -1781,7 +1786,7 @@ static int nfc_device_ready(struct mtd_info *mtd) dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n", mask & status); - return status & NFC_SR_RB_EDGE; + return status & host->nfc->caps->rb_mask; } static void nfc_select_chip(struct mtd_info *mtd, int chip) @@ -1954,8 +1959,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command, } /* fall through */ default: - nfc_prepare_interrupt(host, NFC_SR_RB_EDGE); - nfc_wait_interrupt(host, NFC_SR_RB_EDGE); + nfc_prepare_interrupt(host, host->nfc->caps->rb_mask); + nfc_wait_interrupt(host, host->nfc->caps->rb_mask); } } @@ -2352,6 +2357,11 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev) } } + nfc->caps = (const struct atmel_nand_nfc_caps *) + of_device_get_match_data(&pdev->dev); + if (!nfc->caps) + return -ENODEV; + nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff); nfc_readl(nfc->hsmc_regs, SR); /* clear the NFC_SR */ @@ -2380,8 +2390,17 @@ static int atmel_nand_nfc_remove(struct platform_device *pdev) return 0; } +static const struct atmel_nand_nfc_caps sama5d3_nfc_caps = { + .rb_mask = NFC_SR_RB_EDGE0, +}; + +static const struct atmel_nand_nfc_caps sama5d4_nfc_caps = { + .rb_mask = NFC_SR_RB_EDGE3, +}; + static const struct of_device_id atmel_nand_nfc_match[] = { - { .compatible = "atmel,sama5d3-nfc" }, + { .compatible = "atmel,sama5d3-nfc", .data = &sama5d3_nfc_caps }, + { .compatible = "atmel,sama5d4-nfc", .data = &sama5d4_nfc_caps }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match); diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h index 4d5d262..0bbc1fa 100644 --- a/drivers/mtd/nand/atmel_nand_nfc.h +++ b/drivers/mtd/nand/atmel_nand_nfc.h @@ -42,7 +42,8 @@ #define NFC_SR_UNDEF (1 << 21) #define NFC_SR_AWB (1 << 22) #define NFC_SR_ASE (1 << 23) -#define NFC_SR_RB_EDGE (1 << 24) +#define NFC_SR_RB_EDGE0 (1 << 24) +#define NFC_SR_RB_EDGE3 (1 << 27) #define ATMEL_HSMC_NFC_IER 0x0c #define ATMEL_HSMC_NFC_IDR 0x10 -- cgit v1.1 From 5575075612cadd504dd8c8e1b8c66fa5d48b7042 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Wed, 10 Feb 2016 10:56:25 +0100 Subject: mtd: atmel_nand: Support PMECC on SAMA5D2 Starting with the SAMA5D2, there is a new revision of the Atmel PMECC controller that can correct 32 bits in each sector. This controller is not 100% compatible with the previous revision that corrected a maximum of 24 bits by sector, as some register addresses overlap. Using information from the device tree, we can configure the driver to work with both versions. For the binding: Acked-by: Rob Herring Tested-by: Wenyou Yang Reviewed-by: Boris Brezillon Signed-off-by: Romain Izard Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 23 ++++++++++++++++++++++- drivers/mtd/nand/atmel_nand_ecc.h | 8 ++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 06a3e11..d883279 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -65,6 +65,7 @@ module_param(on_flash_bbt, int, 0); struct atmel_nand_caps { bool pmecc_correct_erase_page; + uint8_t pmecc_max_correction; }; struct atmel_nand_nfc_caps { @@ -145,6 +146,7 @@ struct atmel_nand_host { int pmecc_cw_len; /* Length of codeword */ void __iomem *pmerrloc_base; + void __iomem *pmerrloc_el_base; void __iomem *pmecc_rom_base; /* lookup table for alpha_to and index_of */ @@ -818,7 +820,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, sector_size = host->pmecc_sector_size; while (err_nbr) { - tmp = pmerrloc_readl_el_relaxed(host->pmerrloc_base, i) - 1; + tmp = pmerrloc_readl_el_relaxed(host->pmerrloc_el_base, i) - 1; byte_pos = tmp / 8; bit_pos = tmp % 8; @@ -1210,6 +1212,8 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, err_no = PTR_ERR(host->pmerrloc_base); goto err; } + host->pmerrloc_el_base = host->pmerrloc_base + ATMEL_PMERRLOC_SIGMAx + + (host->caps->pmecc_max_correction + 1) * 4; if (!host->has_no_lookup_table) { regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3); @@ -2307,17 +2311,34 @@ static int atmel_nand_remove(struct platform_device *pdev) return 0; } +/* + * AT91RM9200 does not have PMECC or PMECC Errloc peripherals for + * BCH ECC. Combined with the "atmel,has-pmecc", it is used to describe + * devices from the SAM9 family that have those. + */ static const struct atmel_nand_caps at91rm9200_caps = { .pmecc_correct_erase_page = false, + .pmecc_max_correction = 24, }; static const struct atmel_nand_caps sama5d4_caps = { .pmecc_correct_erase_page = true, + .pmecc_max_correction = 24, +}; + +/* + * The PMECC Errloc controller starting in SAMA5D2 is not compatible, + * as the increased correction strength requires more registers. + */ +static const struct atmel_nand_caps sama5d2_caps = { + .pmecc_correct_erase_page = true, + .pmecc_max_correction = 32, }; static const struct of_device_id atmel_nand_dt_ids[] = { { .compatible = "atmel,at91rm9200-nand", .data = &at91rm9200_caps }, { .compatible = "atmel,sama5d4-nand", .data = &sama5d4_caps }, + { .compatible = "atmel,sama5d2-nand", .data = &sama5d2_caps }, { /* sentinel */ } }; diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h index 668e735..ec964c4 100644 --- a/drivers/mtd/nand/atmel_nand_ecc.h +++ b/drivers/mtd/nand/atmel_nand_ecc.h @@ -108,7 +108,11 @@ #define PMERRLOC_ERR_NUM_MASK (0x1f << 8) #define PMERRLOC_CALC_DONE (1 << 0) #define ATMEL_PMERRLOC_SIGMAx 0x028 /* Error location SIGMA x */ -#define ATMEL_PMERRLOC_ELx 0x08c /* Error location x */ + +/* + * The ATMEL_PMERRLOC_ELx register location depends from the number of + * bits corrected by the PMECC controller. Do not use it. + */ /* Register access macros for PMECC */ #define pmecc_readl_relaxed(addr, reg) \ @@ -136,7 +140,7 @@ readl_relaxed((addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4)) #define pmerrloc_readl_el_relaxed(addr, n) \ - readl_relaxed((addr) + ATMEL_PMERRLOC_ELx + ((n) * 4)) + readl_relaxed((addr) + ((n) * 4)) /* Galois field dimension */ #define PMECC_GF_DIMENSION_13 13 -- cgit v1.1 From 94248462f066ec19b9c184ff66300e6e71977609 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Wed, 10 Feb 2016 10:56:26 +0100 Subject: mtd: atmel_nand: Support 32-bit ECC strength As the SAMA5D2 controller supports the 32-bit ECC strength, accept it as a valid setting when required by the device tree or the NAND parameter page. Then configure the controller to use this new setting. For the binding: Acked-by: Rob Herring Signed-off-by: Romain Izard Tested-by: Wenyou Yang Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/atmel_nand.c | 19 +++++++++++++++++-- drivers/mtd/nand/atmel_nand_ecc.h | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index d883279..20cbaab 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -475,6 +475,7 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) * 8-bits 13-bytes 14-bytes * 12-bits 20-bytes 21-bytes * 24-bits 39-bytes 42-bytes + * 32-bits 52-bytes 56-bytes */ static int pmecc_get_ecc_bytes(int cap, int sector_size) { @@ -1024,6 +1025,9 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd) case 24: val = PMECC_CFG_BCH_ERR24; break; + case 32: + val = PMECC_CFG_BCH_ERR32; + break; } if (host->pmecc_sector_size == 512) @@ -1085,6 +1089,9 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host, /* If device tree doesn't specify, use NAND's minimum ECC parameters */ if (host->pmecc_corr_cap == 0) { + if (*cap > host->caps->pmecc_max_correction) + return -EINVAL; + /* use the most fitable ecc bits (the near bigger one ) */ if (*cap <= 2) host->pmecc_corr_cap = 2; @@ -1096,6 +1103,8 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host, host->pmecc_corr_cap = 12; else if (*cap <= 24) host->pmecc_corr_cap = 24; + else if (*cap <= 32) + host->pmecc_corr_cap = 32; else return -EINVAL; } @@ -1554,8 +1563,14 @@ static int atmel_of_init_port(struct atmel_nand_host *host, * them from NAND ONFI parameters. */ if (of_property_read_u32(np, "atmel,pmecc-cap", &val) == 0) { - if ((val != 2) && (val != 4) && (val != 8) && (val != 12) && - (val != 24)) { + if (val > host->caps->pmecc_max_correction) { + dev_err(host->dev, + "Required ECC strength too high: %u max %u\n", + val, host->caps->pmecc_max_correction); + return -EINVAL; + } + if ((val != 2) && (val != 4) && (val != 8) && + (val != 12) && (val != 24) && (val != 32)) { dev_err(host->dev, "Required ECC strength not supported: %u\n", val); diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h index ec964c4..834d694 100644 --- a/drivers/mtd/nand/atmel_nand_ecc.h +++ b/drivers/mtd/nand/atmel_nand_ecc.h @@ -43,6 +43,7 @@ #define PMECC_CFG_BCH_ERR8 (2 << 0) #define PMECC_CFG_BCH_ERR12 (3 << 0) #define PMECC_CFG_BCH_ERR24 (4 << 0) +#define PMECC_CFG_BCH_ERR32 (5 << 0) #define PMECC_CFG_SECTOR512 (0 << 4) #define PMECC_CFG_SECTOR1024 (1 << 4) -- cgit v1.1 From 436e94a6fbcdca133a2546769db4ac0a84265ad1 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 13 Dec 2015 22:49:26 +0000 Subject: mtd: bcm63xxpart: Remove dependency on mach-bcm63xx Read nvram directly from flash instead of using the in-memory copy that mach-bcm63xx has, to remove the dependency on mach-bcm63xx and allow the parser to work on bmips too. Rename remaining BCM63XX defines to BCM963XX as these are properties of the flash layout on the board. BCM963XX_DEFAULT_PSI_SIZE changes from SZ_64K to 64 because it will be multiplied by SZ_1K later on. Signed-off-by: Simon Arlott Signed-off-by: Brian Norris --- drivers/mtd/Kconfig | 2 +- drivers/mtd/bcm63xxpart.c | 72 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 16 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 42cc953..e83a279 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -142,7 +142,7 @@ config MTD_AR7_PARTS config MTD_BCM63XX_PARTS tristate "BCM63XX CFE partitioning support" - depends on BCM63XX + depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST select CRC32 help This provides partions parsing for BCM63xx devices with CFE diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index cec3188..1eea8b6 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -24,6 +24,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -34,12 +35,11 @@ #include #include -#include -#include +#define BCM963XX_CFE_BLOCK_SIZE SZ_64K /* always at least 64KiB */ -#define BCM63XX_CFE_BLOCK_SIZE SZ_64K /* always at least 64KiB */ - -#define BCM63XX_CFE_MAGIC_OFFSET 0x4e0 +#define BCM963XX_CFE_MAGIC_OFFSET 0x4e0 +#define BCM963XX_CFE_VERSION_OFFSET 0x570 +#define BCM963XX_NVRAM_OFFSET 0x580 static int bcm63xx_detect_cfe(struct mtd_info *master) { @@ -58,20 +58,45 @@ static int bcm63xx_detect_cfe(struct mtd_info *master) return 0; /* very old CFE's do not have the cfe-v string, so check for magic */ - ret = mtd_read(master, BCM63XX_CFE_MAGIC_OFFSET, 8, &retlen, + ret = mtd_read(master, BCM963XX_CFE_MAGIC_OFFSET, 8, &retlen, (void *)buf); buf[retlen] = 0; return strncmp("CFE1CFE1", buf, 8); } +static int bcm63xx_read_nvram(struct mtd_info *master, + struct bcm963xx_nvram *nvram) +{ + u32 actual_crc, expected_crc; + size_t retlen; + int ret; + + /* extract nvram data */ + ret = mtd_read(master, BCM963XX_NVRAM_OFFSET, BCM963XX_NVRAM_V5_SIZE, + &retlen, (void *)nvram); + if (ret) + return ret; + + ret = bcm963xx_nvram_checksum(nvram, &expected_crc, &actual_crc); + if (ret) + pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n", + expected_crc, actual_crc); + + if (!nvram->psi_size) + nvram->psi_size = BCM963XX_DEFAULT_PSI_SIZE; + + return 0; +} + static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { /* CFE, NVRAM and global Linux are always present */ int nrparts = 3, curpart = 0; - struct bcm_tag *buf; + struct bcm963xx_nvram *nvram = NULL; + struct bcm_tag *buf = NULL; struct mtd_partition *parts; int ret; size_t retlen; @@ -86,25 +111,35 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, if (bcm63xx_detect_cfe(master)) return -EINVAL; + nvram = vzalloc(sizeof(*nvram)); + if (!nvram) + return -ENOMEM; + + ret = bcm63xx_read_nvram(master, nvram); + if (ret) + goto out; + cfe_erasesize = max_t(uint32_t, master->erasesize, - BCM63XX_CFE_BLOCK_SIZE); + BCM963XX_CFE_BLOCK_SIZE); cfelen = cfe_erasesize; - nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K; + nvramlen = nvram->psi_size * SZ_1K; nvramlen = roundup(nvramlen, cfe_erasesize); /* Allocate memory for buffer */ buf = vmalloc(sizeof(struct bcm_tag)); - if (!buf) - return -ENOMEM; + if (!buf) { + ret = -ENOMEM; + goto out; + } /* Get the tag */ ret = mtd_read(master, cfelen, sizeof(struct bcm_tag), &retlen, (void *)buf); if (retlen != sizeof(struct bcm_tag)) { - vfree(buf); - return -EIO; + ret = -EIO; + goto out; } computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf, @@ -154,8 +189,8 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, /* Ask kernel for more memory */ parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); if (!parts) { - vfree(buf); - return -ENOMEM; + ret = -ENOMEM; + goto out; } /* Start building partition list */ @@ -206,8 +241,15 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, sparelen); *pparts = parts; + ret = 0; + +out: + vfree(nvram); vfree(buf); + if (ret) + return ret; + return nrparts; }; -- cgit v1.1 From 7fffa694a8917af0c553ab48290a57e3674aa5d3 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 13 Dec 2015 22:51:02 +0000 Subject: mtd: bcm63xxpart: Extract read of image tag to separate function Extract image tag reading and CRC check to a separate function. Signed-off-by: Simon Arlott Signed-off-by: Brian Norris --- drivers/mtd/bcm63xxpart.c | 62 ++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 22 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index 1eea8b6..eafbf52 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -41,6 +41,10 @@ #define BCM963XX_CFE_VERSION_OFFSET 0x570 #define BCM963XX_NVRAM_OFFSET 0x580 +/* Ensure strings read from flash structs are null terminated */ +#define STR_NULL_TERMINATE(x) \ + do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0) + static int bcm63xx_detect_cfe(struct mtd_info *master) { char buf[9]; @@ -89,6 +93,37 @@ static int bcm63xx_read_nvram(struct mtd_info *master, return 0; } +static int bcm63xx_read_image_tag(struct mtd_info *master, const char *name, + loff_t tag_offset, struct bcm_tag *buf) +{ + int ret; + size_t retlen; + u32 computed_crc; + + ret = mtd_read(master, tag_offset, sizeof(*buf), &retlen, (void *)buf); + if (ret) + return ret; + + if (retlen != sizeof(*buf)) + return -EIO; + + computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf, + offsetof(struct bcm_tag, header_crc)); + if (computed_crc == buf->header_crc) { + STR_NULL_TERMINATE(buf->board_id); + STR_NULL_TERMINATE(buf->tag_version); + + pr_info("%s: CFE image tag found at 0x%llx with version %s, board type %s\n", + name, tag_offset, buf->tag_version, buf->board_id); + + return 0; + } + + pr_warn("%s: CFE image tag at 0x%llx CRC invalid (expected %08x, actual %08x)\n", + name, tag_offset, buf->header_crc, computed_crc); + return 1; +} + static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, const struct mtd_partition **pparts, struct mtd_part_parser_data *data) @@ -99,13 +134,11 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, struct bcm_tag *buf = NULL; struct mtd_partition *parts; int ret; - size_t retlen; unsigned int rootfsaddr, kerneladdr, spareaddr; unsigned int rootfslen, kernellen, sparelen, totallen; unsigned int cfelen, nvramlen; unsigned int cfe_erasesize; int i; - u32 computed_crc; bool rootfs_first = false; if (bcm63xx_detect_cfe(master)) @@ -134,28 +167,13 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, } /* Get the tag */ - ret = mtd_read(master, cfelen, sizeof(struct bcm_tag), &retlen, - (void *)buf); - - if (retlen != sizeof(struct bcm_tag)) { - ret = -EIO; - goto out; - } - - computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf, - offsetof(struct bcm_tag, header_crc)); - if (computed_crc == buf->header_crc) { - char *boardid = &(buf->board_id[0]); - char *tagversion = &(buf->tag_version[0]); - + ret = bcm63xx_read_image_tag(master, "rootfs", cfelen, buf); + if (!ret) { sscanf(buf->flash_image_start, "%u", &rootfsaddr); sscanf(buf->kernel_address, "%u", &kerneladdr); sscanf(buf->kernel_length, "%u", &kernellen); sscanf(buf->total_length, "%u", &totallen); - pr_info("CFE boot tag found with version %s and board type %s\n", - tagversion, boardid); - kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE; rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE; spareaddr = roundup(totallen, master->erasesize) + cfelen; @@ -169,13 +187,13 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, rootfsaddr = kerneladdr + kernellen; rootfslen = spareaddr - rootfsaddr; } - } else { - pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n", - buf->header_crc, computed_crc); + } else if (ret > 0) { kernellen = 0; rootfslen = 0; rootfsaddr = 0; spareaddr = cfelen; + } else { + goto out; } sparelen = master->size - spareaddr - nvramlen; -- cgit v1.1 From 2c4fd433fb934c7d5ed02113a5eaa3edb42ea10b Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 13 Dec 2015 22:51:37 +0000 Subject: mtd: bcm63xxpart: Null terminate and validate conversion of flash strings Strings read from flash could be missing null termination characters, or not contain valid integers. Null terminate the strings and check for errors when converting them to integers. Also validate that the addresses are at least BCM963XX_EXTENDED_SIZE because this will be subtracted from them. Signed-off-by: Simon Arlott Signed-off-by: Brian Norris --- drivers/mtd/bcm63xxpart.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index eafbf52..41aa202 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -169,10 +169,39 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, /* Get the tag */ ret = bcm63xx_read_image_tag(master, "rootfs", cfelen, buf); if (!ret) { - sscanf(buf->flash_image_start, "%u", &rootfsaddr); - sscanf(buf->kernel_address, "%u", &kerneladdr); - sscanf(buf->kernel_length, "%u", &kernellen); - sscanf(buf->total_length, "%u", &totallen); + STR_NULL_TERMINATE(buf->flash_image_start); + if (kstrtouint(buf->flash_image_start, 10, &rootfsaddr) || + rootfsaddr < BCM963XX_EXTENDED_SIZE) { + pr_err("invalid rootfs address: %*ph\n", + sizeof(buf->flash_image_start), + buf->flash_image_start); + goto invalid_tag; + } + + STR_NULL_TERMINATE(buf->kernel_address); + if (kstrtouint(buf->kernel_address, 10, &kerneladdr) || + kerneladdr < BCM963XX_EXTENDED_SIZE) { + pr_err("invalid kernel address: %*ph\n", + sizeof(buf->kernel_address), + buf->kernel_address); + goto invalid_tag; + } + + STR_NULL_TERMINATE(buf->kernel_length); + if (kstrtouint(buf->kernel_length, 10, &kernellen)) { + pr_err("invalid kernel length: %*ph\n", + sizeof(buf->kernel_length), + buf->kernel_length); + goto invalid_tag; + } + + STR_NULL_TERMINATE(buf->total_length); + if (kstrtouint(buf->total_length, 10, &totallen)) { + pr_err("invalid total length: %*ph\n", + sizeof(buf->total_length), + buf->total_length); + goto invalid_tag; + } kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE; rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE; @@ -188,6 +217,7 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, rootfslen = spareaddr - rootfsaddr; } } else if (ret > 0) { +invalid_tag: kernellen = 0; rootfslen = 0; rootfsaddr = 0; -- cgit v1.1 From 4110fdd295e1219f4e4c4e35e2eba7b605b74ed7 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 13 Dec 2015 22:52:15 +0000 Subject: mtd: bcm63xxpart: Move NOR flash layout to a separate function Move the NOR flash layout to a separate function to allow the NAND flash layout to be supported. Signed-off-by: Simon Arlott Signed-off-by: Brian Norris --- drivers/mtd/bcm63xxpart.c | 54 ++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index 41aa202..26c38a1 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -124,13 +124,11 @@ static int bcm63xx_read_image_tag(struct mtd_info *master, const char *name, return 1; } -static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) +static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master, + const struct mtd_partition **pparts, struct bcm963xx_nvram *nvram) { /* CFE, NVRAM and global Linux are always present */ int nrparts = 3, curpart = 0; - struct bcm963xx_nvram *nvram = NULL; struct bcm_tag *buf = NULL; struct mtd_partition *parts; int ret; @@ -141,17 +139,6 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, int i; bool rootfs_first = false; - if (bcm63xx_detect_cfe(master)) - return -EINVAL; - - nvram = vzalloc(sizeof(*nvram)); - if (!nvram) - return -ENOMEM; - - ret = bcm63xx_read_nvram(master, nvram); - if (ret) - goto out; - cfe_erasesize = max_t(uint32_t, master->erasesize, BCM963XX_CFE_BLOCK_SIZE); @@ -159,12 +146,9 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, nvramlen = nvram->psi_size * SZ_1K; nvramlen = roundup(nvramlen, cfe_erasesize); - /* Allocate memory for buffer */ buf = vmalloc(sizeof(struct bcm_tag)); - if (!buf) { - ret = -ENOMEM; - goto out; - } + if (!buf) + return -ENOMEM; /* Get the tag */ ret = bcm63xx_read_image_tag(master, "rootfs", cfelen, buf); @@ -234,7 +218,6 @@ invalid_tag: if (kernellen > 0) nrparts++; - /* Ask kernel for more memory */ parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); if (!parts) { ret = -ENOMEM; @@ -292,13 +275,40 @@ invalid_tag: ret = 0; out: - vfree(nvram); vfree(buf); if (ret) return ret; return nrparts; +} + +static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct bcm963xx_nvram *nvram = NULL; + int ret; + + if (bcm63xx_detect_cfe(master)) + return -EINVAL; + + nvram = vzalloc(sizeof(*nvram)); + if (!nvram) + return -ENOMEM; + + ret = bcm63xx_read_nvram(master, nvram); + if (ret) + goto out; + + if (!mtd_type_is_nand(master)) + ret = bcm63xx_parse_cfe_nor_partitions(master, pparts, nvram); + else + ret = -EINVAL; + +out: + vfree(nvram); + return ret; }; static struct mtd_part_parser bcm63xx_cfe_parser = { -- cgit v1.1 From c2cdace755b583bae540a9979bff1aa428181b8c Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 10 Feb 2016 14:54:21 +0100 Subject: mtd: nand: pxa3xx_nand: add support for partial chunks This commit is needed to properly support the 8-bits ECC configuration with 4KB pages. When pages larger than 2 KB are used on platforms using the PXA3xx NAND controller, the reading/programming operations need to be split in chunks of 2 KBs or less because the controller FIFO is limited to about 2 KB (i.e a bit more than 2 KB to accommodate OOB data). Due to this requirement, the data layout on NAND is a bit strange, with ECC interleaved with data, at the end of each chunk. When a 4-bits ECC configuration is used with 4 KB pages, the physical data layout on the NAND looks like this: | 2048 data | 32 spare | 30 ECC | 2048 data | 32 spare | 30 ECC | So the data chunks have an equal size, 2080 bytes for each chunk, which the driver supports properly. When a 8-bits ECC configuration is used with 4KB pages, the physical data layout on the NAND looks like this: | 1024 data | 30 ECC | 1024 data | 30 ECC | 1024 data | 30 ECC | 1024 data | 30 ECC | 64 spare | 30 ECC | So, the spare area is stored in its own chunk, which has a different size than the other chunks. Since OOB is not used by UBIFS, the initial implementation of the driver has chosen to not support reading this additional "spare" chunk of data. Unfortunately, Marvell has chosen to store the BBT signature in the OOB area. Therefore, if the driver doesn't read this spare area, Linux has no way of finding the BBT. It thinks there is no BBT, and rewrites one, which U-Boot does not recognize, causing compatibility problems between the bootloader and the kernel in terms of NAND usage. To fix this, this commit implements the support for reading a partial last chunk. This support is currently only useful for the case of 8 bits ECC with 4 KB pages, but it will be useful in the future to enable other configurations such as 12 bits and 16 bits ECC with 4 KB pages, or 8 bits ECC with 8 KB pages, etc. All those configurations have a "last" chunk that doesn't have the same size as the other chunks. In order to implement reading of the last chunk, this commit: - Adds a number of new fields to the pxa3xx_nand_info to describe how many full chunks and how many chunks we have, the size of full chunks and partial chunks, both in terms of data area and spare area. - Fills in the step_chunk_size and step_spare_size variables to describe how much data and spare should be read/written for the current read/program step. - Reworks the state machine to accommodate doing the additional read or program step when a last partial chunk is used. This commit has been tested on a Marvell Armada 398 DB board, with a 4KB page NAND, tested in both 4 bits ECC and 8 bits ECC configurations. Robert Jarzmik has tested on some PXA platforms. Signed-off-by: Thomas Petazzoni Tested-by: Robert Jarzmik Acked-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 157 ++++++++++++++++++++++++++--------------- 1 file changed, 101 insertions(+), 56 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index e42496a..56e8954 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -234,15 +234,44 @@ struct pxa3xx_nand_info { int use_spare; /* use spare ? */ int need_wait; - unsigned int data_size; /* data to be read from FIFO */ - unsigned int chunk_size; /* split commands chunk size */ - unsigned int oob_size; + /* Amount of real data per full chunk */ + unsigned int chunk_size; + + /* Amount of spare data per full chunk */ unsigned int spare_size; + + /* Number of full chunks (i.e chunk_size + spare_size) */ + unsigned int nfullchunks; + + /* + * Total number of chunks. If equal to nfullchunks, then there + * are only full chunks. Otherwise, there is one last chunk of + * size (last_chunk_size + last_spare_size) + */ + unsigned int ntotalchunks; + + /* Amount of real data in the last chunk */ + unsigned int last_chunk_size; + + /* Amount of spare data in the last chunk */ + unsigned int last_spare_size; + unsigned int ecc_size; unsigned int ecc_err_cnt; unsigned int max_bitflips; int retcode; + /* + * Variables only valid during command + * execution. step_chunk_size and step_spare_size is the + * amount of real data and spare data in the current + * chunk. cur_chunk is the current chunk being + * read/programmed. + */ + unsigned int step_chunk_size; + unsigned int step_spare_size; + unsigned int cur_chunk; + /* cached register value */ uint32_t reg_ndcr; uint32_t ndtr0cs0; @@ -538,25 +567,6 @@ static int pxa3xx_nand_init(struct pxa3xx_nand_host *host) return 0; } -/* - * Set the data and OOB size, depending on the selected - * spare and ECC configuration. - * Only applicable to READ0, READOOB and PAGEPROG commands. - */ -static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info, - struct mtd_info *mtd) -{ - int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; - - info->data_size = mtd->writesize; - if (!oob_enable) - return; - - info->oob_size = info->spare_size; - if (!info->use_ecc) - info->oob_size += info->ecc_size; -} - /** * NOTE: it is a must to set ND_RUN firstly, then write * command buffer, otherwise, it does not work. @@ -672,28 +682,28 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len) static void handle_data_pio(struct pxa3xx_nand_info *info) { - unsigned int do_bytes = min(info->data_size, info->chunk_size); - switch (info->state) { case STATE_PIO_WRITING: - writesl(info->mmio_base + NDDB, - info->data_buff + info->data_buff_pos, - DIV_ROUND_UP(do_bytes, 4)); + if (info->step_chunk_size) + writesl(info->mmio_base + NDDB, + info->data_buff + info->data_buff_pos, + DIV_ROUND_UP(info->step_chunk_size, 4)); - if (info->oob_size > 0) + if (info->step_spare_size) writesl(info->mmio_base + NDDB, info->oob_buff + info->oob_buff_pos, - DIV_ROUND_UP(info->oob_size, 4)); + DIV_ROUND_UP(info->step_spare_size, 4)); break; case STATE_PIO_READING: - drain_fifo(info, - info->data_buff + info->data_buff_pos, - DIV_ROUND_UP(do_bytes, 4)); + if (info->step_chunk_size) + drain_fifo(info, + info->data_buff + info->data_buff_pos, + DIV_ROUND_UP(info->step_chunk_size, 4)); - if (info->oob_size > 0) + if (info->step_spare_size) drain_fifo(info, info->oob_buff + info->oob_buff_pos, - DIV_ROUND_UP(info->oob_size, 4)); + DIV_ROUND_UP(info->step_spare_size, 4)); break; default: dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, @@ -702,9 +712,8 @@ static void handle_data_pio(struct pxa3xx_nand_info *info) } /* Update buffer pointers for multi-page read/write */ - info->data_buff_pos += do_bytes; - info->oob_buff_pos += info->oob_size; - info->data_size -= do_bytes; + info->data_buff_pos += info->step_chunk_size; + info->oob_buff_pos += info->step_spare_size; } static void pxa3xx_nand_data_dma_irq(void *data) @@ -745,8 +754,9 @@ static void start_data_dma(struct pxa3xx_nand_info *info) info->state); BUG(); } - info->sg.length = info->data_size + - (info->oob_size ? info->spare_size + info->ecc_size : 0); + info->sg.length = info->chunk_size; + if (info->use_spare) + info->sg.length += info->spare_size + info->ecc_size; dma_map_sg(info->dma_chan->device->dev, &info->sg, 1, info->dma_dir); tx = dmaengine_prep_slave_sg(info->dma_chan, &info->sg, 1, direction, @@ -907,9 +917,11 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command) /* reset data and oob column point to handle data */ info->buf_start = 0; info->buf_count = 0; - info->oob_size = 0; info->data_buff_pos = 0; info->oob_buff_pos = 0; + info->step_chunk_size = 0; + info->step_spare_size = 0; + info->cur_chunk = 0; info->use_ecc = 0; info->use_spare = 1; info->retcode = ERR_NONE; @@ -921,8 +933,6 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command) case NAND_CMD_READ0: case NAND_CMD_PAGEPROG: info->use_ecc = 1; - case NAND_CMD_READOOB: - pxa3xx_set_datasize(info, mtd); break; case NAND_CMD_PARAM: info->use_spare = 0; @@ -981,6 +991,14 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, if (command == NAND_CMD_READOOB) info->buf_start += mtd->writesize; + if (info->cur_chunk < info->nfullchunks) { + info->step_chunk_size = info->chunk_size; + info->step_spare_size = info->spare_size; + } else { + info->step_chunk_size = info->last_chunk_size; + info->step_spare_size = info->last_spare_size; + } + /* * Multiple page read needs an 'extended command type' field, * which is either naked-read or last-read according to the @@ -992,8 +1010,8 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8) | NDCB0_LEN_OVRD | NDCB0_EXT_CMD_TYPE(ext_cmd_type); - info->ndcb3 = info->chunk_size + - info->oob_size; + info->ndcb3 = info->step_chunk_size + + info->step_spare_size; } set_command_address(info, mtd->writesize, column, page_addr); @@ -1013,8 +1031,6 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, | NDCB0_EXT_CMD_TYPE(ext_cmd_type) | addr_cycle | command; - /* No data transfer in this case */ - info->data_size = 0; exec_cmd = 1; } break; @@ -1026,6 +1042,14 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, break; } + if (info->cur_chunk < info->nfullchunks) { + info->step_chunk_size = info->chunk_size; + info->step_spare_size = info->spare_size; + } else { + info->step_chunk_size = info->last_chunk_size; + info->step_spare_size = info->last_spare_size; + } + /* Second command setting for large pages */ if (mtd->writesize > PAGE_CHUNK_SIZE) { /* @@ -1036,14 +1060,14 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, info->ndcb0 |= NDCB0_CMD_TYPE(0x1) | NDCB0_LEN_OVRD | NDCB0_EXT_CMD_TYPE(ext_cmd_type); - info->ndcb3 = info->chunk_size + - info->oob_size; + info->ndcb3 = info->step_chunk_size + + info->step_spare_size; /* * This is the command dispatch that completes a chunked * page program operation. */ - if (info->data_size == 0) { + if (info->cur_chunk == info->ntotalchunks) { info->ndcb0 = NDCB0_CMD_TYPE(0x1) | NDCB0_EXT_CMD_TYPE(ext_cmd_type) | command; @@ -1070,7 +1094,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, | command; info->ndcb1 = (column & 0xFF); info->ndcb3 = INIT_BUFFER_SIZE; - info->data_size = INIT_BUFFER_SIZE; + info->step_chunk_size = INIT_BUFFER_SIZE; break; case NAND_CMD_READID: @@ -1080,7 +1104,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, | command; info->ndcb1 = (column & 0xFF); - info->data_size = 8; + info->step_chunk_size = 8; break; case NAND_CMD_STATUS: info->buf_count = 1; @@ -1088,7 +1112,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, | NDCB0_ADDR_CYC(1) | command; - info->data_size = 8; + info->step_chunk_size = 8; break; case NAND_CMD_ERASE1: @@ -1229,6 +1253,7 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, init_completion(&info->dev_ready); do { info->state = STATE_PREPARED; + exec_cmd = prepare_set_command(info, command, ext_cmd_type, column, page_addr); if (!exec_cmd) { @@ -1248,22 +1273,30 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, break; } + /* Only a few commands need several steps */ + if (command != NAND_CMD_PAGEPROG && + command != NAND_CMD_READ0 && + command != NAND_CMD_READOOB) + break; + + info->cur_chunk++; + /* Check if the sequence is complete */ - if (info->data_size == 0 && command != NAND_CMD_PAGEPROG) + if (info->cur_chunk == info->ntotalchunks && command != NAND_CMD_PAGEPROG) break; /* * After a splitted program command sequence has issued * the command dispatch, the command sequence is complete. */ - if (info->data_size == 0 && + if (info->cur_chunk == (info->ntotalchunks + 1) && command == NAND_CMD_PAGEPROG && ext_cmd_type == EXT_CMD_TYPE_DISPATCH) break; if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) { /* Last read: issue a 'last naked read' */ - if (info->data_size == info->chunk_size) + if (info->cur_chunk == info->ntotalchunks - 1) ext_cmd_type = EXT_CMD_TYPE_LAST_RW; else ext_cmd_type = EXT_CMD_TYPE_NAKED_RW; @@ -1273,7 +1306,7 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, * the command dispatch must be issued to complete. */ } else if (command == NAND_CMD_PAGEPROG && - info->data_size == 0) { + info->cur_chunk == info->ntotalchunks) { ext_cmd_type = EXT_CMD_TYPE_DISPATCH; } } while (1); @@ -1518,6 +1551,8 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, int strength, int ecc_stepsize, int page_size) { if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) { + info->nfullchunks = 1; + info->ntotalchunks = 1; info->chunk_size = 2048; info->spare_size = 40; info->ecc_size = 24; @@ -1526,6 +1561,8 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, ecc->strength = 1; } else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) { + info->nfullchunks = 1; + info->ntotalchunks = 1; info->chunk_size = 512; info->spare_size = 8; info->ecc_size = 8; @@ -1539,6 +1576,8 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, */ } else if (strength == 4 && ecc_stepsize == 512 && page_size == 2048) { info->ecc_bch = 1; + info->nfullchunks = 1; + info->ntotalchunks = 1; info->chunk_size = 2048; info->spare_size = 32; info->ecc_size = 32; @@ -1549,6 +1588,8 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) { info->ecc_bch = 1; + info->nfullchunks = 2; + info->ntotalchunks = 2; info->chunk_size = 2048; info->spare_size = 32; info->ecc_size = 32; @@ -1563,8 +1604,12 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, */ } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) { info->ecc_bch = 1; + info->nfullchunks = 4; + info->ntotalchunks = 5; info->chunk_size = 1024; info->spare_size = 0; + info->last_chunk_size = 0; + info->last_spare_size = 64; info->ecc_size = 32; ecc->mode = NAND_ECC_HW; ecc->size = info->chunk_size; -- cgit v1.1 From c08266794926a9f6c2940e8585fbcbdc51caa7ed Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 11 Feb 2016 11:53:57 +0100 Subject: mtd: spi-nor: Add support for s25fl116k The Spansion s25fl116k is a 16MBit NOR Flash supporting dual and quad read operations. Signed-off-by: Sascha Hauer Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/spi-nor.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index ed0c19c..13e07ce 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -797,6 +797,7 @@ static const struct flash_info spi_nor_ids[] = { { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, + { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) }, { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) }, { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) }, -- cgit v1.1 From 3b5394a3ccffbfa1d1d448d48742853a862822c4 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Wed, 3 Feb 2016 14:26:46 +0100 Subject: mtd: spi-nor: remove micron_quad_enable() This patch remove the micron_quad_enable() function which force the Quad SPI mode. However, once this mode is enabled, the Micron memory expect ALL commands to use the SPI 4-4-4 protocol. Hence a failure does occur when calling spi_nor_wait_till_ready() right after the update of the Enhanced Volatile Configuration Register (EVCR) in the micron_quad_enable() as the SPI controller driver is not aware about the protocol change. Since there is almost no performance increase using Fast Read 4-4-4 commands instead of Fast Read 1-1-4 commands, we rather keep on using the Extended SPI mode than enabling the Quad SPI mode. Let's take the example of the pretty standard use of 8 dummy cycles during Fast Read operations on 64KB erase sectors: Fast Read 1-1-4 requires 8 cycles for the command, then 24 cycles for the 3byte address followed by 8 dummy clock cycles and finally 65536*2 cycles for the read data; so 131112 clock cycles. On the other hand the Fast Read 4-4-4 would require 2 cycles for the command, then 6 cycles for the 3byte address followed by 8 dummy clock cycles and finally 65536*2 cycles for the read data. So 131088 clock cycles. The theorical bandwidth increase is 0.0%. Now using Fast Read operations on 512byte pages: Fast Read 1-1-4 needs 8+24+8+(512*2) = 1064 clock cycles whereas Fast Read 4-4-4 would requires 2+6+8+(512*2) = 1040 clock cycles. Hence the theorical bandwidth increase is 2.3%. Consecutive reads for non sequential pages is not a relevant use case so The Quad SPI mode is not worth it. mtd_speedtest seems to confirm these figures. Signed-off-by: Cyrille Pitchen Fixes: 548cd3ab54da ("mtd: spi-nor: Add quad I/O support for Micron SPI NOR") Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/spi-nor.c | 46 +------------------------------------------ 1 file changed, 1 insertion(+), 45 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 13e07ce..999b3ce5 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1101,45 +1101,6 @@ static int spansion_quad_enable(struct spi_nor *nor) return 0; } -static int micron_quad_enable(struct spi_nor *nor) -{ - int ret; - u8 val; - - ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); - if (ret < 0) { - dev_err(nor->dev, "error %d reading EVCR\n", ret); - return ret; - } - - write_enable(nor); - - /* set EVCR, enable quad I/O */ - nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON; - ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1); - if (ret < 0) { - dev_err(nor->dev, "error while writing EVCR register\n"); - return ret; - } - - ret = spi_nor_wait_till_ready(nor); - if (ret) - return ret; - - /* read EVCR and check it */ - ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); - if (ret < 0) { - dev_err(nor->dev, "error %d reading EVCR\n", ret); - return ret; - } - if (val & EVCR_QUAD_EN_MICRON) { - dev_err(nor->dev, "Micron EVCR Quad bit not clear\n"); - return -EINVAL; - } - - return 0; -} - static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) { int status; @@ -1153,12 +1114,7 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) } return status; case SNOR_MFR_MICRON: - status = micron_quad_enable(nor); - if (status) { - dev_err(nor->dev, "Micron quad-read not enabled\n"); - return -EINVAL; - } - return status; + return 0; default: status = spansion_quad_enable(nor); if (status) { -- cgit v1.1 From 288e6eaa06877ea925d8dcdac5e56310fa6d8c7c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 2 Feb 2016 13:53:23 -0600 Subject: gpio: Include linux/gpio.h instead of asm/gpio.h Most arches have an asm/gpio.h that merely includes linux/gpio.h. The others select ARCH_HAVE_CUSTOM_GPIO_H, and when that's selected, linux/gpio.h includes asm/gpio.h. Therefore, code should include linux/gpio.h instead of including asm/gpio.h directly. Remove includes of asm/gpio.h, adding an include of linux/gpio.h when necessary. This is a follow-on to 7563bbf89d06 ("gpiolib/arches: Centralise bolierplate asm/gpio.h"). Signed-off-by: Bjorn Helgaas Acked-by: Thomas Gleixner Acked-by: Arnd Bergmann Acked-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/mtd/onenand/omap2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 0aacf12..24a1388 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -35,10 +35,10 @@ #include #include #include +#include #include #include -#include #include -- cgit v1.1 From 5e64c29e98bfbba1b527b0a164f9493f3db9e8cb Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 20 Feb 2016 22:27:48 +0200 Subject: mtd: onenand: fix deadlock in onenand_block_markbad Commit 5942ddbc500d ("mtd: introduce mtd_block_markbad interface") incorrectly changed onenand_block_markbad() to call mtd_block_markbad instead of onenand_chip's block_markbad function. As a result the function will now recurse and deadlock. Fix by reverting the change. Fixes: 5942ddbc500d ("mtd: introduce mtd_block_markbad interface") Signed-off-by: Aaro Koskinen Acked-by: Artem Bityutskiy Cc: Signed-off-by: Brian Norris --- drivers/mtd/onenand/onenand_base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 43b3392..652d018 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -2599,6 +2599,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) */ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) { + struct onenand_chip *this = mtd->priv; int ret; ret = onenand_block_isbad(mtd, ofs); @@ -2610,7 +2611,7 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) } onenand_get_device(mtd, FL_WRITING); - ret = mtd_block_markbad(mtd, ofs); + ret = this->block_markbad(mtd, ofs); onenand_release_device(mtd); return ret; } -- cgit v1.1 From d267aefc54a28efc5bda7f009598dc83b5f98734 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 24 Feb 2016 16:07:23 -0800 Subject: mtd: brcmnand: Fix v7.1 register offsets The BRCMNAND controller revision 7.1 is almost 100% compatible with the previous v6.0 register offset layout, except for the Correctable Error Reporting Threshold registers. Fix this by adding another table with the correct offsets for CORR_THRESHOLD and CORR_THRESHOLD_EXT. Fixes: 27c5b17cd1b1 ("mtd: nand: add NAND driver "library" for Broadcom STB NAND controller") Signed-off-by: Florian Fainelli Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index 844fc07..f7009c1 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -311,6 +311,36 @@ static const u16 brcmnand_regs_v60[] = { [BRCMNAND_FC_BASE] = 0x400, }; +/* BRCMNAND v7.1 */ +static const u16 brcmnand_regs_v71[] = { + [BRCMNAND_CMD_START] = 0x04, + [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, + [BRCMNAND_CMD_ADDRESS] = 0x0c, + [BRCMNAND_INTFC_STATUS] = 0x14, + [BRCMNAND_CS_SELECT] = 0x18, + [BRCMNAND_CS_XOR] = 0x1c, + [BRCMNAND_LL_OP] = 0x20, + [BRCMNAND_CS0_BASE] = 0x50, + [BRCMNAND_CS1_BASE] = 0, + [BRCMNAND_CORR_THRESHOLD] = 0xdc, + [BRCMNAND_CORR_THRESHOLD_EXT] = 0xe0, + [BRCMNAND_UNCORR_COUNT] = 0xfc, + [BRCMNAND_CORR_COUNT] = 0x100, + [BRCMNAND_CORR_EXT_ADDR] = 0x10c, + [BRCMNAND_CORR_ADDR] = 0x110, + [BRCMNAND_UNCORR_EXT_ADDR] = 0x114, + [BRCMNAND_UNCORR_ADDR] = 0x118, + [BRCMNAND_SEMAPHORE] = 0x150, + [BRCMNAND_ID] = 0x194, + [BRCMNAND_ID_EXT] = 0x198, + [BRCMNAND_LL_RDATA] = 0x19c, + [BRCMNAND_OOB_READ_BASE] = 0x200, + [BRCMNAND_OOB_READ_10_BASE] = 0, + [BRCMNAND_OOB_WRITE_BASE] = 0x280, + [BRCMNAND_OOB_WRITE_10_BASE] = 0, + [BRCMNAND_FC_BASE] = 0x400, +}; + enum brcmnand_cs_reg { BRCMNAND_CS_CFG_EXT = 0, BRCMNAND_CS_CFG, @@ -406,7 +436,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) } /* Register offsets */ - if (ctrl->nand_version >= 0x0600) + if (ctrl->nand_version >= 0x0701) + ctrl->reg_offsets = brcmnand_regs_v71; + else if (ctrl->nand_version >= 0x0600) ctrl->reg_offsets = brcmnand_regs_v60; else if (ctrl->nand_version >= 0x0500) ctrl->reg_offsets = brcmnand_regs_v50; -- cgit v1.1 From f671a1f3803428b01272b056d6dc0e09e0df6fd4 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Sat, 5 Mar 2016 00:21:20 +0100 Subject: mtd: nand: sunxi: remove direct mtd->priv accesses mtd->priv is no longer pointing to the struct nand_chip it is attached to. Replace those accesses by mtd_to_nand() calls. Signed-off-by: Boris Brezillon Fixes: 4be4e03efc7f ("mtd: nand: sunxi: add randomizer support") Signed-off-by: Brian Norris --- drivers/mtd/nand/sunxi_nand.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index b5ea6b3..1c03eee 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -642,7 +642,7 @@ static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc) static void sunxi_nfc_randomizer_config(struct mtd_info *mtd, int page, bool ecc) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL); u16 state; @@ -658,7 +658,7 @@ static void sunxi_nfc_randomizer_config(struct mtd_info *mtd, static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); if (!(nand->options & NAND_NEED_SCRAMBLING)) @@ -670,7 +670,7 @@ static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd) static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd) { - struct nand_chip *nand = mtd->priv; + struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); if (!(nand->options & NAND_NEED_SCRAMBLING)) -- cgit v1.1 From c57753d4541d5104284abbdceb841e690394e55f Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Tue, 1 Mar 2016 16:04:00 -0500 Subject: mtd: nand: tests: fix regression introduced in mtd_nandectest Offending Commit: 6e94119 "mtd: nand: return consistent error codes in ecc.correct() implementations" The new error code was not being handled properly in double bit error detection. Signed-off-by: Jorge Ramirez-Ortiz Reviewed-by: Boris Brezillon Tested-by: Franklin S Cooper Jr Signed-off-by: Brian Norris --- drivers/mtd/tests/mtd_nandecctest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c index 7931615..88b6c81 100644 --- a/drivers/mtd/tests/mtd_nandecctest.c +++ b/drivers/mtd/tests/mtd_nandecctest.c @@ -187,7 +187,7 @@ static int double_bit_error_detect(void *error_data, void *error_ecc, __nand_calculate_ecc(error_data, size, calc_ecc); ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size); - return (ret == -1) ? 0 : -EINVAL; + return (ret == -EBADMSG) ? 0 : -EINVAL; } static const struct nand_ecc_test nand_ecc_test[] = { -- cgit v1.1 From 9097103f06332d099c5ab06d1e7f22f4bcaca6e2 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Fri, 12 Feb 2016 23:29:04 +0100 Subject: mtd: nand: pxa3xx_nand: fix dmaengine initialization When the driver is initialized in a pure device-tree platform, the driver's probe fails allocating the dma channel : [ 525.624435] pxa3xx-nand 43100000.nand: no resource defined for data DMA [ 525.632088] pxa3xx-nand 43100000.nand: alloc nand resource failed The reason is that the DMA IO resource is not acquired through platform resources but by OF bindings. Fix this by ensuring that DMA IO resources are only queried in the non device-tree case. Fixes: 8f5ba31aa565 ("mtd: nand: pxa3xx-nand: switch to dmaengine") Signed-off-by: Robert Jarzmik Acked-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 56e8954..f100c4d 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1795,7 +1795,7 @@ static int alloc_nand_resource(struct platform_device *pdev) if (ret < 0) return ret; - if (use_dma) { + if (!np && use_dma) { r = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (r == NULL) { dev_err(&pdev->dev, -- cgit v1.1 From 4607777c71be52c4e7c9cbcf8ecac4a452090d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Sun, 28 Feb 2016 16:09:18 -0300 Subject: mtd: spi-nor: add subsector flag to n25q128a Micron n25q128axx support subsector (4K) erase so let's update the flags. Tested on n25q128a13. Signed-off-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/spi-nor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 999b3ce5..03e5e44 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -762,8 +762,8 @@ static const struct flash_info spi_nor_ids[] = { { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, - { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, - { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, + { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, + { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -- cgit v1.1 From e4f6daac20332448529b11f09388f1d55ef2084c Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 21 Feb 2016 10:53:03 +0100 Subject: ubi: Fix out of bounds write in volume update code ubi_start_leb_change() allocates too few bytes. ubi_more_leb_change_data() will write up to req->upd_bytes + ubi->min_io_size bytes. Cc: stable@vger.kernel.org Signed-off-by: Richard Weinberger Reviewed-by: Boris Brezillon --- drivers/mtd/ubi/upd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 2a1b6e0..0134ba3 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -193,7 +193,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, vol->changing_leb = 1; vol->ch_lnum = req->lnum; - vol->upd_buf = vmalloc(req->bytes); + vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size)); if (!vol->upd_buf) return -ENOMEM; -- cgit v1.1 From 2012850be8e3324bf3420ea08e1d0ee75c8d134c Mon Sep 17 00:00:00 2001 From: Yao Yuan Date: Tue, 26 Jan 2016 15:23:55 +0800 Subject: mtd: spi-nor: fsl-quadspi: add big-endian support Add R/W functions for big- or little-endian registers: The qSPI controller's endian is independent of the CPU core's endian. So far, the qSPI have two versions for big-endian and little-endian. Signed-off-by: Yuan Yao Acked-by: Han xu Acked-by: Han xu Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/fsl-quadspi.c | 157 +++++++++++++++++++++++--------------- 1 file changed, 97 insertions(+), 60 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 54640f1..04e8a93 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -275,6 +275,7 @@ struct fsl_qspi { u32 clk_rate; unsigned int chip_base_addr; /* We may support two chips. */ bool has_second_chip; + bool big_endian; struct mutex lock; struct pm_qos_request pm_qos_req; }; @@ -300,6 +301,28 @@ static inline int needs_wakeup_wait_mode(struct fsl_qspi *q) } /* + * R/W functions for big- or little-endian registers: + * The qSPI controller's endian is independent of the CPU core's endian. + * So far, although the CPU core is little-endian but the qSPI have two + * versions for big-endian and little-endian. + */ +static void qspi_writel(struct fsl_qspi *q, u32 val, void __iomem *addr) +{ + if (q->big_endian) + iowrite32be(val, addr); + else + iowrite32(val, addr); +} + +static u32 qspi_readl(struct fsl_qspi *q, void __iomem *addr) +{ + if (q->big_endian) + return ioread32be(addr); + else + return ioread32(addr); +} + +/* * An IC bug makes us to re-arrange the 32-bit data. * The following chips, such as IMX6SLX, have fixed this bug. */ @@ -310,14 +333,14 @@ static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a) static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q) { - writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); - writel(QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR); + qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); + qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR); } static inline void fsl_qspi_lock_lut(struct fsl_qspi *q) { - writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); - writel(QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR); + qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); + qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR); } static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id) @@ -326,8 +349,8 @@ static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id) u32 reg; /* clear interrupt */ - reg = readl(q->iobase + QUADSPI_FR); - writel(reg, q->iobase + QUADSPI_FR); + reg = qspi_readl(q, q->iobase + QUADSPI_FR); + qspi_writel(q, reg, q->iobase + QUADSPI_FR); if (reg & QUADSPI_FR_TFF_MASK) complete(&q->c); @@ -348,7 +371,7 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q) /* Clear all the LUT table */ for (i = 0; i < QUADSPI_LUT_NUM; i++) - writel(0, base + QUADSPI_LUT_BASE + i * 4); + qspi_writel(q, 0, base + QUADSPI_LUT_BASE + i * 4); /* Quad Read */ lut_base = SEQID_QUAD_READ * 4; @@ -364,14 +387,15 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q) dummy = 8; } - writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), + qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), base + QUADSPI_LUT(lut_base)); - writel(LUT0(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo), + qspi_writel(q, LUT0(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo), base + QUADSPI_LUT(lut_base + 1)); /* Write enable */ lut_base = SEQID_WREN * 4; - writel(LUT0(CMD, PAD1, SPINOR_OP_WREN), base + QUADSPI_LUT(lut_base)); + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WREN), + base + QUADSPI_LUT(lut_base)); /* Page Program */ lut_base = SEQID_PP * 4; @@ -385,13 +409,15 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q) addrlen = ADDR32BIT; } - writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), + qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), base + QUADSPI_LUT(lut_base)); - writel(LUT0(FSL_WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1)); + qspi_writel(q, LUT0(FSL_WRITE, PAD1, 0), + base + QUADSPI_LUT(lut_base + 1)); /* Read Status */ lut_base = SEQID_RDSR * 4; - writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(FSL_READ, PAD1, 0x1), + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDSR) | + LUT1(FSL_READ, PAD1, 0x1), base + QUADSPI_LUT(lut_base)); /* Erase a sector */ @@ -400,40 +426,46 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q) cmd = q->nor[0].erase_opcode; addrlen = q->nor_size <= SZ_16M ? ADDR24BIT : ADDR32BIT; - writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), + qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), base + QUADSPI_LUT(lut_base)); /* Erase the whole chip */ lut_base = SEQID_CHIP_ERASE * 4; - writel(LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE), + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE), base + QUADSPI_LUT(lut_base)); /* READ ID */ lut_base = SEQID_RDID * 4; - writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(FSL_READ, PAD1, 0x8), + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDID) | + LUT1(FSL_READ, PAD1, 0x8), base + QUADSPI_LUT(lut_base)); /* Write Register */ lut_base = SEQID_WRSR * 4; - writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(FSL_WRITE, PAD1, 0x2), + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRSR) | + LUT1(FSL_WRITE, PAD1, 0x2), base + QUADSPI_LUT(lut_base)); /* Read Configuration Register */ lut_base = SEQID_RDCR * 4; - writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(FSL_READ, PAD1, 0x1), + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDCR) | + LUT1(FSL_READ, PAD1, 0x1), base + QUADSPI_LUT(lut_base)); /* Write disable */ lut_base = SEQID_WRDI * 4; - writel(LUT0(CMD, PAD1, SPINOR_OP_WRDI), base + QUADSPI_LUT(lut_base)); + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRDI), + base + QUADSPI_LUT(lut_base)); /* Enter 4 Byte Mode (Micron) */ lut_base = SEQID_EN4B * 4; - writel(LUT0(CMD, PAD1, SPINOR_OP_EN4B), base + QUADSPI_LUT(lut_base)); + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_EN4B), + base + QUADSPI_LUT(lut_base)); /* Enter 4 Byte Mode (Spansion) */ lut_base = SEQID_BRWR * 4; - writel(LUT0(CMD, PAD1, SPINOR_OP_BRWR), base + QUADSPI_LUT(lut_base)); + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_BRWR), + base + QUADSPI_LUT(lut_base)); fsl_qspi_lock_lut(q); } @@ -488,15 +520,16 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len) q->chip_base_addr, addr, len, cmd); /* save the reg */ - reg = readl(base + QUADSPI_MCR); + reg = qspi_readl(q, base + QUADSPI_MCR); - writel(q->memmap_phy + q->chip_base_addr + addr, base + QUADSPI_SFAR); - writel(QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS, + qspi_writel(q, q->memmap_phy + q->chip_base_addr + addr, + base + QUADSPI_SFAR); + qspi_writel(q, QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS, base + QUADSPI_RBCT); - writel(reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR); + qspi_writel(q, reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR); do { - reg2 = readl(base + QUADSPI_SR); + reg2 = qspi_readl(q, base + QUADSPI_SR); if (reg2 & (QUADSPI_SR_IP_ACC_MASK | QUADSPI_SR_AHB_ACC_MASK)) { udelay(1); dev_dbg(q->dev, "The controller is busy, 0x%x\n", reg2); @@ -507,21 +540,22 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len) /* trigger the LUT now */ seqid = fsl_qspi_get_seqid(q, cmd); - writel((seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, base + QUADSPI_IPCR); + qspi_writel(q, (seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, + base + QUADSPI_IPCR); /* Wait for the interrupt. */ if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) { dev_err(q->dev, "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n", - cmd, addr, readl(base + QUADSPI_FR), - readl(base + QUADSPI_SR)); + cmd, addr, qspi_readl(q, base + QUADSPI_FR), + qspi_readl(q, base + QUADSPI_SR)); err = -ETIMEDOUT; } else { err = 0; } /* restore the MCR */ - writel(reg, base + QUADSPI_MCR); + qspi_writel(q, reg, base + QUADSPI_MCR); return err; } @@ -533,7 +567,7 @@ static void fsl_qspi_read_data(struct fsl_qspi *q, int len, u8 *rxbuf) int i = 0; while (len > 0) { - tmp = readl(q->iobase + QUADSPI_RBDR + i * 4); + tmp = qspi_readl(q, q->iobase + QUADSPI_RBDR + i * 4); tmp = fsl_qspi_endian_xchg(q, tmp); dev_dbg(q->dev, "chip addr:0x%.8x, rcv:0x%.8x\n", q->chip_base_addr, tmp); @@ -561,9 +595,9 @@ static inline void fsl_qspi_invalid(struct fsl_qspi *q) { u32 reg; - reg = readl(q->iobase + QUADSPI_MCR); + reg = qspi_readl(q, q->iobase + QUADSPI_MCR); reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK; - writel(reg, q->iobase + QUADSPI_MCR); + qspi_writel(q, reg, q->iobase + QUADSPI_MCR); /* * The minimum delay : 1 AHB + 2 SFCK clocks. @@ -572,7 +606,7 @@ static inline void fsl_qspi_invalid(struct fsl_qspi *q) udelay(1); reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK); - writel(reg, q->iobase + QUADSPI_MCR); + qspi_writel(q, reg, q->iobase + QUADSPI_MCR); } static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor, @@ -586,20 +620,20 @@ static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor, q->chip_base_addr, to, count); /* clear the TX FIFO. */ - tmp = readl(q->iobase + QUADSPI_MCR); - writel(tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR); + tmp = qspi_readl(q, q->iobase + QUADSPI_MCR); + qspi_writel(q, tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR); /* fill the TX data to the FIFO */ for (j = 0, i = ((count + 3) / 4); j < i; j++) { tmp = fsl_qspi_endian_xchg(q, *txbuf); - writel(tmp, q->iobase + QUADSPI_TBDR); + qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR); txbuf++; } /* fill the TXFIFO upto 16 bytes for i.MX7d */ if (needs_fill_txfifo(q)) for (; i < 4; i++) - writel(tmp, q->iobase + QUADSPI_TBDR); + qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR); /* Trigger it */ ret = fsl_qspi_runcmd(q, opcode, to, count); @@ -615,10 +649,10 @@ static void fsl_qspi_set_map_addr(struct fsl_qspi *q) int nor_size = q->nor_size; void __iomem *base = q->iobase; - writel(nor_size + q->memmap_phy, base + QUADSPI_SFA1AD); - writel(nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD); - writel(nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD); - writel(nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD); + qspi_writel(q, nor_size + q->memmap_phy, base + QUADSPI_SFA1AD); + qspi_writel(q, nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD); + qspi_writel(q, nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD); + qspi_writel(q, nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD); } /* @@ -640,24 +674,26 @@ static void fsl_qspi_init_abh_read(struct fsl_qspi *q) int seqid; /* AHB configuration for access buffer 0/1/2 .*/ - writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); - writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); - writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); + qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); + qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); + qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); /* * Set ADATSZ with the maximum AHB buffer size to improve the * read performance. */ - writel(QUADSPI_BUF3CR_ALLMST_MASK | ((q->devtype_data->ahb_buf_size / 8) - << QUADSPI_BUF3CR_ADATSZ_SHIFT), base + QUADSPI_BUF3CR); + qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK | + ((q->devtype_data->ahb_buf_size / 8) + << QUADSPI_BUF3CR_ADATSZ_SHIFT), + base + QUADSPI_BUF3CR); /* We only use the buffer3 */ - writel(0, base + QUADSPI_BUF0IND); - writel(0, base + QUADSPI_BUF1IND); - writel(0, base + QUADSPI_BUF2IND); + qspi_writel(q, 0, base + QUADSPI_BUF0IND); + qspi_writel(q, 0, base + QUADSPI_BUF1IND); + qspi_writel(q, 0, base + QUADSPI_BUF2IND); /* Set the default lut sequence for AHB Read. */ seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode); - writel(seqid << QUADSPI_BFGENCR_SEQID_SHIFT, + qspi_writel(q, seqid << QUADSPI_BFGENCR_SEQID_SHIFT, q->iobase + QUADSPI_BFGENCR); } @@ -713,7 +749,7 @@ static int fsl_qspi_nor_setup(struct fsl_qspi *q) return ret; /* Reset the module */ - writel(QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK, + qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK, base + QUADSPI_MCR); udelay(1); @@ -721,24 +757,24 @@ static int fsl_qspi_nor_setup(struct fsl_qspi *q) fsl_qspi_init_lut(q); /* Disable the module */ - writel(QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, + qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, base + QUADSPI_MCR); - reg = readl(base + QUADSPI_SMPR); - writel(reg & ~(QUADSPI_SMPR_FSDLY_MASK + reg = qspi_readl(q, base + QUADSPI_SMPR); + qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK | QUADSPI_SMPR_FSPHS_MASK | QUADSPI_SMPR_HSENA_MASK | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR); /* Enable the module */ - writel(QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK, + qspi_writel(q, QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK, base + QUADSPI_MCR); /* clear all interrupt status */ - writel(0xffffffff, q->iobase + QUADSPI_FR); + qspi_writel(q, 0xffffffff, q->iobase + QUADSPI_FR); /* enable the interrupt */ - writel(QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); + qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); return 0; } @@ -954,6 +990,7 @@ static int fsl_qspi_probe(struct platform_device *pdev) if (IS_ERR(q->iobase)) return PTR_ERR(q->iobase); + q->big_endian = of_property_read_bool(np, "big-endian"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI-memory"); if (!devm_request_mem_region(dev, res->start, resource_size(res), @@ -1101,8 +1138,8 @@ static int fsl_qspi_remove(struct platform_device *pdev) } /* disable the hardware */ - writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); - writel(0x0, q->iobase + QUADSPI_RSER); + qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); + qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER); mutex_destroy(&q->lock); -- cgit v1.1 From e8c034b2fbe57f56c3902187f844f41d295b5159 Mon Sep 17 00:00:00 2001 From: Yao Yuan Date: Tue, 26 Jan 2016 15:23:56 +0800 Subject: mtd: spi-nor: fsl-quadspi: add support for ls1021a LS1021a also support Freescale Quad SPI controller. Add fsl-quadspi support for ls1021a chip and make SPI_FSL_QUADSPI selectable for LS1021A SOC hardwares. Signed-off-by: Yuan Yao Acked-by: Han xu Acked-by: Han xu Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/Kconfig | 2 +- drivers/mtd/spi-nor/fsl-quadspi.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index 83befab..3392a97 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -31,7 +31,7 @@ config MTD_SPI_NOR_USE_4K_SECTORS config SPI_FSL_QUADSPI tristate "Freescale Quad SPI controller" - depends on ARCH_MXC || COMPILE_TEST + depends on ARCH_MXC || SOC_LS1021A || COMPILE_TEST depends on HAS_IOMEM help This enables support for the Quad SPI controller in master mode. diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 04e8a93..9ab2b51 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -213,6 +213,7 @@ enum fsl_qspi_devtype { FSL_QUADSPI_IMX6SX, FSL_QUADSPI_IMX7D, FSL_QUADSPI_IMX6UL, + FSL_QUADSPI_LS1021A, }; struct fsl_qspi_devtype_data { @@ -258,6 +259,14 @@ static struct fsl_qspi_devtype_data imx6ul_data = { | QUADSPI_QUIRK_4X_INT_CLK, }; +static struct fsl_qspi_devtype_data ls1021a_data = { + .devtype = FSL_QUADSPI_LS1021A, + .rxfifo = 128, + .txfifo = 64, + .ahb_buf_size = 1024, + .driver_data = 0, +}; + #define FSL_QSPI_MAX_CHIP 4 struct fsl_qspi { struct spi_nor nor[FSL_QSPI_MAX_CHIP]; @@ -812,6 +821,7 @@ static const struct of_device_id fsl_qspi_dt_ids[] = { { .compatible = "fsl,imx6sx-qspi", .data = (void *)&imx6sx_data, }, { .compatible = "fsl,imx7d-qspi", .data = (void *)&imx7d_data, }, { .compatible = "fsl,imx6ul-qspi", .data = (void *)&imx6ul_data, }, + { .compatible = "fsl,ls1021a-qspi", .data = (void *)&ls1021a_data, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); -- cgit v1.1 From a578c4f9ebe0ae781a69a68255b06b35aab6e5fe Mon Sep 17 00:00:00 2001 From: Yao Yuan Date: Tue, 26 Jan 2016 15:23:57 +0800 Subject: mtd: spi-nor: fsl-quadspi: add support for layerscape LS1043a and LS2080A in the Layerscape family also support Freescale Quad SPI, make Quad SPI selectable for these hardwares. Signed-off-by: Yuan Yao Acked-by: Han xu Signed-off-by: Brian Norris --- drivers/mtd/spi-nor/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index 3392a97..d42c98e 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -31,7 +31,7 @@ config MTD_SPI_NOR_USE_4K_SECTORS config SPI_FSL_QUADSPI tristate "Freescale Quad SPI controller" - depends on ARCH_MXC || SOC_LS1021A || COMPILE_TEST + depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST depends on HAS_IOMEM help This enables support for the Quad SPI controller in master mode. -- cgit v1.1 From 4cf9339d2036287b734dfdcadcebc9e3daf380b5 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 7 Mar 2016 10:37:30 -0800 Subject: mtd: nand: pxa3xx_nand: kill unused field 'drcmr_cmd' With this removal, we don't need to 'get' the second DMA resource either, as it's also unused. Signed-off-by: Brian Norris Acked-by: Robert Jarzmik Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index f100c4d..d650885 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -211,7 +211,6 @@ struct pxa3xx_nand_info { struct dma_chan *dma_chan; dma_cookie_t dma_cookie; int drcmr_dat; - int drcmr_cmd; unsigned char *data_buff; unsigned char *oob_buff; @@ -1804,15 +1803,6 @@ static int alloc_nand_resource(struct platform_device *pdev) goto fail_disable_clk; } info->drcmr_dat = r->start; - - r = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (r == NULL) { - dev_err(&pdev->dev, - "no resource defined for cmd DMA\n"); - ret = -ENXIO; - goto fail_disable_clk; - } - info->drcmr_cmd = r->start; } irq = platform_get_irq(pdev, 0); -- cgit v1.1 From c67682c5e0a43bdcb049c7775b78200835f12b95 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 2 Mar 2016 16:26:59 +0100 Subject: mtd: mtdram: Add parameter for setting writebuf size ubifs uses the write buffer size in recovery algorithm. When inspecting an unclean ubifs recovery fails with writebuf size 64 in mtdram while recovery on actual mtd device with writebuf size of 1024 succeeds. So add a parameter for setting this property. Signed-off-by: Alexander Stein Reviewed-by: Richard Weinberger Signed-off-by: Brian Norris --- drivers/mtd/devices/mtdram.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 627a9bc..cbd8547 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -19,6 +19,7 @@ static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE; static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE; +static unsigned long writebuf_size = 64; #define MTDRAM_TOTAL_SIZE (total_size * 1024) #define MTDRAM_ERASE_SIZE (erase_size * 1024) @@ -27,6 +28,8 @@ module_param(total_size, ulong, 0); MODULE_PARM_DESC(total_size, "Total device size in KiB"); module_param(erase_size, ulong, 0); MODULE_PARM_DESC(erase_size, "Device erase block size in KiB"); +module_param(writebuf_size, ulong, 0); +MODULE_PARM_DESC(writebuf_size, "Device write buf size in Bytes (Default: 64)"); #endif // We could store these in the mtd structure, but we only support 1 device.. @@ -123,7 +126,7 @@ int mtdram_init_device(struct mtd_info *mtd, void *mapped_address, mtd->flags = MTD_CAP_RAM; mtd->size = size; mtd->writesize = 1; - mtd->writebufsize = 64; /* Mimic CFI NOR flashes */ + mtd->writebufsize = writebuf_size; mtd->erasesize = MTDRAM_ERASE_SIZE; mtd->priv = mapped_address; -- cgit v1.1 From 3707b2c3d21f7c9f8c6aadba79ef012f0bbad10c Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 12 Feb 2016 12:26:04 -0800 Subject: mtd: bcm63xxpart: give width specifier an 'int', not 'size_t' Fixes this warning: >> drivers/mtd/bcm63xxpart.c:175:4: note: in expansion of macro 'pr_err' pr_err("invalid rootfs address: %*ph\n", ^ >> include/linux/kern_levels.h:4:18: warning: field width specifier '*' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Wformat=] Reported-by: kbuild test robot Signed-off-by: Brian Norris --- drivers/mtd/bcm63xxpart.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index 26c38a1..41d1d31 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -157,7 +157,7 @@ static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master, if (kstrtouint(buf->flash_image_start, 10, &rootfsaddr) || rootfsaddr < BCM963XX_EXTENDED_SIZE) { pr_err("invalid rootfs address: %*ph\n", - sizeof(buf->flash_image_start), + (int)sizeof(buf->flash_image_start), buf->flash_image_start); goto invalid_tag; } @@ -166,7 +166,7 @@ static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master, if (kstrtouint(buf->kernel_address, 10, &kerneladdr) || kerneladdr < BCM963XX_EXTENDED_SIZE) { pr_err("invalid kernel address: %*ph\n", - sizeof(buf->kernel_address), + (int)sizeof(buf->kernel_address), buf->kernel_address); goto invalid_tag; } @@ -174,7 +174,7 @@ static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master, STR_NULL_TERMINATE(buf->kernel_length); if (kstrtouint(buf->kernel_length, 10, &kernellen)) { pr_err("invalid kernel length: %*ph\n", - sizeof(buf->kernel_length), + (int)sizeof(buf->kernel_length), buf->kernel_length); goto invalid_tag; } @@ -182,7 +182,7 @@ static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master, STR_NULL_TERMINATE(buf->total_length); if (kstrtouint(buf->total_length, 10, &totallen)) { pr_err("invalid total length: %*ph\n", - sizeof(buf->total_length), + (int)sizeof(buf->total_length), buf->total_length); goto invalid_tag; } -- cgit v1.1 From 9ebfdf5b18493f338237ef9861a555c2f79b0c17 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 4 Mar 2016 17:19:23 -0800 Subject: mtd: nand: check status before reporting timeout In commit b70af9bef49b ("mtd: nand: increase ready wait timeout and report timeouts"), we increased the likelihood of scheduling during nand_wait(). This makes us more likely to hit the time_before(...) condition, since a lot of time may pass before we get scheduled again. Now, the loop was already buggy, since we don't check if the NAND is ready after exiting the loop; we simply print out a timeout warning. Fix this by doing a final status check before printing a timeout message. This isn't actually a critical bug, since the only effect is a false warning print. But too many prints never hurt anyone, did they? :) Side note: perhaps I'm not smart enough, but I'm not sure what the best policy is for this kind of loop; do we busy loop (i.e., no cond_resched()) to keep the lowest I/O latency (it's not great if the resched is delaying Richard's system ~400ms)? Or do we allow rescheduling, to play nice with the rest of the system (since some operations can take quite a while)? Reported-by: Richard Weinberger Signed-off-by: Brian Norris Reviewed-by: Boris Brezillon Reviewed-by: Richard Weinberger Reviewed-by: Harvey Hunt --- drivers/mtd/nand/nand_base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index f2c8ff3..596a9b0 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -566,8 +566,8 @@ void nand_wait_ready(struct mtd_info *mtd) cond_resched(); } while (time_before(jiffies, timeo)); - pr_warn_ratelimited( - "timeout while waiting for chip to become ready\n"); + if (!chip->dev_ready(mtd)) + pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); out: led_trigger_event(nand_led_trigger, LED_OFF); } -- cgit v1.1 From f5b8aa78ef086248145363bf1ffe5ca4348b6a98 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Mar 2016 10:46:51 +0100 Subject: mtd: kill the ecclayout->oobavail field ecclayout->oobavail is just redundant with the mtd->oobavail field. Moreover, it prevents static const definition of ecc layouts since the NAND framework is calculating this value based on the ecclayout->oobfree field. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/devices/docg3.c | 5 ++-- drivers/mtd/mtdswap.c | 16 ++++++------ drivers/mtd/nand/brcmnand/brcmnand.c | 8 +++--- drivers/mtd/nand/docg4.c | 1 - drivers/mtd/nand/hisi504_nand.c | 1 - drivers/mtd/nand/nand_base.c | 14 +++++------ drivers/mtd/onenand/onenand_base.c | 16 ++++++------ drivers/mtd/tests/oobtest.c | 49 ++++++++++++++++++------------------ 8 files changed, 51 insertions(+), 59 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index c3a2695..e7b2e43 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -72,13 +72,11 @@ MODULE_PARM_DESC(reliable_mode, "Set the docg3 mode (0=normal MLC, 1=fast, " * @eccbytes: 8 bytes are used (1 for Hamming ECC, 7 for BCH ECC) * @eccpos: ecc positions (byte 7 is Hamming ECC, byte 8-14 are BCH ECC) * @oobfree: free pageinfo bytes (byte 0 until byte 6, byte 15 - * @oobavail: 8 available bytes remaining after ECC toll */ static struct nand_ecclayout docg3_oobinfo = { .eccbytes = 8, .eccpos = {7, 8, 9, 10, 11, 12, 13, 14}, .oobfree = {{0, 7}, {15, 1} }, - .oobavail = 8, }; static inline u8 doc_readb(struct docg3 *docg3, u16 reg) @@ -1438,7 +1436,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, oobdelta = mtd->oobsize; break; case MTD_OPS_AUTO_OOB: - oobdelta = mtd->ecclayout->oobavail; + oobdelta = mtd->oobavail; break; default: return -EINVAL; @@ -1860,6 +1858,7 @@ static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) mtd->_write_oob = doc_write_oob; mtd->_block_isbad = doc_block_isbad; mtd->ecclayout = &docg3_oobinfo; + mtd->oobavail = 8; mtd->ecc_strength = DOC_ECC_BCH_T; return 0; diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c index fc8b3d1..d330eb1 100644 --- a/drivers/mtd/mtdswap.c +++ b/drivers/mtd/mtdswap.c @@ -346,7 +346,7 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb) if (mtd_can_have_bb(d->mtd) && mtd_block_isbad(d->mtd, offset)) return MTDSWAP_SCANNED_BAD; - ops.ooblen = 2 * d->mtd->ecclayout->oobavail; + ops.ooblen = 2 * d->mtd->oobavail; ops.oobbuf = d->oob_buf; ops.ooboffs = 0; ops.datbuf = NULL; @@ -359,7 +359,7 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb) data = (struct mtdswap_oobdata *)d->oob_buf; data2 = (struct mtdswap_oobdata *) - (d->oob_buf + d->mtd->ecclayout->oobavail); + (d->oob_buf + d->mtd->oobavail); if (le16_to_cpu(data->magic) == MTDSWAP_MAGIC_CLEAN) { eb->erase_count = le32_to_cpu(data->count); @@ -933,7 +933,7 @@ static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d, ops.mode = MTD_OPS_AUTO_OOB; ops.len = mtd->writesize; - ops.ooblen = mtd->ecclayout->oobavail; + ops.ooblen = mtd->oobavail; ops.ooboffs = 0; ops.datbuf = d->page_buf; ops.oobbuf = d->oob_buf; @@ -945,7 +945,7 @@ static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d, for (i = 0; i < mtd_pages; i++) { patt = mtdswap_test_patt(test + i); memset(d->page_buf, patt, mtd->writesize); - memset(d->oob_buf, patt, mtd->ecclayout->oobavail); + memset(d->oob_buf, patt, mtd->oobavail); ret = mtd_write_oob(mtd, pos, &ops); if (ret) goto error; @@ -964,7 +964,7 @@ static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d, if (p1[j] != patt) goto error; - for (j = 0; j < mtd->ecclayout->oobavail; j++) + for (j = 0; j < mtd->oobavail; j++) if (p2[j] != (unsigned char)patt) goto error; @@ -1387,7 +1387,7 @@ static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks, if (!d->page_buf) goto page_buf_fail; - d->oob_buf = kmalloc(2 * mtd->ecclayout->oobavail, GFP_KERNEL); + d->oob_buf = kmalloc(2 * mtd->oobavail, GFP_KERNEL); if (!d->oob_buf) goto oob_buf_fail; @@ -1454,10 +1454,10 @@ static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) return; } - if (!mtd->oobsize || oinfo->oobavail < MTDSWAP_OOBSIZE) { + if (!mtd->oobsize || mtd->oobavail < MTDSWAP_OOBSIZE) { printk(KERN_ERR "%s: Not enough free bytes in OOB, " "%d available, %zu needed.\n", - MTDSWAP_PREFIX, oinfo->oobavail, MTDSWAP_OOBSIZE); + MTDSWAP_PREFIX, mtd->oobavail, MTDSWAP_OOBSIZE); return; } diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c index f7009c1..e052839 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/brcmnand/brcmnand.c @@ -828,7 +828,8 @@ static struct nand_ecclayout *brcmnand_create_layout(int ecc_level, idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1) break; } - goto out; + + return layout; } /* @@ -879,10 +880,7 @@ static struct nand_ecclayout *brcmnand_create_layout(int ecc_level, idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1) break; } -out: - /* Sum available OOB */ - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE; i++) - layout->oobavail += layout->oobfree[i].length; + return layout; } diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index df4165b..fb46fd7 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c @@ -225,7 +225,6 @@ struct docg4_priv { static struct nand_ecclayout docg4_oobinfo = { .eccbytes = 9, .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, - .oobavail = 5, .oobfree = { {.offset = 2, .length = 5} } }; diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c index f8d37f3..96502b6 100644 --- a/drivers/mtd/nand/hisi504_nand.c +++ b/drivers/mtd/nand/hisi504_nand.c @@ -632,7 +632,6 @@ static void hisi_nfc_host_init(struct hinfc_host *host) } static struct nand_ecclayout nand_ecc_2K_16bits = { - .oobavail = 6, .oobfree = { {2, 6} }, }; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 596a9b0..53993df 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2076,7 +2076,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, stats = mtd->ecc_stats; if (ops->mode == MTD_OPS_AUTO_OOB) - len = chip->ecc.layout->oobavail; + len = mtd->oobavail; else len = mtd->oobsize; @@ -2767,7 +2767,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, __func__, (unsigned int)to, (int)ops->ooblen); if (ops->mode == MTD_OPS_AUTO_OOB) - len = chip->ecc.layout->oobavail; + len = mtd->oobavail; else len = mtd->oobsize; @@ -4325,11 +4325,11 @@ int nand_scan_tail(struct mtd_info *mtd) * The number of bytes available for a client to place data into * the out of band area. */ - ecc->layout->oobavail = 0; - for (i = 0; ecc->layout->oobfree[i].length - && i < ARRAY_SIZE(ecc->layout->oobfree); i++) - ecc->layout->oobavail += ecc->layout->oobfree[i].length; - mtd->oobavail = ecc->layout->oobavail; + mtd->oobavail = 0; + if (ecc->layout) { + for (i = 0; ecc->layout->oobfree[i].length; i++) + mtd->oobavail += ecc->layout->oobfree[i].length; + } /* ECC sanity check: warn if it's too weak */ if (!nand_ecc_strength_good(mtd)) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 652d018..df47537 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -1125,7 +1125,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, (int)len); if (ops->mode == MTD_OPS_AUTO_OOB) - oobsize = this->ecclayout->oobavail; + oobsize = mtd->oobavail; else oobsize = mtd->oobsize; @@ -1230,7 +1230,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, (int)len); if (ops->mode == MTD_OPS_AUTO_OOB) - oobsize = this->ecclayout->oobavail; + oobsize = mtd->oobavail; else oobsize = mtd->oobsize; @@ -1365,7 +1365,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, ops->oobretlen = 0; if (mode == MTD_OPS_AUTO_OOB) - oobsize = this->ecclayout->oobavail; + oobsize = mtd->oobavail; else oobsize = mtd->oobsize; @@ -1887,7 +1887,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, return 0; if (ops->mode == MTD_OPS_AUTO_OOB) - oobsize = this->ecclayout->oobavail; + oobsize = mtd->oobavail; else oobsize = mtd->oobsize; @@ -2063,7 +2063,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, ops->oobretlen = 0; if (mode == MTD_OPS_AUTO_OOB) - oobsize = this->ecclayout->oobavail; + oobsize = mtd->oobavail; else oobsize = mtd->oobsize; @@ -4050,12 +4050,10 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) * The number of bytes available for a client to place data into * the out of band area */ - this->ecclayout->oobavail = 0; + mtd->oobavail = 0; for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && this->ecclayout->oobfree[i].length; i++) - this->ecclayout->oobavail += - this->ecclayout->oobfree[i].length; - mtd->oobavail = this->ecclayout->oobavail; + mtd->oobavail += this->ecclayout->oobfree[i].length; mtd->ecclayout = this->ecclayout; mtd->ecc_strength = 1; diff --git a/drivers/mtd/tests/oobtest.c b/drivers/mtd/tests/oobtest.c index 3176212..1cb3f77 100644 --- a/drivers/mtd/tests/oobtest.c +++ b/drivers/mtd/tests/oobtest.c @@ -215,19 +215,19 @@ static int verify_eraseblock(int ebnum) pr_info("ignoring error as within bitflip_limit\n"); } - if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) { + if (use_offset != 0 || use_len < mtd->oobavail) { int k; ops.mode = MTD_OPS_AUTO_OOB; ops.len = 0; ops.retlen = 0; - ops.ooblen = mtd->ecclayout->oobavail; + ops.ooblen = mtd->oobavail; ops.oobretlen = 0; ops.ooboffs = 0; ops.datbuf = NULL; ops.oobbuf = readbuf; err = mtd_read_oob(mtd, addr, &ops); - if (err || ops.oobretlen != mtd->ecclayout->oobavail) { + if (err || ops.oobretlen != mtd->oobavail) { pr_err("error: readoob failed at %#llx\n", (long long)addr); errcnt += 1; @@ -244,7 +244,7 @@ static int verify_eraseblock(int ebnum) /* verify post-(use_offset + use_len) area for 0xff */ k = use_offset + use_len; bitflips += memffshow(addr, k, readbuf + k, - mtd->ecclayout->oobavail - k); + mtd->oobavail - k); if (bitflips > bitflip_limit) { pr_err("error: verify failed at %#llx\n", @@ -269,8 +269,8 @@ static int verify_eraseblock_in_one_go(int ebnum) struct mtd_oob_ops ops; int err = 0; loff_t addr = (loff_t)ebnum * mtd->erasesize; - size_t len = mtd->ecclayout->oobavail * pgcnt; - size_t oobavail = mtd->ecclayout->oobavail; + size_t len = mtd->oobavail * pgcnt; + size_t oobavail = mtd->oobavail; size_t bitflips; int i; @@ -394,8 +394,8 @@ static int __init mtd_oobtest_init(void) goto out; use_offset = 0; - use_len = mtd->ecclayout->oobavail; - use_len_max = mtd->ecclayout->oobavail; + use_len = mtd->oobavail; + use_len_max = mtd->oobavail; vary_offset = 0; /* First test: write all OOB, read it back and verify */ @@ -460,8 +460,8 @@ static int __init mtd_oobtest_init(void) /* Write all eraseblocks */ use_offset = 0; - use_len = mtd->ecclayout->oobavail; - use_len_max = mtd->ecclayout->oobavail; + use_len = mtd->oobavail; + use_len_max = mtd->oobavail; vary_offset = 1; prandom_seed_state(&rnd_state, 5); @@ -471,8 +471,8 @@ static int __init mtd_oobtest_init(void) /* Check all eraseblocks */ use_offset = 0; - use_len = mtd->ecclayout->oobavail; - use_len_max = mtd->ecclayout->oobavail; + use_len = mtd->oobavail; + use_len_max = mtd->oobavail; vary_offset = 1; prandom_seed_state(&rnd_state, 5); err = verify_all_eraseblocks(); @@ -480,8 +480,8 @@ static int __init mtd_oobtest_init(void) goto out; use_offset = 0; - use_len = mtd->ecclayout->oobavail; - use_len_max = mtd->ecclayout->oobavail; + use_len = mtd->oobavail; + use_len_max = mtd->oobavail; vary_offset = 0; /* Fourth test: try to write off end of device */ @@ -501,7 +501,7 @@ static int __init mtd_oobtest_init(void) ops.retlen = 0; ops.ooblen = 1; ops.oobretlen = 0; - ops.ooboffs = mtd->ecclayout->oobavail; + ops.ooboffs = mtd->oobavail; ops.datbuf = NULL; ops.oobbuf = writebuf; pr_info("attempting to start write past end of OOB\n"); @@ -521,7 +521,7 @@ static int __init mtd_oobtest_init(void) ops.retlen = 0; ops.ooblen = 1; ops.oobretlen = 0; - ops.ooboffs = mtd->ecclayout->oobavail; + ops.ooboffs = mtd->oobavail; ops.datbuf = NULL; ops.oobbuf = readbuf; pr_info("attempting to start read past end of OOB\n"); @@ -543,7 +543,7 @@ static int __init mtd_oobtest_init(void) ops.mode = MTD_OPS_AUTO_OOB; ops.len = 0; ops.retlen = 0; - ops.ooblen = mtd->ecclayout->oobavail + 1; + ops.ooblen = mtd->oobavail + 1; ops.oobretlen = 0; ops.ooboffs = 0; ops.datbuf = NULL; @@ -563,7 +563,7 @@ static int __init mtd_oobtest_init(void) ops.mode = MTD_OPS_AUTO_OOB; ops.len = 0; ops.retlen = 0; - ops.ooblen = mtd->ecclayout->oobavail + 1; + ops.ooblen = mtd->oobavail + 1; ops.oobretlen = 0; ops.ooboffs = 0; ops.datbuf = NULL; @@ -587,7 +587,7 @@ static int __init mtd_oobtest_init(void) ops.mode = MTD_OPS_AUTO_OOB; ops.len = 0; ops.retlen = 0; - ops.ooblen = mtd->ecclayout->oobavail; + ops.ooblen = mtd->oobavail; ops.oobretlen = 0; ops.ooboffs = 1; ops.datbuf = NULL; @@ -607,7 +607,7 @@ static int __init mtd_oobtest_init(void) ops.mode = MTD_OPS_AUTO_OOB; ops.len = 0; ops.retlen = 0; - ops.ooblen = mtd->ecclayout->oobavail; + ops.ooblen = mtd->oobavail; ops.oobretlen = 0; ops.ooboffs = 1; ops.datbuf = NULL; @@ -638,7 +638,7 @@ static int __init mtd_oobtest_init(void) for (i = 0; i < ebcnt - 1; ++i) { int cnt = 2; int pg; - size_t sz = mtd->ecclayout->oobavail; + size_t sz = mtd->oobavail; if (bbt[i] || bbt[i + 1]) continue; addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize; @@ -673,13 +673,12 @@ static int __init mtd_oobtest_init(void) for (i = 0; i < ebcnt - 1; ++i) { if (bbt[i] || bbt[i + 1]) continue; - prandom_bytes_state(&rnd_state, writebuf, - mtd->ecclayout->oobavail * 2); + prandom_bytes_state(&rnd_state, writebuf, mtd->oobavail * 2); addr = (loff_t)(i + 1) * mtd->erasesize - mtd->writesize; ops.mode = MTD_OPS_AUTO_OOB; ops.len = 0; ops.retlen = 0; - ops.ooblen = mtd->ecclayout->oobavail * 2; + ops.ooblen = mtd->oobavail * 2; ops.oobretlen = 0; ops.ooboffs = 0; ops.datbuf = NULL; @@ -688,7 +687,7 @@ static int __init mtd_oobtest_init(void) if (err) goto out; if (memcmpshow(addr, readbuf, writebuf, - mtd->ecclayout->oobavail * 2)) { + mtd->oobavail * 2)) { pr_err("error: verify failed at %#llx\n", (long long)addr); errcnt += 1; -- cgit v1.1 From 29f1058a90b319b01c4cf469720e0350212d5c9c Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Mar 2016 10:46:52 +0100 Subject: mtd: create an mtd_oobavail() helper and make use of it Currently, all MTD drivers/sublayers exposing an OOB area are doing the same kind of test to extract the available OOB size based on the mtd_info and mtd_oob_ops structures. Move this common logic into an inline function and make use of it. Signed-off-by: Boris Brezillon Suggested-by: Priit Laes Signed-off-by: Brian Norris --- drivers/mtd/mtdpart.c | 5 +---- drivers/mtd/nand/nand_base.c | 16 ++++------------ drivers/mtd/onenand/onenand_base.c | 19 +++---------------- 3 files changed, 8 insertions(+), 32 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 10bf304..08de4b2 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -126,10 +126,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from, if (ops->oobbuf) { size_t len, pages; - if (ops->mode == MTD_OPS_AUTO_OOB) - len = mtd->oobavail; - else - len = mtd->oobsize; + len = mtd_oobavail(mtd, ops); pages = mtd_div_by_ws(mtd->size, mtd); pages -= mtd_div_by_ws(from, mtd); if (ops->ooboffs + ops->ooblen > pages * len) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 53993df..a36f15b 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1723,8 +1723,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, int ret = 0; uint32_t readlen = ops->len; uint32_t oobreadlen = ops->ooblen; - uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ? - mtd->oobavail : mtd->oobsize; + uint32_t max_oobsize = mtd_oobavail(mtd, ops); uint8_t *bufpoi, *oob, *buf; int use_bufpoi; @@ -2075,10 +2074,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, stats = mtd->ecc_stats; - if (ops->mode == MTD_OPS_AUTO_OOB) - len = mtd->oobavail; - else - len = mtd->oobsize; + len = mtd_oobavail(mtd, ops); if (unlikely(ops->ooboffs >= len)) { pr_debug("%s: attempt to start read outside oob\n", @@ -2575,8 +2571,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, uint32_t writelen = ops->len; uint32_t oobwritelen = ops->ooblen; - uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ? - mtd->oobavail : mtd->oobsize; + uint32_t oobmaxlen = mtd_oobavail(mtd, ops); uint8_t *oob = ops->oobbuf; uint8_t *buf = ops->datbuf; @@ -2766,10 +2761,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to, (int)ops->ooblen); - if (ops->mode == MTD_OPS_AUTO_OOB) - len = mtd->oobavail; - else - len = mtd->oobsize; + len = mtd_oobavail(mtd, ops); /* Do not allow write past end of page */ if ((ops->ooboffs + ops->ooblen) > len) { diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index df47537..af28bb3 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -1124,11 +1124,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from, (int)len); - if (ops->mode == MTD_OPS_AUTO_OOB) - oobsize = mtd->oobavail; - else - oobsize = mtd->oobsize; - + oobsize = mtd_oobavail(mtd, ops); oobcolumn = from & (mtd->oobsize - 1); /* Do not allow reads past end of device */ @@ -1229,11 +1225,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from, (int)len); - if (ops->mode == MTD_OPS_AUTO_OOB) - oobsize = mtd->oobavail; - else - oobsize = mtd->oobsize; - + oobsize = mtd_oobavail(mtd, ops); oobcolumn = from & (mtd->oobsize - 1); /* Do not allow reads past end of device */ @@ -1885,12 +1877,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, /* Check zero length */ if (!len) return 0; - - if (ops->mode == MTD_OPS_AUTO_OOB) - oobsize = mtd->oobavail; - else - oobsize = mtd->oobsize; - + oobsize = mtd_oobavail(mtd, ops); oobcolumn = to & (mtd->oobsize - 1); column = to & (mtd->writesize - 1); -- cgit v1.1 From f2de0fa64306651bc5aa04f6bb56c057658486d5 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Mar 2016 10:46:53 +0100 Subject: mtd: mtdswap: remove useless if (!mtd->ecclayout) test If the MTD device does not have OOB, the mtd->oobsize and mtd->oobavail fields are set to zero, and we are testing those values in the following test. Remove the useless if (!mtd->ecclayout) test. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/mtdswap.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c index d330eb1..cb06bdd 100644 --- a/drivers/mtd/mtdswap.c +++ b/drivers/mtd/mtdswap.c @@ -1417,7 +1417,6 @@ static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) unsigned long part; unsigned int eblocks, eavailable, bad_blocks, spare_cnt; uint64_t swap_size, use_size, size_limit; - struct nand_ecclayout *oinfo; int ret; parts = &partitions[0]; @@ -1447,13 +1446,6 @@ static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) return; } - oinfo = mtd->ecclayout; - if (!oinfo) { - printk(KERN_ERR "%s: mtd%d does not have OOB\n", - MTDSWAP_PREFIX, mtd->index); - return; - } - if (!mtd->oobsize || mtd->oobavail < MTDSWAP_OOBSIZE) { printk(KERN_ERR "%s: Not enough free bytes in OOB, " "%d available, %zu needed.\n", -- cgit v1.1 From a8c65d504e0b2256f7672506ae6ea68d88ef020a Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Mon, 7 Mar 2016 10:46:54 +0100 Subject: mtd: nand: simplify nand_bch_init() usage nand_bch_init() requires several arguments which could directly be deduced from the mtd device. Get rid of those useless parameters. nand_bch_init() is also requiring the caller to provide a proper eccbytes value, while this value could be deduced from the ecc.size and ecc.strength value. Fallback to eccbytes calculation when it is set to 0. Signed-off-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 6 ++---- drivers/mtd/nand/nand_bch.c | 27 +++++++++++++++++---------- drivers/mtd/nand/omap2.c | 28 ++++++++++++---------------- 3 files changed, 31 insertions(+), 30 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index a36f15b..191e4f7 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4279,10 +4279,8 @@ int nand_scan_tail(struct mtd_info *mtd) } /* See nand_bch_init() for details. */ - ecc->bytes = DIV_ROUND_UP( - ecc->strength * fls(8 * ecc->size), 8); - ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, - &ecc->layout); + ecc->bytes = 0; + ecc->priv = nand_bch_init(mtd); if (!ecc->priv) { pr_warn("BCH ECC initialization failed!\n"); BUG(); diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index a87c1b6..b585bae 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c @@ -107,9 +107,6 @@ EXPORT_SYMBOL(nand_bch_correct_data); /** * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction * @mtd: MTD block structure - * @eccsize: ecc block size in bytes - * @eccbytes: ecc length in bytes - * @ecclayout: output default layout * * Returns: * a pointer to a new NAND BCH control structure, or NULL upon failure @@ -123,14 +120,21 @@ EXPORT_SYMBOL(nand_bch_correct_data); * @eccsize = 512 (thus, m=13 is the smallest integer such that 2^m-1 > 512*8) * @eccbytes = 7 (7 bytes are required to store m*t = 13*4 = 52 bits) */ -struct nand_bch_control * -nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, - struct nand_ecclayout **ecclayout) +struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) { + struct nand_chip *nand = mtd_to_nand(mtd); unsigned int m, t, eccsteps, i; - struct nand_ecclayout *layout; + struct nand_ecclayout *layout = nand->ecc.layout; struct nand_bch_control *nbc = NULL; unsigned char *erased_page; + unsigned int eccsize = nand->ecc.size; + unsigned int eccbytes = nand->ecc.bytes; + unsigned int eccstrength = nand->ecc.strength; + + if (!eccbytes && eccstrength) { + eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8); + nand->ecc.bytes = eccbytes; + } if (!eccsize || !eccbytes) { printk(KERN_WARNING "ecc parameters not supplied\n"); @@ -158,7 +162,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, eccsteps = mtd->writesize/eccsize; /* if no ecc placement scheme was provided, build one */ - if (!*ecclayout) { + if (!layout) { /* handle large page devices only */ if (mtd->oobsize < 64) { @@ -184,7 +188,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, layout->oobfree[0].offset = 2; layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; - *ecclayout = layout; + nand->ecc.layout = layout; } /* sanity checks */ @@ -192,7 +196,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, printk(KERN_WARNING "eccsize %u is too large\n", eccsize); goto fail; } - if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) { + if (layout->eccbytes != (eccsteps*eccbytes)) { printk(KERN_WARNING "invalid ecc layout\n"); goto fail; } @@ -216,6 +220,9 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, for (i = 0; i < eccbytes; i++) nbc->eccmask[i] ^= 0xff; + if (!eccstrength) + nand->ecc.strength = (eccbytes * 8) / fls(8 * eccsize); + return nbc; fail: nand_bch_free(nbc); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index c553f78..0749ca1 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1807,13 +1807,19 @@ static int omap_nand_probe(struct platform_device *pdev) goto return_error; } + /* + * Bail out earlier to let NAND_ECC_SOFT code create its own + * ecclayout instead of using ours. + */ + if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) { + nand_chip->ecc.mode = NAND_ECC_SOFT; + goto scan_tail; + } + /* populate MTD interface based on ECC scheme */ ecclayout = &info->oobinfo; + nand_chip->ecc.layout = ecclayout; switch (info->ecc_opt) { - case OMAP_ECC_HAM1_CODE_SW: - nand_chip->ecc.mode = NAND_ECC_SOFT; - break; - case OMAP_ECC_HAM1_CODE_HW: pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n"); nand_chip->ecc.mode = NAND_ECC_HW; @@ -1861,10 +1867,7 @@ static int omap_nand_probe(struct platform_device *pdev) ecclayout->oobfree->offset = 1 + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; /* software bch library is used for locating errors */ - nand_chip->ecc.priv = nand_bch_init(mtd, - nand_chip->ecc.size, - nand_chip->ecc.bytes, - &ecclayout); + nand_chip->ecc.priv = nand_bch_init(mtd); if (!nand_chip->ecc.priv) { dev_err(&info->pdev->dev, "unable to use BCH library\n"); err = -EINVAL; @@ -1925,10 +1928,7 @@ static int omap_nand_probe(struct platform_device *pdev) ecclayout->oobfree->offset = 1 + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; /* software bch library is used for locating errors */ - nand_chip->ecc.priv = nand_bch_init(mtd, - nand_chip->ecc.size, - nand_chip->ecc.bytes, - &ecclayout); + nand_chip->ecc.priv = nand_bch_init(mtd); if (!nand_chip->ecc.priv) { dev_err(&info->pdev->dev, "unable to use BCH library\n"); err = -EINVAL; @@ -2002,9 +2002,6 @@ static int omap_nand_probe(struct platform_device *pdev) goto return_error; } - if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) - goto scan_tail; - /* all OOB bytes from oobfree->offset till end off OOB are free */ ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset; /* check if NAND device's OOB is enough to store ECC signatures */ @@ -2015,7 +2012,6 @@ static int omap_nand_probe(struct platform_device *pdev) err = -EINVAL; goto return_error; } - nand_chip->ecc.layout = ecclayout; scan_tail: /* second phase scan */ -- cgit v1.1 From edf891ef9ab773363f8e58022a26d7d31604aed6 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 29 Jan 2016 11:25:30 -0800 Subject: mtd: spi-nor: wait for SR_WIP to clear on initial unlock Fixup a piece leftover by commit 32321e950d8a ("mtd: spi-nor: wait until lock/unlock operations are ready"). That commit made us wait for the WIP bit to settle after lock/unlock operations, but it missed the open-coded "unlock" that happens at probe() time. We should probably have this code utilize the unlock() routines in the future, to avoid duplication, but unfortunately, flash which need to be unlocked don't all have a proper ->flash_unlock() callback. Signed-off-by: Brian Norris Cc: Stas Sergeev Reviewed-by: Ezequiel Garcia Tested-by: Ezequiel Garcia --- drivers/mtd/spi-nor/spi-nor.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 03e5e44..a9b3bdf2 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1193,6 +1193,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) JEDEC_MFR(info) == SNOR_MFR_SST) { write_enable(nor); write_sr(nor, 0); + spi_nor_wait_till_ready(nor); } if (!mtd->name) -- cgit v1.1 From 4c0dba447ef4a97dfbae6e876312e952667eddc4 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 29 Jan 2016 11:25:31 -0800 Subject: mtd: spi-nor: silently drop lock/unlock for already locked/unlocked region If, for instance, the entire flash is already unlocked and I try to mtd_unlock() the entire device, I don't expect to see an EINVAL error. It should just silently succeed. Ditto for mtd_lock(). Signed-off-by: Brian Norris Reviewed-by: Ezequiel Garcia Tested-by: Ezequiel Garcia --- drivers/mtd/spi-nor/spi-nor.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index a9b3bdf2..3dde727 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -515,8 +515,12 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) status_new = (status_old & ~mask) | val; + /* Don't bother if they're the same */ + if (status_new == status_old) + return 0; + /* Only modify protection if it will not unlock other areas */ - if ((status_new & mask) <= (status_old & mask)) + if ((status_new & mask) < (status_old & mask)) return -EINVAL; write_enable(nor); @@ -569,8 +573,12 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) status_new = (status_old & ~mask) | val; + /* Don't bother if they're the same */ + if (status_new == status_old) + return 0; + /* Only modify protection if it will not lock other areas */ - if ((status_new & mask) >= (status_old & mask)) + if ((status_new & mask) > (status_old & mask)) return -EINVAL; write_enable(nor); -- cgit v1.1 From f8860802da84aa2bbc9f316e549a349fb40cda63 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 29 Jan 2016 11:25:32 -0800 Subject: mtd: spi-nor: make lock/unlock bounds checks more obvious and robust There are a few different corner cases to the current logic that seem undesirable: * mtd_lock() with offs==0 trips a bounds issue on ofs - mtd->erasesize < 0 * mtd_unlock() on the middle of a flash that is already unlocked will return -EINVAL * probably other corner cases So, let's stop doing "smart" checks like "check the block below us", let's just do the following: (a) pass only non-negative offsets/lengths to stm_is_locked_sr() (b) add a similar stm_is_unlocked_sr() function, so we can check if the *entire* range is unlocked (and not just whether some part of it is unlocked) Then armed with (b), we can make lock() and unlock() much more symmetric: (c) short-circuit the procedure if there is no work to be done, and (d) check the entire range above/below This also aligns well with the structure needed for proper TB (Top/Bottom) support. Signed-off-by: Brian Norris Tested-by: Ezequiel Garcia --- drivers/mtd/spi-nor/spi-nor.c | 68 +++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 18 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 3dde727..680bc15 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -439,17 +439,38 @@ static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, } /* - * Return 1 if the entire region is locked, 0 otherwise + * Return 1 if the entire region is locked (if @locked is true) or unlocked (if + * @locked is false); 0 otherwise */ -static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, - u8 sr) +static int stm_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, + u8 sr, bool locked) { loff_t lock_offs; uint64_t lock_len; + if (!len) + return 1; + stm_get_locked_range(nor, sr, &lock_offs, &lock_len); - return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); + if (locked) + /* Requested range is a sub-range of locked range */ + return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); + else + /* Requested range does not overlap with locked range */ + return (ofs >= lock_offs + lock_len) || (ofs + len <= lock_offs); +} + +static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, + u8 sr) +{ + return stm_check_lock_status_sr(nor, ofs, len, sr, true); +} + +static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, + u8 sr) +{ + return stm_check_lock_status_sr(nor, ofs, len, sr, false); } /* @@ -481,20 +502,24 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) int status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; + loff_t lock_len; int ret; status_old = read_sr(nor); if (status_old < 0) return status_old; - /* SPI NOR always locks to the end */ - if (ofs + len != mtd->size) { - /* Does combined region extend to end? */ - if (!stm_is_locked_sr(nor, ofs + len, mtd->size - ofs - len, - status_old)) - return -EINVAL; - len = mtd->size - ofs; - } + /* If nothing in our range is unlocked, we don't need to do anything */ + if (stm_is_locked_sr(nor, ofs, len, status_old)) + return 0; + + /* If anything above us is unlocked, we can't use 'top' protection */ + if (!stm_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), + status_old)) + return -EINVAL; + + /* lock_len: length of region that should end up locked */ + lock_len = mtd->size - ofs; /* * Need smallest pow such that: @@ -505,7 +530,7 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) * * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) */ - pow = ilog2(mtd->size) - ilog2(len); + pow = ilog2(mtd->size) - ilog2(lock_len); val = mask - (pow << shift); if (val & ~mask) return -EINVAL; @@ -541,17 +566,24 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) int status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; + loff_t lock_len; int ret; status_old = read_sr(nor); if (status_old < 0) return status_old; - /* Cannot unlock; would unlock larger region than requested */ - if (stm_is_locked_sr(nor, ofs - mtd->erasesize, mtd->erasesize, - status_old)) + /* If nothing in our range is locked, we don't need to do anything */ + if (stm_is_unlocked_sr(nor, ofs, len, status_old)) + return 0; + + /* If anything below us is locked, we can't use 'top' protection */ + if (!stm_is_unlocked_sr(nor, 0, ofs, status_old)) return -EINVAL; + /* lock_len: length of region that should remain locked */ + lock_len = mtd->size - (ofs + len); + /* * Need largest pow such that: * @@ -561,8 +593,8 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) * * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) */ - pow = ilog2(mtd->size) - order_base_2(mtd->size - (ofs + len)); - if (ofs + len == mtd->size) { + pow = ilog2(mtd->size) - order_base_2(lock_len); + if (lock_len == 0) { val = 0; /* fully unlocked */ } else { val = mask - (pow << shift); -- cgit v1.1 From 47b8edbf0d43dcb9fda83833c05470edf59c31e3 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 29 Jan 2016 11:25:33 -0800 Subject: mtd: spi-nor: disallow further writes to SR if WP# is low Locking the flash is most useful if it provides real hardware security. Otherwise, it's little more than a software permission bit. A reasonable use case that provides real HW security might be like follows: (1) hardware WP# is deasserted (2) program flash (3) flash range is protected via status register (4) hardware WP# is asserted (5) flash protection range can no longer be changed, until WP# is deasserted In this way, flash protection is co-owned by hardware and software. Now, one would expect to be able to perform step (3) with ioctl(MEMLOCK), except that the spi-nor driver does not set the Status Register Protect bit (a.k.a. Status Register Write Disable (SRWD)), so even though the range is now locked, it does not satisfy step (5) -- it can still be changed by a call to ioctl(MEMUNLOCK). So, let's enable status register protection after the first lock command, and disable protection only when the flash is fully unlocked. Signed-off-by: Brian Norris Tested-by: Ezequiel Garcia --- drivers/mtd/spi-nor/spi-nor.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 680bc15..6fcd9d7 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -540,6 +540,9 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) status_new = (status_old & ~mask) | val; + /* Disallow further writes if WP pin is asserted */ + status_new |= SR_SRWD; + /* Don't bother if they're the same */ if (status_new == status_old) return 0; @@ -605,6 +608,10 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) status_new = (status_old & ~mask) | val; + /* Don't protect status register if we're fully unlocked */ + if (lock_len == mtd->size) + status_new &= ~SR_SRWD; + /* Don't bother if they're the same */ if (status_new == status_old) return 0; -- cgit v1.1 From 0618114e2c5dd059f8d22787e62e3f1723af68fc Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 29 Jan 2016 11:25:34 -0800 Subject: mtd: spi-nor: use BIT() for flash_info flags It's a little easier to read and make sure there are no collisions (IMO). Signed-off-by: Brian Norris Reviewed-by: Ezequiel Garcia Tested-by: Ezequiel Garcia --- drivers/mtd/spi-nor/spi-nor.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 6fcd9d7..72d87c2 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -61,14 +61,14 @@ struct flash_info { u16 addr_width; u16 flags; -#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ -#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ -#define SST_WRITE 0x04 /* use SST byte programming */ -#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ -#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ -#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ -#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ -#define USE_FSR 0x80 /* use flag status register */ +#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */ +#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */ +#define SST_WRITE BIT(2) /* use SST byte programming */ +#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */ +#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ +#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ +#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ +#define USE_FSR BIT(7) /* use flag status register */ }; #define JEDEC_MFR(info) ((info)->id[0]) -- cgit v1.1 From 76a4707de5e18dc32d9cb4e990686140c5664a15 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 29 Jan 2016 11:25:35 -0800 Subject: mtd: spi-nor: add SPI_NOR_HAS_LOCK flag We can't determine this purely by manufacturer type (see commit 67b9bcd36906 ("mtd: spi-nor: fix Spansion regressions (aliased with Winbond)")), and it's not autodetectable by anything like SFDP. So make a new flag for it. Signed-off-by: Brian Norris Reviewed-by: Ezequiel Garcia Tested-by: Ezequiel Garcia --- drivers/mtd/spi-nor/spi-nor.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 72d87c2..d1edafc 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -69,6 +69,7 @@ struct flash_info { #define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ #define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ #define USE_FSR BIT(7) /* use flag status register */ +#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ }; #define JEDEC_MFR(info) ((info)->id[0]) @@ -1237,7 +1238,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || JEDEC_MFR(info) == SNOR_MFR_INTEL || - JEDEC_MFR(info) == SNOR_MFR_SST) { + JEDEC_MFR(info) == SNOR_MFR_SST || + info->flags & SPI_NOR_HAS_LOCK) { write_enable(nor); write_sr(nor, 0); spi_nor_wait_till_ready(nor); @@ -1254,7 +1256,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) mtd->_read = spi_nor_read; /* NOR protection support for STmicro/Micron chips and similar */ - if (JEDEC_MFR(info) == SNOR_MFR_MICRON) { + if (JEDEC_MFR(info) == SNOR_MFR_MICRON || + info->flags & SPI_NOR_HAS_LOCK) { nor->flash_lock = stm_lock; nor->flash_unlock = stm_unlock; nor->flash_is_locked = stm_is_locked; -- cgit v1.1 From 3dd8012a8eeb3702fa17450ec1a16a3f38af138d Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 29 Jan 2016 11:25:36 -0800 Subject: mtd: spi-nor: add TB (Top/Bottom) protect support Some flash support a bit in the status register that inverts protection so that it applies to the bottom of the flash, not the top. This yields additions to the protection range table, as noted in the comments. Because this feature is not universal to all flash that support lock/unlock, control it via a new flag. Signed-off-by: Brian Norris Tested-by: Ezequiel Garcia --- drivers/mtd/spi-nor/spi-nor.c | 70 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 7 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index d1edafc..2aebf18 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -70,6 +70,11 @@ struct flash_info { #define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ #define USE_FSR BIT(7) /* use flag status register */ #define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ +#define SPI_NOR_HAS_TB BIT(9) /* + * Flash SR has Top/Bottom (TB) protect + * bit. Must be used with + * SPI_NOR_HAS_LOCK. + */ }; #define JEDEC_MFR(info) ((info)->id[0]) @@ -435,7 +440,10 @@ static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, } else { pow = ((sr & mask) ^ mask) >> shift; *len = mtd->size >> pow; - *ofs = mtd->size - *len; + if (nor->flags & SNOR_F_HAS_SR_TB && sr & SR_TB) + *ofs = 0; + else + *ofs = mtd->size - *len; } } @@ -476,12 +484,14 @@ static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, /* * Lock a region of the flash. Compatible with ST Micro and similar flash. - * Supports only the block protection bits BP{0,1,2} in the status register + * Supports the block protection bits BP{0,1,2} in the status register * (SR). Does not support these features found in newer SR bitfields: - * - TB: top/bottom protect - only handle TB=0 (top protect) * - SEC: sector/block protect - only handle SEC=0 (block protect) * - CMP: complement protect - only support CMP=0 (range is not complemented) * + * Support for the following is provided conditionally for some flash: + * - TB: top/bottom protect + * * Sample table portion for 8MB flash (Winbond w25q64fw): * * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion @@ -494,6 +504,13 @@ static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 * X | X | 1 | 1 | 1 | 8 MB | ALL + * ------|-------|-------|-------|-------|---------------|------------------- + * 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64 + * 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32 + * 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16 + * 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8 + * 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4 + * 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2 * * Returns negative on errors, 0 on success. */ @@ -504,6 +521,8 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; loff_t lock_len; + bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; + bool use_top; int ret; status_old = read_sr(nor); @@ -514,13 +533,26 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) if (stm_is_locked_sr(nor, ofs, len, status_old)) return 0; + /* If anything below us is unlocked, we can't use 'bottom' protection */ + if (!stm_is_locked_sr(nor, 0, ofs, status_old)) + can_be_bottom = false; + /* If anything above us is unlocked, we can't use 'top' protection */ if (!stm_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), status_old)) + can_be_top = false; + + if (!can_be_bottom && !can_be_top) return -EINVAL; + /* Prefer top, if both are valid */ + use_top = can_be_top; + /* lock_len: length of region that should end up locked */ - lock_len = mtd->size - ofs; + if (use_top) + lock_len = mtd->size - ofs; + else + lock_len = ofs + len; /* * Need smallest pow such that: @@ -539,11 +571,14 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) if (!(val & mask)) return -EINVAL; - status_new = (status_old & ~mask) | val; + status_new = (status_old & ~mask & ~SR_TB) | val; /* Disallow further writes if WP pin is asserted */ status_new |= SR_SRWD; + if (!use_top) + status_new |= SR_TB; + /* Don't bother if they're the same */ if (status_new == status_old) return 0; @@ -571,6 +606,8 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; loff_t lock_len; + bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; + bool use_top; int ret; status_old = read_sr(nor); @@ -583,10 +620,24 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) /* If anything below us is locked, we can't use 'top' protection */ if (!stm_is_unlocked_sr(nor, 0, ofs, status_old)) + can_be_top = false; + + /* If anything above us is locked, we can't use 'bottom' protection */ + if (!stm_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len), + status_old)) + can_be_bottom = false; + + if (!can_be_bottom && !can_be_top) return -EINVAL; + /* Prefer top, if both are valid */ + use_top = can_be_top; + /* lock_len: length of region that should remain locked */ - lock_len = mtd->size - (ofs + len); + if (use_top) + lock_len = mtd->size - (ofs + len); + else + lock_len = ofs; /* * Need largest pow such that: @@ -607,12 +658,15 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) return -EINVAL; } - status_new = (status_old & ~mask) | val; + status_new = (status_old & ~mask & ~SR_TB) | val; /* Don't protect status register if we're fully unlocked */ if (lock_len == mtd->size) status_new &= ~SR_SRWD; + if (!use_top) + status_new |= SR_TB; + /* Don't bother if they're the same */ if (status_new == status_old) return 0; @@ -1277,6 +1331,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) if (info->flags & USE_FSR) nor->flags |= SNOR_F_USE_FSR; + if (info->flags & SPI_NOR_HAS_TB) + nor->flags |= SNOR_F_HAS_SR_TB; #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS /* prefer "small sector" erase if possible */ -- cgit v1.1 From 9648388fc7737365be7a8092e77df78ccc2cd1a4 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 29 Jan 2016 11:25:37 -0800 Subject: mtd: spi-nor: support lock/unlock for a few Winbond chips These are recent Winbond models that are known to have lock/unlock support via writing the Status Register, and that also support the TB (Top/Bottom) protection bit. Tested on w25q32dw. [Note on style: these entries are getting pretty long lines, so I picked a style that seems reasonable for splitting up the flags separate from the other mostly-similar fields.] Signed-off-by: Brian Norris Reviewed-by: Ezequiel Garcia Tested-by: Ezequiel Garcia --- drivers/mtd/spi-nor/spi-nor.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 2aebf18..157841d 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -963,11 +963,23 @@ static const struct flash_info spi_nor_ids[] = { { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, - { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { + "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, - { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, - { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { + "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, -- cgit v1.1 From 9f3e04297b08212ef43fce4f167e01f40a98d243 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 3 Feb 2016 14:29:49 +0530 Subject: mtd: nand: don't select chip in nand_chip's block_bad op One of the arguments passed to struct nand_chip's block_bad op is 'getchip', which, if true, is supposed to get and select the nand device, and later unselect and release the device. This op is intended to be replaceable by drivers. The drivers shouldn't be responsible for selecting/unselecting chip. Like other ops, the chip should already be selected before the block_bad op is called. Remove the getchip argument from the block_bad op and nand_block_checkbad. Move the chip selection to nand_block_isbad, since it is the only caller to nand_block_checkbad which requires chip selection. Modify nand_block_bad (the default function for the op) such that it doesn't select the chip. Remove the getchip argument from the bad_block funcs in cafe_nand, diskonchip and docg4 drivers. Reviewed-by: Boris Brezillon Signed-off-by: Archit Taneja Signed-off-by: Brian Norris --- drivers/mtd/nand/cafe_nand.c | 2 +- drivers/mtd/nand/diskonchip.c | 2 +- drivers/mtd/nand/docg4.c | 2 +- drivers/mtd/nand/nand_base.c | 41 +++++++++++++++++++---------------------- 4 files changed, 22 insertions(+), 25 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index aa1a616..e553aff 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -537,7 +537,7 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd, return 0; } -static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs) { return 0; } diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index f170f3c..547c100 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -794,7 +794,7 @@ static int doc200x_dev_ready(struct mtd_info *mtd) } } -static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs) { /* This is our last resort if we couldn't find or create a BBT. Just pretend all blocks are good. */ diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index fb46fd7..d86a60e 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c @@ -1120,7 +1120,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) return ret; } -static int docg4_block_neverbad(struct mtd_info *mtd, loff_t ofs, int getchip) +static int docg4_block_neverbad(struct mtd_info *mtd, loff_t ofs) { /* only called when module_param ignore_badblocks is set */ return 0; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 191e4f7..d49b01d 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -317,9 +317,9 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) * * Check, if the block is bad. */ -static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +static int nand_block_bad(struct mtd_info *mtd, loff_t ofs) { - int page, chipnr, res = 0, i = 0; + int page, res = 0, i = 0; struct nand_chip *chip = mtd_to_nand(mtd); u16 bad; @@ -328,15 +328,6 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) page = (int)(ofs >> chip->page_shift) & chip->pagemask; - if (getchip) { - chipnr = (int)(ofs >> chip->chip_shift); - - nand_get_device(mtd, FL_READING); - - /* Select the NAND device */ - chip->select_chip(mtd, chipnr); - } - do { if (chip->options & NAND_BUSWIDTH_16) { chip->cmdfunc(mtd, NAND_CMD_READOOB, @@ -361,11 +352,6 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) i++; } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE)); - if (getchip) { - chip->select_chip(mtd, -1); - nand_release_device(mtd); - } - return res; } @@ -503,19 +489,17 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs) * nand_block_checkbad - [GENERIC] Check if a block is marked bad * @mtd: MTD device structure * @ofs: offset from device start - * @getchip: 0, if the chip is already selected * @allowbbt: 1, if its allowed to access the bbt area * * Check, if the block is bad. Either by reading the bad block table or * calling of the scan function. */ -static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, - int allowbbt) +static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt) { struct nand_chip *chip = mtd_to_nand(mtd); if (!chip->bbt) - return chip->block_bad(mtd, ofs, getchip); + return chip->block_bad(mtd, ofs); /* Return info from the table */ return nand_isbad_bbt(mtd, ofs, allowbbt); @@ -2949,7 +2933,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, while (len) { /* Check if we have a bad block, we do not erase bad blocks! */ if (nand_block_checkbad(mtd, ((loff_t) page) << - chip->page_shift, 0, allowbbt)) { + chip->page_shift, allowbbt)) { pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", __func__, page); instr->state = MTD_ERASE_FAILED; @@ -3036,7 +3020,20 @@ static void nand_sync(struct mtd_info *mtd) */ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) { - return nand_block_checkbad(mtd, offs, 1, 0); + struct nand_chip *chip = mtd_to_nand(mtd); + int chipnr = (int)(offs >> chip->chip_shift); + int ret; + + /* Select the NAND device */ + nand_get_device(mtd, FL_READING); + chip->select_chip(mtd, chipnr); + + ret = nand_block_checkbad(mtd, offs, 0); + + chip->select_chip(mtd, -1); + nand_release_device(mtd); + + return ret; } /** -- cgit v1.1 From c76b78d8ec05a247975542061df3f1321783f98d Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 3 Feb 2016 14:29:50 +0530 Subject: mtd: nand: Qualcomm NAND controller driver The Qualcomm NAND controller is found in SoCs like IPQ806x, MSM7xx, MDM9x15 series. It exists as a sub block inside the IPs EBI2 (External Bus Interface 2) and QPIC (Qualcomm Parallel Interface Controller). These IPs provide a broader interface for external slow peripheral devices such as LCD and NAND/NOR flash memory or SRAM like interfaces. We add support for the NAND controller found within EBI2. For the SoCs of our interest, we only use the NAND controller within EBI2. Therefore, it's safe for us to assume that the NAND controller is a standalone block within the SoC. The controller supports 512B, 2kB, 4kB and 8kB page 8-bit and 16-bit NAND flash devices. It contains a HW ECC block that supports BCH ECC (4, 8 and 16 bit correction/step) and RS ECC(4 bit correction/step) that covers main and spare data. The controller contains an internal 512 byte page buffer to which we read/write via DMA. The EBI2 type NAND controller uses ADM DMA for register read/write and data transfers. The controller performs page reads and writes at a codeword/step level of 512 bytes. It can support up to 2 external chips of different configurations. The driver prepares register read and write configuration descriptors for each codeword, followed by data descriptors to read or write data from the controller's internal buffer. It uses a single ADM DMA channel that we get via dmaengine API. The controller requires 2 ADM CRCIs for command and data flow control. These are passed via DT. The ecc layout used by the controller is syndrome like, but we can't use the standard syndrome ecc ops because of several reasons. First, the amount of data bytes covered by ecc isn't same in each step. Second, writing to free oob space requires us writing to the entire step in which the oob lies. This forces us to create our own ecc ops. One more difference is how the controller accesses the bad block marker. The controller ignores reading the marker when ECC is enabled. ECC needs to be explicity disabled to read or write to the bad block marker. The nand_bbt helpers library hence can't access BBMs for the controller. For now, we skip the creation of BBT and populate chip->block_bad and chip->block_markbad helpers instead. Reviewed-by: Andy Gross Signed-off-by: Stephen Boyd Signed-off-by: Archit Taneja Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/Kconfig | 7 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/qcom_nandc.c | 2223 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2231 insertions(+) create mode 100644 drivers/mtd/nand/qcom_nandc.c (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index b253654..f05e0e9 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -556,4 +556,11 @@ config MTD_NAND_HISI504 help Enables support for NAND controller on Hisilicon SoC Hip04. +config MTD_NAND_QCOM + tristate "Support for NAND on QCOM SoCs" + depends on ARCH_QCOM + help + Enables support for NAND flash chips on SoCs containing the EBI2 NAND + controller. This controller is found on IPQ806x SoC. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 9e36233..f553353 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -56,5 +56,6 @@ obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ +obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o nand-objs := nand_base.o nand_bbt.o nand_timings.o diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c new file mode 100644 index 0000000..f550a57 --- /dev/null +++ b/drivers/mtd/nand/qcom_nandc.c @@ -0,0 +1,2223 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* NANDc reg offsets */ +#define NAND_FLASH_CMD 0x00 +#define NAND_ADDR0 0x04 +#define NAND_ADDR1 0x08 +#define NAND_FLASH_CHIP_SELECT 0x0c +#define NAND_EXEC_CMD 0x10 +#define NAND_FLASH_STATUS 0x14 +#define NAND_BUFFER_STATUS 0x18 +#define NAND_DEV0_CFG0 0x20 +#define NAND_DEV0_CFG1 0x24 +#define NAND_DEV0_ECC_CFG 0x28 +#define NAND_DEV1_ECC_CFG 0x2c +#define NAND_DEV1_CFG0 0x30 +#define NAND_DEV1_CFG1 0x34 +#define NAND_READ_ID 0x40 +#define NAND_READ_STATUS 0x44 +#define NAND_DEV_CMD0 0xa0 +#define NAND_DEV_CMD1 0xa4 +#define NAND_DEV_CMD2 0xa8 +#define NAND_DEV_CMD_VLD 0xac +#define SFLASHC_BURST_CFG 0xe0 +#define NAND_ERASED_CW_DETECT_CFG 0xe8 +#define NAND_ERASED_CW_DETECT_STATUS 0xec +#define NAND_EBI2_ECC_BUF_CFG 0xf0 +#define FLASH_BUF_ACC 0x100 + +#define NAND_CTRL 0xf00 +#define NAND_VERSION 0xf08 +#define NAND_READ_LOCATION_0 0xf20 +#define NAND_READ_LOCATION_1 0xf24 + +/* dummy register offsets, used by write_reg_dma */ +#define NAND_DEV_CMD1_RESTORE 0xdead +#define NAND_DEV_CMD_VLD_RESTORE 0xbeef + +/* NAND_FLASH_CMD bits */ +#define PAGE_ACC BIT(4) +#define LAST_PAGE BIT(5) + +/* NAND_FLASH_CHIP_SELECT bits */ +#define NAND_DEV_SEL 0 +#define DM_EN BIT(2) + +/* NAND_FLASH_STATUS bits */ +#define FS_OP_ERR BIT(4) +#define FS_READY_BSY_N BIT(5) +#define FS_MPU_ERR BIT(8) +#define FS_DEVICE_STS_ERR BIT(16) +#define FS_DEVICE_WP BIT(23) + +/* NAND_BUFFER_STATUS bits */ +#define BS_UNCORRECTABLE_BIT BIT(8) +#define BS_CORRECTABLE_ERR_MSK 0x1f + +/* NAND_DEVn_CFG0 bits */ +#define DISABLE_STATUS_AFTER_WRITE 4 +#define CW_PER_PAGE 6 +#define UD_SIZE_BYTES 9 +#define ECC_PARITY_SIZE_BYTES_RS 19 +#define SPARE_SIZE_BYTES 23 +#define NUM_ADDR_CYCLES 27 +#define STATUS_BFR_READ 30 +#define SET_RD_MODE_AFTER_STATUS 31 + +/* NAND_DEVn_CFG0 bits */ +#define DEV0_CFG1_ECC_DISABLE 0 +#define WIDE_FLASH 1 +#define NAND_RECOVERY_CYCLES 2 +#define CS_ACTIVE_BSY 5 +#define BAD_BLOCK_BYTE_NUM 6 +#define BAD_BLOCK_IN_SPARE_AREA 16 +#define WR_RD_BSY_GAP 17 +#define ENABLE_BCH_ECC 27 + +/* NAND_DEV0_ECC_CFG bits */ +#define ECC_CFG_ECC_DISABLE 0 +#define ECC_SW_RESET 1 +#define ECC_MODE 4 +#define ECC_PARITY_SIZE_BYTES_BCH 8 +#define ECC_NUM_DATA_BYTES 16 +#define ECC_FORCE_CLK_OPEN 30 + +/* NAND_DEV_CMD1 bits */ +#define READ_ADDR 0 + +/* NAND_DEV_CMD_VLD bits */ +#define READ_START_VLD 0 + +/* NAND_EBI2_ECC_BUF_CFG bits */ +#define NUM_STEPS 0 + +/* NAND_ERASED_CW_DETECT_CFG bits */ +#define ERASED_CW_ECC_MASK 1 +#define AUTO_DETECT_RES 0 +#define MASK_ECC (1 << ERASED_CW_ECC_MASK) +#define RESET_ERASED_DET (1 << AUTO_DETECT_RES) +#define ACTIVE_ERASED_DET (0 << AUTO_DETECT_RES) +#define CLR_ERASED_PAGE_DET (RESET_ERASED_DET | MASK_ECC) +#define SET_ERASED_PAGE_DET (ACTIVE_ERASED_DET | MASK_ECC) + +/* NAND_ERASED_CW_DETECT_STATUS bits */ +#define PAGE_ALL_ERASED BIT(7) +#define CODEWORD_ALL_ERASED BIT(6) +#define PAGE_ERASED BIT(5) +#define CODEWORD_ERASED BIT(4) +#define ERASED_PAGE (PAGE_ALL_ERASED | PAGE_ERASED) +#define ERASED_CW (CODEWORD_ALL_ERASED | CODEWORD_ERASED) + +/* Version Mask */ +#define NAND_VERSION_MAJOR_MASK 0xf0000000 +#define NAND_VERSION_MAJOR_SHIFT 28 +#define NAND_VERSION_MINOR_MASK 0x0fff0000 +#define NAND_VERSION_MINOR_SHIFT 16 + +/* NAND OP_CMDs */ +#define PAGE_READ 0x2 +#define PAGE_READ_WITH_ECC 0x3 +#define PAGE_READ_WITH_ECC_SPARE 0x4 +#define PROGRAM_PAGE 0x6 +#define PAGE_PROGRAM_WITH_ECC 0x7 +#define PROGRAM_PAGE_SPARE 0x9 +#define BLOCK_ERASE 0xa +#define FETCH_ID 0xb +#define RESET_DEVICE 0xd + +/* + * the NAND controller performs reads/writes with ECC in 516 byte chunks. + * the driver calls the chunks 'step' or 'codeword' interchangeably + */ +#define NANDC_STEP_SIZE 512 + +/* + * the largest page size we support is 8K, this will have 16 steps/codewords + * of 512 bytes each + */ +#define MAX_NUM_STEPS (SZ_8K / NANDC_STEP_SIZE) + +/* we read at most 3 registers per codeword scan */ +#define MAX_REG_RD (3 * MAX_NUM_STEPS) + +/* ECC modes supported by the controller */ +#define ECC_NONE BIT(0) +#define ECC_RS_4BIT BIT(1) +#define ECC_BCH_4BIT BIT(2) +#define ECC_BCH_8BIT BIT(3) + +struct desc_info { + struct list_head node; + + enum dma_data_direction dir; + struct scatterlist sgl; + struct dma_async_tx_descriptor *dma_desc; +}; + +/* + * holds the current register values that we want to write. acts as a contiguous + * chunk of memory which we use to write the controller registers through DMA. + */ +struct nandc_regs { + __le32 cmd; + __le32 addr0; + __le32 addr1; + __le32 chip_sel; + __le32 exec; + + __le32 cfg0; + __le32 cfg1; + __le32 ecc_bch_cfg; + + __le32 clrflashstatus; + __le32 clrreadstatus; + + __le32 cmd1; + __le32 vld; + + __le32 orig_cmd1; + __le32 orig_vld; + + __le32 ecc_buf_cfg; +}; + +/* + * NAND controller data struct + * + * @controller: base controller structure + * @host_list: list containing all the chips attached to the + * controller + * @dev: parent device + * @base: MMIO base + * @base_dma: physical base address of controller registers + * @core_clk: controller clock + * @aon_clk: another controller clock + * + * @chan: dma channel + * @cmd_crci: ADM DMA CRCI for command flow control + * @data_crci: ADM DMA CRCI for data flow control + * @desc_list: DMA descriptor list (list of desc_infos) + * + * @data_buffer: our local DMA buffer for page read/writes, + * used when we can't use the buffer provided + * by upper layers directly + * @buf_size/count/start: markers for chip->read_buf/write_buf functions + * @reg_read_buf: local buffer for reading back registers via DMA + * @reg_read_pos: marker for data read in reg_read_buf + * + * @regs: a contiguous chunk of memory for DMA register + * writes. contains the register values to be + * written to controller + * @cmd1/vld: some fixed controller register values + * @ecc_modes: supported ECC modes by the current controller, + * initialized via DT match data + */ +struct qcom_nand_controller { + struct nand_hw_control controller; + struct list_head host_list; + + struct device *dev; + + void __iomem *base; + dma_addr_t base_dma; + + struct clk *core_clk; + struct clk *aon_clk; + + struct dma_chan *chan; + unsigned int cmd_crci; + unsigned int data_crci; + struct list_head desc_list; + + u8 *data_buffer; + int buf_size; + int buf_count; + int buf_start; + + __le32 *reg_read_buf; + int reg_read_pos; + + struct nandc_regs *regs; + + u32 cmd1, vld; + u32 ecc_modes; +}; + +/* + * NAND chip structure + * + * @chip: base NAND chip structure + * @node: list node to add itself to host_list in + * qcom_nand_controller + * + * @cs: chip select value for this chip + * @cw_size: the number of bytes in a single step/codeword + * of a page, consisting of all data, ecc, spare + * and reserved bytes + * @cw_data: the number of bytes within a codeword protected + * by ECC + * @use_ecc: request the controller to use ECC for the + * upcoming read/write + * @bch_enabled: flag to tell whether BCH ECC mode is used + * @ecc_bytes_hw: ECC bytes used by controller hardware for this + * chip + * @status: value to be returned if NAND_CMD_STATUS command + * is executed + * @last_command: keeps track of last command on this chip. used + * for reading correct status + * + * @cfg0, cfg1, cfg0_raw..: NANDc register configurations needed for + * ecc/non-ecc mode for the current nand flash + * device + */ +struct qcom_nand_host { + struct nand_chip chip; + struct list_head node; + + int cs; + int cw_size; + int cw_data; + bool use_ecc; + bool bch_enabled; + int ecc_bytes_hw; + int spare_bytes; + int bbm_size; + u8 status; + int last_command; + + u32 cfg0, cfg1; + u32 cfg0_raw, cfg1_raw; + u32 ecc_buf_cfg; + u32 ecc_bch_cfg; + u32 clrflashstatus; + u32 clrreadstatus; +}; + +static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip) +{ + return container_of(chip, struct qcom_nand_host, chip); +} + +static inline struct qcom_nand_controller * +get_qcom_nand_controller(struct nand_chip *chip) +{ + return container_of(chip->controller, struct qcom_nand_controller, + controller); +} + +static inline u32 nandc_read(struct qcom_nand_controller *nandc, int offset) +{ + return ioread32(nandc->base + offset); +} + +static inline void nandc_write(struct qcom_nand_controller *nandc, int offset, + u32 val) +{ + iowrite32(val, nandc->base + offset); +} + +static __le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset) +{ + switch (offset) { + case NAND_FLASH_CMD: + return ®s->cmd; + case NAND_ADDR0: + return ®s->addr0; + case NAND_ADDR1: + return ®s->addr1; + case NAND_FLASH_CHIP_SELECT: + return ®s->chip_sel; + case NAND_EXEC_CMD: + return ®s->exec; + case NAND_FLASH_STATUS: + return ®s->clrflashstatus; + case NAND_DEV0_CFG0: + return ®s->cfg0; + case NAND_DEV0_CFG1: + return ®s->cfg1; + case NAND_DEV0_ECC_CFG: + return ®s->ecc_bch_cfg; + case NAND_READ_STATUS: + return ®s->clrreadstatus; + case NAND_DEV_CMD1: + return ®s->cmd1; + case NAND_DEV_CMD1_RESTORE: + return ®s->orig_cmd1; + case NAND_DEV_CMD_VLD: + return ®s->vld; + case NAND_DEV_CMD_VLD_RESTORE: + return ®s->orig_vld; + case NAND_EBI2_ECC_BUF_CFG: + return ®s->ecc_buf_cfg; + default: + return NULL; + } +} + +static void nandc_set_reg(struct qcom_nand_controller *nandc, int offset, + u32 val) +{ + struct nandc_regs *regs = nandc->regs; + __le32 *reg; + + reg = offset_to_nandc_reg(regs, offset); + + if (reg) + *reg = cpu_to_le32(val); +} + +/* helper to configure address register values */ +static void set_address(struct qcom_nand_host *host, u16 column, int page) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + if (chip->options & NAND_BUSWIDTH_16) + column >>= 1; + + nandc_set_reg(nandc, NAND_ADDR0, page << 16 | column); + nandc_set_reg(nandc, NAND_ADDR1, page >> 16 & 0xff); +} + +/* + * update_rw_regs: set up read/write register values, these will be + * written to the NAND controller registers via DMA + * + * @num_cw: number of steps for the read/write operation + * @read: read or write operation + */ +static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + u32 cmd, cfg0, cfg1, ecc_bch_cfg; + + if (read) { + if (host->use_ecc) + cmd = PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE; + else + cmd = PAGE_READ | PAGE_ACC | LAST_PAGE; + } else { + cmd = PROGRAM_PAGE | PAGE_ACC | LAST_PAGE; + } + + if (host->use_ecc) { + cfg0 = (host->cfg0 & ~(7U << CW_PER_PAGE)) | + (num_cw - 1) << CW_PER_PAGE; + + cfg1 = host->cfg1; + ecc_bch_cfg = host->ecc_bch_cfg; + } else { + cfg0 = (host->cfg0_raw & ~(7U << CW_PER_PAGE)) | + (num_cw - 1) << CW_PER_PAGE; + + cfg1 = host->cfg1_raw; + ecc_bch_cfg = 1 << ECC_CFG_ECC_DISABLE; + } + + nandc_set_reg(nandc, NAND_FLASH_CMD, cmd); + nandc_set_reg(nandc, NAND_DEV0_CFG0, cfg0); + nandc_set_reg(nandc, NAND_DEV0_CFG1, cfg1); + nandc_set_reg(nandc, NAND_DEV0_ECC_CFG, ecc_bch_cfg); + nandc_set_reg(nandc, NAND_EBI2_ECC_BUF_CFG, host->ecc_buf_cfg); + nandc_set_reg(nandc, NAND_FLASH_STATUS, host->clrflashstatus); + nandc_set_reg(nandc, NAND_READ_STATUS, host->clrreadstatus); + nandc_set_reg(nandc, NAND_EXEC_CMD, 1); +} + +static int prep_dma_desc(struct qcom_nand_controller *nandc, bool read, + int reg_off, const void *vaddr, int size, + bool flow_control) +{ + struct desc_info *desc; + struct dma_async_tx_descriptor *dma_desc; + struct scatterlist *sgl; + struct dma_slave_config slave_conf; + enum dma_transfer_direction dir_eng; + int ret; + + desc = kzalloc(sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + sgl = &desc->sgl; + + sg_init_one(sgl, vaddr, size); + + if (read) { + dir_eng = DMA_DEV_TO_MEM; + desc->dir = DMA_FROM_DEVICE; + } else { + dir_eng = DMA_MEM_TO_DEV; + desc->dir = DMA_TO_DEVICE; + } + + ret = dma_map_sg(nandc->dev, sgl, 1, desc->dir); + if (ret == 0) { + ret = -ENOMEM; + goto err; + } + + memset(&slave_conf, 0x00, sizeof(slave_conf)); + + slave_conf.device_fc = flow_control; + if (read) { + slave_conf.src_maxburst = 16; + slave_conf.src_addr = nandc->base_dma + reg_off; + slave_conf.slave_id = nandc->data_crci; + } else { + slave_conf.dst_maxburst = 16; + slave_conf.dst_addr = nandc->base_dma + reg_off; + slave_conf.slave_id = nandc->cmd_crci; + } + + ret = dmaengine_slave_config(nandc->chan, &slave_conf); + if (ret) { + dev_err(nandc->dev, "failed to configure dma channel\n"); + goto err; + } + + dma_desc = dmaengine_prep_slave_sg(nandc->chan, sgl, 1, dir_eng, 0); + if (!dma_desc) { + dev_err(nandc->dev, "failed to prepare desc\n"); + ret = -EINVAL; + goto err; + } + + desc->dma_desc = dma_desc; + + list_add_tail(&desc->node, &nandc->desc_list); + + return 0; +err: + kfree(desc); + + return ret; +} + +/* + * read_reg_dma: prepares a descriptor to read a given number of + * contiguous registers to the reg_read_buf pointer + * + * @first: offset of the first register in the contiguous block + * @num_regs: number of registers to read + */ +static int read_reg_dma(struct qcom_nand_controller *nandc, int first, + int num_regs) +{ + bool flow_control = false; + void *vaddr; + int size; + + if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) + flow_control = true; + + size = num_regs * sizeof(u32); + vaddr = nandc->reg_read_buf + nandc->reg_read_pos; + nandc->reg_read_pos += num_regs; + + return prep_dma_desc(nandc, true, first, vaddr, size, flow_control); +} + +/* + * write_reg_dma: prepares a descriptor to write a given number of + * contiguous registers + * + * @first: offset of the first register in the contiguous block + * @num_regs: number of registers to write + */ +static int write_reg_dma(struct qcom_nand_controller *nandc, int first, + int num_regs) +{ + bool flow_control = false; + struct nandc_regs *regs = nandc->regs; + void *vaddr; + int size; + + vaddr = offset_to_nandc_reg(regs, first); + + if (first == NAND_FLASH_CMD) + flow_control = true; + + if (first == NAND_DEV_CMD1_RESTORE) + first = NAND_DEV_CMD1; + + if (first == NAND_DEV_CMD_VLD_RESTORE) + first = NAND_DEV_CMD_VLD; + + size = num_regs * sizeof(u32); + + return prep_dma_desc(nandc, false, first, vaddr, size, flow_control); +} + +/* + * read_data_dma: prepares a DMA descriptor to transfer data from the + * controller's internal buffer to the buffer 'vaddr' + * + * @reg_off: offset within the controller's data buffer + * @vaddr: virtual address of the buffer we want to write to + * @size: DMA transaction size in bytes + */ +static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off, + const u8 *vaddr, int size) +{ + return prep_dma_desc(nandc, true, reg_off, vaddr, size, false); +} + +/* + * write_data_dma: prepares a DMA descriptor to transfer data from + * 'vaddr' to the controller's internal buffer + * + * @reg_off: offset within the controller's data buffer + * @vaddr: virtual address of the buffer we want to read from + * @size: DMA transaction size in bytes + */ +static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off, + const u8 *vaddr, int size) +{ + return prep_dma_desc(nandc, false, reg_off, vaddr, size, false); +} + +/* + * helper to prepare dma descriptors to configure registers needed for reading a + * codeword/step in a page + */ +static void config_cw_read(struct qcom_nand_controller *nandc) +{ + write_reg_dma(nandc, NAND_FLASH_CMD, 3); + write_reg_dma(nandc, NAND_DEV0_CFG0, 3); + write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1); + + write_reg_dma(nandc, NAND_EXEC_CMD, 1); + + read_reg_dma(nandc, NAND_FLASH_STATUS, 2); + read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1); +} + +/* + * helpers to prepare dma descriptors used to configure registers needed for + * writing a codeword/step in a page + */ +static void config_cw_write_pre(struct qcom_nand_controller *nandc) +{ + write_reg_dma(nandc, NAND_FLASH_CMD, 3); + write_reg_dma(nandc, NAND_DEV0_CFG0, 3); + write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1); +} + +static void config_cw_write_post(struct qcom_nand_controller *nandc) +{ + write_reg_dma(nandc, NAND_EXEC_CMD, 1); + + read_reg_dma(nandc, NAND_FLASH_STATUS, 1); + + write_reg_dma(nandc, NAND_FLASH_STATUS, 1); + write_reg_dma(nandc, NAND_READ_STATUS, 1); +} + +/* + * the following functions are used within chip->cmdfunc() to perform different + * NAND_CMD_* commands + */ + +/* sets up descriptors for NAND_CMD_PARAM */ +static int nandc_param(struct qcom_nand_host *host) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + /* + * NAND_CMD_PARAM is called before we know much about the FLASH chip + * in use. we configure the controller to perform a raw read of 512 + * bytes to read onfi params + */ + nandc_set_reg(nandc, NAND_FLASH_CMD, PAGE_READ | PAGE_ACC | LAST_PAGE); + nandc_set_reg(nandc, NAND_ADDR0, 0); + nandc_set_reg(nandc, NAND_ADDR1, 0); + nandc_set_reg(nandc, NAND_DEV0_CFG0, 0 << CW_PER_PAGE + | 512 << UD_SIZE_BYTES + | 5 << NUM_ADDR_CYCLES + | 0 << SPARE_SIZE_BYTES); + nandc_set_reg(nandc, NAND_DEV0_CFG1, 7 << NAND_RECOVERY_CYCLES + | 0 << CS_ACTIVE_BSY + | 17 << BAD_BLOCK_BYTE_NUM + | 1 << BAD_BLOCK_IN_SPARE_AREA + | 2 << WR_RD_BSY_GAP + | 0 << WIDE_FLASH + | 1 << DEV0_CFG1_ECC_DISABLE); + nandc_set_reg(nandc, NAND_EBI2_ECC_BUF_CFG, 1 << ECC_CFG_ECC_DISABLE); + + /* configure CMD1 and VLD for ONFI param probing */ + nandc_set_reg(nandc, NAND_DEV_CMD_VLD, + (nandc->vld & ~(1 << READ_START_VLD)) + | 0 << READ_START_VLD); + nandc_set_reg(nandc, NAND_DEV_CMD1, + (nandc->cmd1 & ~(0xFF << READ_ADDR)) + | NAND_CMD_PARAM << READ_ADDR); + + nandc_set_reg(nandc, NAND_EXEC_CMD, 1); + + nandc_set_reg(nandc, NAND_DEV_CMD1_RESTORE, nandc->cmd1); + nandc_set_reg(nandc, NAND_DEV_CMD_VLD_RESTORE, nandc->vld); + + write_reg_dma(nandc, NAND_DEV_CMD_VLD, 1); + write_reg_dma(nandc, NAND_DEV_CMD1, 1); + + nandc->buf_count = 512; + memset(nandc->data_buffer, 0xff, nandc->buf_count); + + config_cw_read(nandc); + + read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, + nandc->buf_count); + + /* restore CMD1 and VLD regs */ + write_reg_dma(nandc, NAND_DEV_CMD1_RESTORE, 1); + write_reg_dma(nandc, NAND_DEV_CMD_VLD_RESTORE, 1); + + return 0; +} + +/* sets up descriptors for NAND_CMD_ERASE1 */ +static int erase_block(struct qcom_nand_host *host, int page_addr) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + nandc_set_reg(nandc, NAND_FLASH_CMD, + BLOCK_ERASE | PAGE_ACC | LAST_PAGE); + nandc_set_reg(nandc, NAND_ADDR0, page_addr); + nandc_set_reg(nandc, NAND_ADDR1, 0); + nandc_set_reg(nandc, NAND_DEV0_CFG0, + host->cfg0_raw & ~(7 << CW_PER_PAGE)); + nandc_set_reg(nandc, NAND_DEV0_CFG1, host->cfg1_raw); + nandc_set_reg(nandc, NAND_EXEC_CMD, 1); + nandc_set_reg(nandc, NAND_FLASH_STATUS, host->clrflashstatus); + nandc_set_reg(nandc, NAND_READ_STATUS, host->clrreadstatus); + + write_reg_dma(nandc, NAND_FLASH_CMD, 3); + write_reg_dma(nandc, NAND_DEV0_CFG0, 2); + write_reg_dma(nandc, NAND_EXEC_CMD, 1); + + read_reg_dma(nandc, NAND_FLASH_STATUS, 1); + + write_reg_dma(nandc, NAND_FLASH_STATUS, 1); + write_reg_dma(nandc, NAND_READ_STATUS, 1); + + return 0; +} + +/* sets up descriptors for NAND_CMD_READID */ +static int read_id(struct qcom_nand_host *host, int column) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + if (column == -1) + return 0; + + nandc_set_reg(nandc, NAND_FLASH_CMD, FETCH_ID); + nandc_set_reg(nandc, NAND_ADDR0, column); + nandc_set_reg(nandc, NAND_ADDR1, 0); + nandc_set_reg(nandc, NAND_FLASH_CHIP_SELECT, DM_EN); + nandc_set_reg(nandc, NAND_EXEC_CMD, 1); + + write_reg_dma(nandc, NAND_FLASH_CMD, 4); + write_reg_dma(nandc, NAND_EXEC_CMD, 1); + + read_reg_dma(nandc, NAND_READ_ID, 1); + + return 0; +} + +/* sets up descriptors for NAND_CMD_RESET */ +static int reset(struct qcom_nand_host *host) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + nandc_set_reg(nandc, NAND_FLASH_CMD, RESET_DEVICE); + nandc_set_reg(nandc, NAND_EXEC_CMD, 1); + + write_reg_dma(nandc, NAND_FLASH_CMD, 1); + write_reg_dma(nandc, NAND_EXEC_CMD, 1); + + read_reg_dma(nandc, NAND_FLASH_STATUS, 1); + + return 0; +} + +/* helpers to submit/free our list of dma descriptors */ +static int submit_descs(struct qcom_nand_controller *nandc) +{ + struct desc_info *desc; + dma_cookie_t cookie = 0; + + list_for_each_entry(desc, &nandc->desc_list, node) + cookie = dmaengine_submit(desc->dma_desc); + + if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE) + return -ETIMEDOUT; + + return 0; +} + +static void free_descs(struct qcom_nand_controller *nandc) +{ + struct desc_info *desc, *n; + + list_for_each_entry_safe(desc, n, &nandc->desc_list, node) { + list_del(&desc->node); + dma_unmap_sg(nandc->dev, &desc->sgl, 1, desc->dir); + kfree(desc); + } +} + +/* reset the register read buffer for next NAND operation */ +static void clear_read_regs(struct qcom_nand_controller *nandc) +{ + nandc->reg_read_pos = 0; + memset(nandc->reg_read_buf, 0, + MAX_REG_RD * sizeof(*nandc->reg_read_buf)); +} + +static void pre_command(struct qcom_nand_host *host, int command) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + nandc->buf_count = 0; + nandc->buf_start = 0; + host->use_ecc = false; + host->last_command = command; + + clear_read_regs(nandc); +} + +/* + * this is called after NAND_CMD_PAGEPROG and NAND_CMD_ERASE1 to set our + * privately maintained status byte, this status byte can be read after + * NAND_CMD_STATUS is called + */ +static void parse_erase_write_errors(struct qcom_nand_host *host, int command) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int num_cw; + int i; + + num_cw = command == NAND_CMD_PAGEPROG ? ecc->steps : 1; + + for (i = 0; i < num_cw; i++) { + u32 flash_status = le32_to_cpu(nandc->reg_read_buf[i]); + + if (flash_status & FS_MPU_ERR) + host->status &= ~NAND_STATUS_WP; + + if (flash_status & FS_OP_ERR || (i == (num_cw - 1) && + (flash_status & + FS_DEVICE_STS_ERR))) + host->status |= NAND_STATUS_FAIL; + } +} + +static void post_command(struct qcom_nand_host *host, int command) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + switch (command) { + case NAND_CMD_READID: + memcpy(nandc->data_buffer, nandc->reg_read_buf, + nandc->buf_count); + break; + case NAND_CMD_PAGEPROG: + case NAND_CMD_ERASE1: + parse_erase_write_errors(host, command); + break; + default: + break; + } +} + +/* + * Implements chip->cmdfunc. It's only used for a limited set of commands. + * The rest of the commands wouldn't be called by upper layers. For example, + * NAND_CMD_READOOB would never be called because we have our own versions + * of read_oob ops for nand_ecc_ctrl. + */ +static void qcom_nandc_command(struct mtd_info *mtd, unsigned int command, + int column, int page_addr) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + bool wait = false; + int ret = 0; + + pre_command(host, command); + + switch (command) { + case NAND_CMD_RESET: + ret = reset(host); + wait = true; + break; + + case NAND_CMD_READID: + nandc->buf_count = 4; + ret = read_id(host, column); + wait = true; + break; + + case NAND_CMD_PARAM: + ret = nandc_param(host); + wait = true; + break; + + case NAND_CMD_ERASE1: + ret = erase_block(host, page_addr); + wait = true; + break; + + case NAND_CMD_READ0: + /* we read the entire page for now */ + WARN_ON(column != 0); + + host->use_ecc = true; + set_address(host, 0, page_addr); + update_rw_regs(host, ecc->steps, true); + break; + + case NAND_CMD_SEQIN: + WARN_ON(column != 0); + set_address(host, 0, page_addr); + break; + + case NAND_CMD_PAGEPROG: + case NAND_CMD_STATUS: + case NAND_CMD_NONE: + default: + break; + } + + if (ret) { + dev_err(nandc->dev, "failure executing command %d\n", + command); + free_descs(nandc); + return; + } + + if (wait) { + ret = submit_descs(nandc); + if (ret) + dev_err(nandc->dev, + "failure submitting descs for command %d\n", + command); + } + + free_descs(nandc); + + post_command(host, command); +} + +/* + * when using BCH ECC, the HW flags an error in NAND_FLASH_STATUS if it read + * an erased CW, and reports an erased CW in NAND_ERASED_CW_DETECT_STATUS. + * + * when using RS ECC, the HW reports the same erros when reading an erased CW, + * but it notifies that it is an erased CW by placing special characters at + * certain offsets in the buffer. + * + * verify if the page is erased or not, and fix up the page for RS ECC by + * replacing the special characters with 0xff. + */ +static bool erased_chunk_check_and_fixup(u8 *data_buf, int data_len) +{ + u8 empty1, empty2; + + /* + * an erased page flags an error in NAND_FLASH_STATUS, check if the page + * is erased by looking for 0x54s at offsets 3 and 175 from the + * beginning of each codeword + */ + + empty1 = data_buf[3]; + empty2 = data_buf[175]; + + /* + * if the erased codework markers, if they exist override them with + * 0xffs + */ + if ((empty1 == 0x54 && empty2 == 0xff) || + (empty1 == 0xff && empty2 == 0x54)) { + data_buf[3] = 0xff; + data_buf[175] = 0xff; + } + + /* + * check if the entire chunk contains 0xffs or not. if it doesn't, then + * restore the original values at the special offsets + */ + if (memchr_inv(data_buf, 0xff, data_len)) { + data_buf[3] = empty1; + data_buf[175] = empty2; + + return false; + } + + return true; +} + +struct read_stats { + __le32 flash; + __le32 buffer; + __le32 erased_cw; +}; + +/* + * reads back status registers set by the controller to notify page read + * errors. this is equivalent to what 'ecc->correct()' would do. + */ +static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf, + u8 *oob_buf) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct mtd_info *mtd = nand_to_mtd(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + unsigned int max_bitflips = 0; + struct read_stats *buf; + int i; + + buf = (struct read_stats *)nandc->reg_read_buf; + + for (i = 0; i < ecc->steps; i++, buf++) { + u32 flash, buffer, erased_cw; + int data_len, oob_len; + + if (i == (ecc->steps - 1)) { + data_len = ecc->size - ((ecc->steps - 1) << 2); + oob_len = ecc->steps << 2; + } else { + data_len = host->cw_data; + oob_len = 0; + } + + flash = le32_to_cpu(buf->flash); + buffer = le32_to_cpu(buf->buffer); + erased_cw = le32_to_cpu(buf->erased_cw); + + if (flash & (FS_OP_ERR | FS_MPU_ERR)) { + bool erased; + + /* ignore erased codeword errors */ + if (host->bch_enabled) { + erased = (erased_cw & ERASED_CW) == ERASED_CW ? + true : false; + } else { + erased = erased_chunk_check_and_fixup(data_buf, + data_len); + } + + if (erased) { + data_buf += data_len; + if (oob_buf) + oob_buf += oob_len + ecc->bytes; + continue; + } + + if (buffer & BS_UNCORRECTABLE_BIT) { + int ret, ecclen, extraooblen; + void *eccbuf; + + eccbuf = oob_buf ? oob_buf + oob_len : NULL; + ecclen = oob_buf ? host->ecc_bytes_hw : 0; + extraooblen = oob_buf ? oob_len : 0; + + /* + * make sure it isn't an erased page reported + * as not-erased by HW because of a few bitflips + */ + ret = nand_check_erased_ecc_chunk(data_buf, + data_len, eccbuf, ecclen, oob_buf, + extraooblen, ecc->strength); + if (ret < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += ret; + max_bitflips = + max_t(unsigned int, max_bitflips, ret); + } + } + } else { + unsigned int stat; + + stat = buffer & BS_CORRECTABLE_ERR_MSK; + mtd->ecc_stats.corrected += stat; + max_bitflips = max(max_bitflips, stat); + } + + data_buf += data_len; + if (oob_buf) + oob_buf += oob_len + ecc->bytes; + } + + return max_bitflips; +} + +/* + * helper to perform the actual page read operation, used by ecc->read_page(), + * ecc->read_oob() + */ +static int read_page_ecc(struct qcom_nand_host *host, u8 *data_buf, + u8 *oob_buf) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int i, ret; + + /* queue cmd descs for each codeword */ + for (i = 0; i < ecc->steps; i++) { + int data_size, oob_size; + + if (i == (ecc->steps - 1)) { + data_size = ecc->size - ((ecc->steps - 1) << 2); + oob_size = (ecc->steps << 2) + host->ecc_bytes_hw + + host->spare_bytes; + } else { + data_size = host->cw_data; + oob_size = host->ecc_bytes_hw + host->spare_bytes; + } + + config_cw_read(nandc); + + if (data_buf) + read_data_dma(nandc, FLASH_BUF_ACC, data_buf, + data_size); + + /* + * when ecc is enabled, the controller doesn't read the real + * or dummy bad block markers in each chunk. To maintain a + * consistent layout across RAW and ECC reads, we just + * leave the real/dummy BBM offsets empty (i.e, filled with + * 0xffs) + */ + if (oob_buf) { + int j; + + for (j = 0; j < host->bbm_size; j++) + *oob_buf++ = 0xff; + + read_data_dma(nandc, FLASH_BUF_ACC + data_size, + oob_buf, oob_size); + } + + if (data_buf) + data_buf += data_size; + if (oob_buf) + oob_buf += oob_size; + } + + ret = submit_descs(nandc); + if (ret) + dev_err(nandc->dev, "failure to read page/oob\n"); + + free_descs(nandc); + + return ret; +} + +/* + * a helper that copies the last step/codeword of a page (containing free oob) + * into our local buffer + */ +static int copy_last_cw(struct qcom_nand_host *host, int page) +{ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int size; + int ret; + + clear_read_regs(nandc); + + size = host->use_ecc ? host->cw_data : host->cw_size; + + /* prepare a clean read buffer */ + memset(nandc->data_buffer, 0xff, size); + + set_address(host, host->cw_size * (ecc->steps - 1), page); + update_rw_regs(host, 1, true); + + config_cw_read(nandc); + + read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size); + + ret = submit_descs(nandc); + if (ret) + dev_err(nandc->dev, "failed to copy last codeword\n"); + + free_descs(nandc); + + return ret; +} + +/* implements ecc->read_page() */ +static int qcom_nandc_read_page(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) +{ + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + u8 *data_buf, *oob_buf = NULL; + int ret; + + data_buf = buf; + oob_buf = oob_required ? chip->oob_poi : NULL; + + ret = read_page_ecc(host, data_buf, oob_buf); + if (ret) { + dev_err(nandc->dev, "failure to read page\n"); + return ret; + } + + return parse_read_errors(host, data_buf, oob_buf); +} + +/* implements ecc->read_page_raw() */ +static int qcom_nandc_read_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) +{ + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + u8 *data_buf, *oob_buf; + struct nand_ecc_ctrl *ecc = &chip->ecc; + int i, ret; + + data_buf = buf; + oob_buf = chip->oob_poi; + + host->use_ecc = false; + update_rw_regs(host, ecc->steps, true); + + for (i = 0; i < ecc->steps; i++) { + int data_size1, data_size2, oob_size1, oob_size2; + int reg_off = FLASH_BUF_ACC; + + data_size1 = mtd->writesize - host->cw_size * (ecc->steps - 1); + oob_size1 = host->bbm_size; + + if (i == (ecc->steps - 1)) { + data_size2 = ecc->size - data_size1 - + ((ecc->steps - 1) << 2); + oob_size2 = (ecc->steps << 2) + host->ecc_bytes_hw + + host->spare_bytes; + } else { + data_size2 = host->cw_data - data_size1; + oob_size2 = host->ecc_bytes_hw + host->spare_bytes; + } + + config_cw_read(nandc); + + read_data_dma(nandc, reg_off, data_buf, data_size1); + reg_off += data_size1; + data_buf += data_size1; + + read_data_dma(nandc, reg_off, oob_buf, oob_size1); + reg_off += oob_size1; + oob_buf += oob_size1; + + read_data_dma(nandc, reg_off, data_buf, data_size2); + reg_off += data_size2; + data_buf += data_size2; + + read_data_dma(nandc, reg_off, oob_buf, oob_size2); + oob_buf += oob_size2; + } + + ret = submit_descs(nandc); + if (ret) + dev_err(nandc->dev, "failure to read raw page\n"); + + free_descs(nandc); + + return 0; +} + +/* implements ecc->read_oob() */ +static int qcom_nandc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int ret; + + clear_read_regs(nandc); + + host->use_ecc = true; + set_address(host, 0, page); + update_rw_regs(host, ecc->steps, true); + + ret = read_page_ecc(host, NULL, chip->oob_poi); + if (ret) + dev_err(nandc->dev, "failure to read oob\n"); + + return ret; +} + +/* implements ecc->write_page() */ +static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required, int page) +{ + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + u8 *data_buf, *oob_buf; + int i, ret; + + clear_read_regs(nandc); + + data_buf = (u8 *)buf; + oob_buf = chip->oob_poi; + + host->use_ecc = true; + update_rw_regs(host, ecc->steps, false); + + for (i = 0; i < ecc->steps; i++) { + int data_size, oob_size; + + if (i == (ecc->steps - 1)) { + data_size = ecc->size - ((ecc->steps - 1) << 2); + oob_size = (ecc->steps << 2) + host->ecc_bytes_hw + + host->spare_bytes; + } else { + data_size = host->cw_data; + oob_size = ecc->bytes; + } + + config_cw_write_pre(nandc); + + write_data_dma(nandc, FLASH_BUF_ACC, data_buf, data_size); + + /* + * when ECC is enabled, we don't really need to write anything + * to oob for the first n - 1 codewords since these oob regions + * just contain ECC bytes that's written by the controller + * itself. For the last codeword, we skip the bbm positions and + * write to the free oob area. + */ + if (i == (ecc->steps - 1)) { + oob_buf += host->bbm_size; + + write_data_dma(nandc, FLASH_BUF_ACC + data_size, + oob_buf, oob_size); + } + + config_cw_write_post(nandc); + + data_buf += data_size; + oob_buf += oob_size; + } + + ret = submit_descs(nandc); + if (ret) + dev_err(nandc->dev, "failure to write page\n"); + + free_descs(nandc); + + return ret; +} + +/* implements ecc->write_page_raw() */ +static int qcom_nandc_write_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) +{ + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + u8 *data_buf, *oob_buf; + int i, ret; + + clear_read_regs(nandc); + + data_buf = (u8 *)buf; + oob_buf = chip->oob_poi; + + host->use_ecc = false; + update_rw_regs(host, ecc->steps, false); + + for (i = 0; i < ecc->steps; i++) { + int data_size1, data_size2, oob_size1, oob_size2; + int reg_off = FLASH_BUF_ACC; + + data_size1 = mtd->writesize - host->cw_size * (ecc->steps - 1); + oob_size1 = host->bbm_size; + + if (i == (ecc->steps - 1)) { + data_size2 = ecc->size - data_size1 - + ((ecc->steps - 1) << 2); + oob_size2 = (ecc->steps << 2) + host->ecc_bytes_hw + + host->spare_bytes; + } else { + data_size2 = host->cw_data - data_size1; + oob_size2 = host->ecc_bytes_hw + host->spare_bytes; + } + + config_cw_write_pre(nandc); + + write_data_dma(nandc, reg_off, data_buf, data_size1); + reg_off += data_size1; + data_buf += data_size1; + + write_data_dma(nandc, reg_off, oob_buf, oob_size1); + reg_off += oob_size1; + oob_buf += oob_size1; + + write_data_dma(nandc, reg_off, data_buf, data_size2); + reg_off += data_size2; + data_buf += data_size2; + + write_data_dma(nandc, reg_off, oob_buf, oob_size2); + oob_buf += oob_size2; + + config_cw_write_post(nandc); + } + + ret = submit_descs(nandc); + if (ret) + dev_err(nandc->dev, "failure to write raw page\n"); + + free_descs(nandc); + + return ret; +} + +/* + * implements ecc->write_oob() + * + * the NAND controller cannot write only data or only oob within a codeword, + * since ecc is calculated for the combined codeword. we first copy the + * entire contents for the last codeword(data + oob), replace the old oob + * with the new one in chip->oob_poi, and then write the entire codeword. + * this read-copy-write operation results in a slight performance loss. + */ +static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + u8 *oob = chip->oob_poi; + int free_boff; + int data_size, oob_size; + int ret, status = 0; + + host->use_ecc = true; + + ret = copy_last_cw(host, page); + if (ret) + return ret; + + clear_read_regs(nandc); + + /* calculate the data and oob size for the last codeword/step */ + data_size = ecc->size - ((ecc->steps - 1) << 2); + oob_size = ecc->steps << 2; + + free_boff = ecc->layout->oobfree[0].offset; + + /* override new oob content to last codeword */ + memcpy(nandc->data_buffer + data_size, oob + free_boff, oob_size); + + set_address(host, host->cw_size * (ecc->steps - 1), page); + update_rw_regs(host, 1, false); + + config_cw_write_pre(nandc); + write_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, + data_size + oob_size); + config_cw_write_post(nandc); + + ret = submit_descs(nandc); + + free_descs(nandc); + + if (ret) { + dev_err(nandc->dev, "failure to write oob\n"); + return -EIO; + } + + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + + status = chip->waitfunc(mtd, chip); + + return status & NAND_STATUS_FAIL ? -EIO : 0; +} + +static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int page, ret, bbpos, bad = 0; + u32 flash_status; + + page = (int)(ofs >> chip->page_shift) & chip->pagemask; + + /* + * configure registers for a raw sub page read, the address is set to + * the beginning of the last codeword, we don't care about reading ecc + * portion of oob. we just want the first few bytes from this codeword + * that contains the BBM + */ + host->use_ecc = false; + + ret = copy_last_cw(host, page); + if (ret) + goto err; + + flash_status = le32_to_cpu(nandc->reg_read_buf[0]); + + if (flash_status & (FS_OP_ERR | FS_MPU_ERR)) { + dev_warn(nandc->dev, "error when trying to read BBM\n"); + goto err; + } + + bbpos = mtd->writesize - host->cw_size * (ecc->steps - 1); + + bad = nandc->data_buffer[bbpos] != 0xff; + + if (chip->options & NAND_BUSWIDTH_16) + bad = bad || (nandc->data_buffer[bbpos + 1] != 0xff); +err: + return bad; +} + +static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + int page, ret, status = 0; + + clear_read_regs(nandc); + + /* + * to mark the BBM as bad, we flash the entire last codeword with 0s. + * we don't care about the rest of the content in the codeword since + * we aren't going to use this block again + */ + memset(nandc->data_buffer, 0x00, host->cw_size); + + page = (int)(ofs >> chip->page_shift) & chip->pagemask; + + /* prepare write */ + host->use_ecc = false; + set_address(host, host->cw_size * (ecc->steps - 1), page); + update_rw_regs(host, 1, false); + + config_cw_write_pre(nandc); + write_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, host->cw_size); + config_cw_write_post(nandc); + + ret = submit_descs(nandc); + + free_descs(nandc); + + if (ret) { + dev_err(nandc->dev, "failure to update BBM\n"); + return -EIO; + } + + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + + status = chip->waitfunc(mtd, chip); + + return status & NAND_STATUS_FAIL ? -EIO : 0; +} + +/* + * the three functions below implement chip->read_byte(), chip->read_buf() + * and chip->write_buf() respectively. these aren't used for + * reading/writing page data, they are used for smaller data like reading + * id, status etc + */ +static uint8_t qcom_nandc_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + u8 *buf = nandc->data_buffer; + u8 ret = 0x0; + + if (host->last_command == NAND_CMD_STATUS) { + ret = host->status; + + host->status = NAND_STATUS_READY | NAND_STATUS_WP; + + return ret; + } + + if (nandc->buf_start < nandc->buf_count) + ret = buf[nandc->buf_start++]; + + return ret; +} + +static void qcom_nandc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start); + + memcpy(buf, nandc->data_buffer + nandc->buf_start, real_len); + nandc->buf_start += real_len; +} + +static void qcom_nandc_write_buf(struct mtd_info *mtd, const uint8_t *buf, + int len) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start); + + memcpy(nandc->data_buffer + nandc->buf_start, buf, real_len); + + nandc->buf_start += real_len; +} + +/* we support only one external chip for now */ +static void qcom_nandc_select_chip(struct mtd_info *mtd, int chipnr) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + if (chipnr <= 0) + return; + + dev_warn(nandc->dev, "invalid chip select\n"); +} + +/* + * NAND controller page layout info + * + * Layout with ECC enabled: + * + * |----------------------| |---------------------------------| + * | xx.......yy| | *********xx.......yy| + * | DATA xx..ECC..yy| | DATA **SPARE**xx..ECC..yy| + * | (516) xx.......yy| | (516-n*4) **(n*4)**xx.......yy| + * | xx.......yy| | *********xx.......yy| + * |----------------------| |---------------------------------| + * codeword 1,2..n-1 codeword n + * <---(528/532 Bytes)--> <-------(528/532 Bytes)---------> + * + * n = Number of codewords in the page + * . = ECC bytes + * * = Spare/free bytes + * x = Unused byte(s) + * y = Reserved byte(s) + * + * 2K page: n = 4, spare = 16 bytes + * 4K page: n = 8, spare = 32 bytes + * 8K page: n = 16, spare = 64 bytes + * + * the qcom nand controller operates at a sub page/codeword level. each + * codeword is 528 and 532 bytes for 4 bit and 8 bit ECC modes respectively. + * the number of ECC bytes vary based on the ECC strength and the bus width. + * + * the first n - 1 codewords contains 516 bytes of user data, the remaining + * 12/16 bytes consist of ECC and reserved data. The nth codeword contains + * both user data and spare(oobavail) bytes that sum up to 516 bytes. + * + * When we access a page with ECC enabled, the reserved bytes(s) are not + * accessible at all. When reading, we fill up these unreadable positions + * with 0xffs. When writing, the controller skips writing the inaccessible + * bytes. + * + * Layout with ECC disabled: + * + * |------------------------------| |---------------------------------------| + * | yy xx.......| | bb *********xx.......| + * | DATA1 yy DATA2 xx..ECC..| | DATA1 bb DATA2 **SPARE**xx..ECC..| + * | (size1) yy (size2) xx.......| | (size1) bb (size2) **(n*4)**xx.......| + * | yy xx.......| | bb *********xx.......| + * |------------------------------| |---------------------------------------| + * codeword 1,2..n-1 codeword n + * <-------(528/532 Bytes)------> <-----------(528/532 Bytes)-----------> + * + * n = Number of codewords in the page + * . = ECC bytes + * * = Spare/free bytes + * x = Unused byte(s) + * y = Dummy Bad Bock byte(s) + * b = Real Bad Block byte(s) + * size1/size2 = function of codeword size and 'n' + * + * when the ECC block is disabled, one reserved byte (or two for 16 bit bus + * width) is now accessible. For the first n - 1 codewords, these are dummy Bad + * Block Markers. In the last codeword, this position contains the real BBM + * + * In order to have a consistent layout between RAW and ECC modes, we assume + * the following OOB layout arrangement: + * + * |-----------| |--------------------| + * |yyxx.......| |bb*********xx.......| + * |yyxx..ECC..| |bb*FREEOOB*xx..ECC..| + * |yyxx.......| |bb*********xx.......| + * |yyxx.......| |bb*********xx.......| + * |-----------| |--------------------| + * first n - 1 nth OOB region + * OOB regions + * + * n = Number of codewords in the page + * . = ECC bytes + * * = FREE OOB bytes + * y = Dummy bad block byte(s) (inaccessible when ECC enabled) + * x = Unused byte(s) + * b = Real bad block byte(s) (inaccessible when ECC enabled) + * + * This layout is read as is when ECC is disabled. When ECC is enabled, the + * inaccessible Bad Block byte(s) are ignored when we write to a page/oob, + * and assumed as 0xffs when we read a page/oob. The ECC, unused and + * dummy/real bad block bytes are grouped as ecc bytes in nand_ecclayout (i.e, + * ecc->bytes is the sum of the three). + */ + +static struct nand_ecclayout * +qcom_nand_create_layout(struct qcom_nand_host *host) +{ + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + struct nand_ecclayout *layout; + int i, j, steps, pos = 0, shift = 0; + + layout = devm_kzalloc(nandc->dev, sizeof(*layout), GFP_KERNEL); + if (!layout) + return NULL; + + steps = mtd->writesize / ecc->size; + layout->eccbytes = steps * ecc->bytes; + + layout->oobfree[0].offset = (steps - 1) * ecc->bytes + host->bbm_size; + layout->oobfree[0].length = steps << 2; + + /* + * the oob bytes in the first n - 1 codewords are all grouped together + * in the format: + * DUMMY_BBM + UNUSED + ECC + */ + for (i = 0; i < steps - 1; i++) { + for (j = 0; j < ecc->bytes; j++) + layout->eccpos[pos++] = i * ecc->bytes + j; + } + + /* + * the oob bytes in the last codeword are grouped in the format: + * BBM + FREE OOB + UNUSED + ECC + */ + + /* fill up the bbm positions */ + for (j = 0; j < host->bbm_size; j++) + layout->eccpos[pos++] = i * ecc->bytes + j; + + /* + * fill up the ecc and reserved positions, their indices are offseted + * by the free oob region + */ + shift = layout->oobfree[0].length + host->bbm_size; + + for (j = 0; j < (host->ecc_bytes_hw + host->spare_bytes); j++) + layout->eccpos[pos++] = i * ecc->bytes + shift + j; + + return layout; +} + +static int qcom_nand_host_setup(struct qcom_nand_host *host) +{ + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + int cwperpage, bad_block_byte; + bool wide_bus; + int ecc_mode = 1; + + /* + * the controller requires each step consists of 512 bytes of data. + * bail out if DT has populated a wrong step size. + */ + if (ecc->size != NANDC_STEP_SIZE) { + dev_err(nandc->dev, "invalid ecc size\n"); + return -EINVAL; + } + + wide_bus = chip->options & NAND_BUSWIDTH_16 ? true : false; + + if (ecc->strength >= 8) { + /* 8 bit ECC defaults to BCH ECC on all platforms */ + host->bch_enabled = true; + ecc_mode = 1; + + if (wide_bus) { + host->ecc_bytes_hw = 14; + host->spare_bytes = 0; + host->bbm_size = 2; + } else { + host->ecc_bytes_hw = 13; + host->spare_bytes = 2; + host->bbm_size = 1; + } + } else { + /* + * if the controller supports BCH for 4 bit ECC, the controller + * uses lesser bytes for ECC. If RS is used, the ECC bytes is + * always 10 bytes + */ + if (nandc->ecc_modes & ECC_BCH_4BIT) { + /* BCH */ + host->bch_enabled = true; + ecc_mode = 0; + + if (wide_bus) { + host->ecc_bytes_hw = 8; + host->spare_bytes = 2; + host->bbm_size = 2; + } else { + host->ecc_bytes_hw = 7; + host->spare_bytes = 4; + host->bbm_size = 1; + } + } else { + /* RS */ + host->ecc_bytes_hw = 10; + + if (wide_bus) { + host->spare_bytes = 0; + host->bbm_size = 2; + } else { + host->spare_bytes = 1; + host->bbm_size = 1; + } + } + } + + /* + * we consider ecc->bytes as the sum of all the non-data content in a + * step. It gives us a clean representation of the oob area (even if + * all the bytes aren't used for ECC).It is always 16 bytes for 8 bit + * ECC and 12 bytes for 4 bit ECC + */ + ecc->bytes = host->ecc_bytes_hw + host->spare_bytes + host->bbm_size; + + ecc->read_page = qcom_nandc_read_page; + ecc->read_page_raw = qcom_nandc_read_page_raw; + ecc->read_oob = qcom_nandc_read_oob; + ecc->write_page = qcom_nandc_write_page; + ecc->write_page_raw = qcom_nandc_write_page_raw; + ecc->write_oob = qcom_nandc_write_oob; + + ecc->mode = NAND_ECC_HW; + + ecc->layout = qcom_nand_create_layout(host); + if (!ecc->layout) + return -ENOMEM; + + cwperpage = mtd->writesize / ecc->size; + + /* + * DATA_UD_BYTES varies based on whether the read/write command protects + * spare data with ECC too. We protect spare data by default, so we set + * it to main + spare data, which are 512 and 4 bytes respectively. + */ + host->cw_data = 516; + + /* + * total bytes in a step, either 528 bytes for 4 bit ECC, or 532 bytes + * for 8 bit ECC + */ + host->cw_size = host->cw_data + ecc->bytes; + + if (ecc->bytes * (mtd->writesize / ecc->size) > mtd->oobsize) { + dev_err(nandc->dev, "ecc data doesn't fit in OOB area\n"); + return -EINVAL; + } + + bad_block_byte = mtd->writesize - host->cw_size * (cwperpage - 1) + 1; + + host->cfg0 = (cwperpage - 1) << CW_PER_PAGE + | host->cw_data << UD_SIZE_BYTES + | 0 << DISABLE_STATUS_AFTER_WRITE + | 5 << NUM_ADDR_CYCLES + | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_RS + | 0 << STATUS_BFR_READ + | 1 << SET_RD_MODE_AFTER_STATUS + | host->spare_bytes << SPARE_SIZE_BYTES; + + host->cfg1 = 7 << NAND_RECOVERY_CYCLES + | 0 << CS_ACTIVE_BSY + | bad_block_byte << BAD_BLOCK_BYTE_NUM + | 0 << BAD_BLOCK_IN_SPARE_AREA + | 2 << WR_RD_BSY_GAP + | wide_bus << WIDE_FLASH + | host->bch_enabled << ENABLE_BCH_ECC; + + host->cfg0_raw = (cwperpage - 1) << CW_PER_PAGE + | host->cw_size << UD_SIZE_BYTES + | 5 << NUM_ADDR_CYCLES + | 0 << SPARE_SIZE_BYTES; + + host->cfg1_raw = 7 << NAND_RECOVERY_CYCLES + | 0 << CS_ACTIVE_BSY + | 17 << BAD_BLOCK_BYTE_NUM + | 1 << BAD_BLOCK_IN_SPARE_AREA + | 2 << WR_RD_BSY_GAP + | wide_bus << WIDE_FLASH + | 1 << DEV0_CFG1_ECC_DISABLE; + + host->ecc_bch_cfg = host->bch_enabled << ECC_CFG_ECC_DISABLE + | 0 << ECC_SW_RESET + | host->cw_data << ECC_NUM_DATA_BYTES + | 1 << ECC_FORCE_CLK_OPEN + | ecc_mode << ECC_MODE + | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_BCH; + + host->ecc_buf_cfg = 0x203 << NUM_STEPS; + + host->clrflashstatus = FS_READY_BSY_N; + host->clrreadstatus = 0xc0; + + dev_dbg(nandc->dev, + "cfg0 %x cfg1 %x ecc_buf_cfg %x ecc_bch cfg %x cw_size %d cw_data %d strength %d parity_bytes %d steps %d\n", + host->cfg0, host->cfg1, host->ecc_buf_cfg, host->ecc_bch_cfg, + host->cw_size, host->cw_data, ecc->strength, ecc->bytes, + cwperpage); + + return 0; +} + +static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) +{ + int ret; + + ret = dma_set_coherent_mask(nandc->dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(nandc->dev, "failed to set DMA mask\n"); + return ret; + } + + /* + * we use the internal buffer for reading ONFI params, reading small + * data like ID and status, and preforming read-copy-write operations + * when writing to a codeword partially. 532 is the maximum possible + * size of a codeword for our nand controller + */ + nandc->buf_size = 532; + + nandc->data_buffer = devm_kzalloc(nandc->dev, nandc->buf_size, + GFP_KERNEL); + if (!nandc->data_buffer) + return -ENOMEM; + + nandc->regs = devm_kzalloc(nandc->dev, sizeof(*nandc->regs), + GFP_KERNEL); + if (!nandc->regs) + return -ENOMEM; + + nandc->reg_read_buf = devm_kzalloc(nandc->dev, + MAX_REG_RD * sizeof(*nandc->reg_read_buf), + GFP_KERNEL); + if (!nandc->reg_read_buf) + return -ENOMEM; + + nandc->chan = dma_request_slave_channel(nandc->dev, "rxtx"); + if (!nandc->chan) { + dev_err(nandc->dev, "failed to request slave channel\n"); + return -ENODEV; + } + + INIT_LIST_HEAD(&nandc->desc_list); + INIT_LIST_HEAD(&nandc->host_list); + + spin_lock_init(&nandc->controller.lock); + init_waitqueue_head(&nandc->controller.wq); + + return 0; +} + +static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) +{ + dma_release_channel(nandc->chan); +} + +/* one time setup of a few nand controller registers */ +static int qcom_nandc_setup(struct qcom_nand_controller *nandc) +{ + /* kill onenand */ + nandc_write(nandc, SFLASHC_BURST_CFG, 0); + + /* enable ADM DMA */ + nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN); + + /* save the original values of these registers */ + nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1); + nandc->vld = nandc_read(nandc, NAND_DEV_CMD_VLD); + + return 0; +} + +static int qcom_nand_host_init(struct qcom_nand_controller *nandc, + struct qcom_nand_host *host, + struct device_node *dn) +{ + struct nand_chip *chip = &host->chip; + struct mtd_info *mtd = nand_to_mtd(chip); + struct device *dev = nandc->dev; + int ret; + + ret = of_property_read_u32(dn, "reg", &host->cs); + if (ret) { + dev_err(dev, "can't get chip-select\n"); + return -ENXIO; + } + + nand_set_flash_node(chip, dn); + mtd->name = devm_kasprintf(dev, GFP_KERNEL, "qcom_nand.%d", host->cs); + mtd->owner = THIS_MODULE; + mtd->dev.parent = dev; + + chip->cmdfunc = qcom_nandc_command; + chip->select_chip = qcom_nandc_select_chip; + chip->read_byte = qcom_nandc_read_byte; + chip->read_buf = qcom_nandc_read_buf; + chip->write_buf = qcom_nandc_write_buf; + + /* + * the bad block marker is readable only when we read the last codeword + * of a page with ECC disabled. currently, the nand_base and nand_bbt + * helpers don't allow us to read BB from a nand chip with ECC + * disabled (MTD_OPS_PLACE_OOB is set by default). use the block_bad + * and block_markbad helpers until we permanently switch to using + * MTD_OPS_RAW for all drivers (with the help of badblockbits) + */ + chip->block_bad = qcom_nandc_block_bad; + chip->block_markbad = qcom_nandc_block_markbad; + + chip->controller = &nandc->controller; + chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER | + NAND_SKIP_BBTSCAN; + + /* set up initial status value */ + host->status = NAND_STATUS_READY | NAND_STATUS_WP; + + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) + return ret; + + ret = qcom_nand_host_setup(host); + if (ret) + return ret; + + ret = nand_scan_tail(mtd); + if (ret) + return ret; + + return mtd_device_register(mtd, NULL, 0); +} + +/* parse custom DT properties here */ +static int qcom_nandc_parse_dt(struct platform_device *pdev) +{ + struct qcom_nand_controller *nandc = platform_get_drvdata(pdev); + struct device_node *np = nandc->dev->of_node; + int ret; + + ret = of_property_read_u32(np, "qcom,cmd-crci", &nandc->cmd_crci); + if (ret) { + dev_err(nandc->dev, "command CRCI unspecified\n"); + return ret; + } + + ret = of_property_read_u32(np, "qcom,data-crci", &nandc->data_crci); + if (ret) { + dev_err(nandc->dev, "data CRCI unspecified\n"); + return ret; + } + + return 0; +} + +static int qcom_nandc_probe(struct platform_device *pdev) +{ + struct qcom_nand_controller *nandc; + struct qcom_nand_host *host; + const void *dev_data; + struct device *dev = &pdev->dev; + struct device_node *dn = dev->of_node, *child; + struct resource *res; + int ret; + + nandc = devm_kzalloc(&pdev->dev, sizeof(*nandc), GFP_KERNEL); + if (!nandc) + return -ENOMEM; + + platform_set_drvdata(pdev, nandc); + nandc->dev = dev; + + dev_data = of_device_get_match_data(dev); + if (!dev_data) { + dev_err(&pdev->dev, "failed to get device data\n"); + return -ENODEV; + } + + nandc->ecc_modes = (unsigned long)dev_data; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + nandc->base = devm_ioremap_resource(dev, res); + if (IS_ERR(nandc->base)) + return PTR_ERR(nandc->base); + + nandc->base_dma = phys_to_dma(dev, (phys_addr_t)res->start); + + nandc->core_clk = devm_clk_get(dev, "core"); + if (IS_ERR(nandc->core_clk)) + return PTR_ERR(nandc->core_clk); + + nandc->aon_clk = devm_clk_get(dev, "aon"); + if (IS_ERR(nandc->aon_clk)) + return PTR_ERR(nandc->aon_clk); + + ret = qcom_nandc_parse_dt(pdev); + if (ret) + return ret; + + ret = qcom_nandc_alloc(nandc); + if (ret) + return ret; + + ret = clk_prepare_enable(nandc->core_clk); + if (ret) + goto err_core_clk; + + ret = clk_prepare_enable(nandc->aon_clk); + if (ret) + goto err_aon_clk; + + ret = qcom_nandc_setup(nandc); + if (ret) + goto err_setup; + + for_each_available_child_of_node(dn, child) { + if (of_device_is_compatible(child, "qcom,nandcs")) { + host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); + if (!host) { + of_node_put(child); + ret = -ENOMEM; + goto err_cs_init; + } + + ret = qcom_nand_host_init(nandc, host, child); + if (ret) { + devm_kfree(dev, host); + continue; + } + + list_add_tail(&host->node, &nandc->host_list); + } + } + + if (list_empty(&nandc->host_list)) { + ret = -ENODEV; + goto err_cs_init; + } + + return 0; + +err_cs_init: + list_for_each_entry(host, &nandc->host_list, node) + nand_release(nand_to_mtd(&host->chip)); +err_setup: + clk_disable_unprepare(nandc->aon_clk); +err_aon_clk: + clk_disable_unprepare(nandc->core_clk); +err_core_clk: + qcom_nandc_unalloc(nandc); + + return ret; +} + +static int qcom_nandc_remove(struct platform_device *pdev) +{ + struct qcom_nand_controller *nandc = platform_get_drvdata(pdev); + struct qcom_nand_host *host; + + list_for_each_entry(host, &nandc->host_list, node) + nand_release(nand_to_mtd(&host->chip)); + + qcom_nandc_unalloc(nandc); + + clk_disable_unprepare(nandc->aon_clk); + clk_disable_unprepare(nandc->core_clk); + + return 0; +} + +#define EBI2_NANDC_ECC_MODES (ECC_RS_4BIT | ECC_BCH_8BIT) + +/* + * data will hold a struct pointer containing more differences once we support + * more controller variants + */ +static const struct of_device_id qcom_nandc_of_match[] = { + { .compatible = "qcom,ipq806x-nand", + .data = (void *)EBI2_NANDC_ECC_MODES, + }, + {} +}; +MODULE_DEVICE_TABLE(of, qcom_nandc_of_match); + +static struct platform_driver qcom_nandc_driver = { + .driver = { + .name = "qcom-nandc", + .of_match_table = qcom_nandc_of_match, + }, + .probe = qcom_nandc_probe, + .remove = qcom_nandc_remove, +}; +module_platform_driver(qcom_nandc_driver); + +MODULE_AUTHOR("Archit Taneja "); +MODULE_DESCRIPTION("Qualcomm NAND Controller driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.1 From 6871c1b96de88d3576d935b528fd1b0ec70e81f5 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 10 Mar 2016 12:47:23 -0800 Subject: mtd: nand: remove kerneldoc for removed function parameter The 'getchip' parameter is gone as of commit 9f3e04297b08 ("mtd: nand: don't select chip in nand_chip's block_bad op"), so kill the doc with it. Reported-by: kbuild test robot Signed-off-by: Brian Norris Acked-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index d49b01d..b6facac 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -313,7 +313,6 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) * nand_block_bad - [DEFAULT] Read bad block marker from the chip * @mtd: MTD device structure * @ofs: offset from device start - * @getchip: 0, if the chip is already selected * * Check, if the block is bad. */ -- cgit v1.1 From 58d303def2a1fbfb5c794bafe7da54b900d9694e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 25 Feb 2016 09:25:20 -0800 Subject: mtd: ubi: Add logging functions ubi_msg, ubi_warn and ubi_err Using logging functions instead of macros can reduce overall object size. $ size drivers/mtd/ubi/built-in.o* text data bss dec hex filename 271620 163364 73696 508680 7c308 drivers/mtd/ubi/built-in.o.allyesconfig.new 287638 165380 73504 526522 808ba drivers/mtd/ubi/built-in.o.allyesconfig.old 87728 3780 504 92012 1676c drivers/mtd/ubi/built-in.o.defconfig.new 97084 3780 504 101368 18bf8 drivers/mtd/ubi/built-in.o.defconfig.old Signed-off-by: Joe Perches Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/misc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ drivers/mtd/ubi/ubi.h | 16 ++++++++++------ 2 files changed, 59 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c index 2a45ac2..989036c 100644 --- a/drivers/mtd/ubi/misc.c +++ b/drivers/mtd/ubi/misc.c @@ -153,3 +153,52 @@ int ubi_check_pattern(const void *buf, uint8_t patt, int size) return 0; return 1; } + +/* Normal UBI messages */ +void ubi_msg(const struct ubi_device *ubi, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + pr_notice(UBI_NAME_STR "%d: %pV\n", ubi->ubi_num, &vaf); + + va_end(args); +} + +/* UBI warning messages */ +void ubi_warn(const struct ubi_device *ubi, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + pr_warn(UBI_NAME_STR "%d warning: %ps: %pV\n", + ubi->ubi_num, __builtin_return_address(0), &vaf); + + va_end(args); +} + +/* UBI error messages */ +void ubi_err(const struct ubi_device *ubi, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + pr_err(UBI_NAME_STR "%d error: %ps: %pV\n", + ubi->ubi_num, __builtin_return_address(0), &vaf); + va_end(args); +} diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 2974b67..dadc6a9 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -49,15 +49,19 @@ /* UBI name used for character devices, sysfs, etc */ #define UBI_NAME_STR "ubi" +struct ubi_device; + /* Normal UBI messages */ -#define ubi_msg(ubi, fmt, ...) pr_notice(UBI_NAME_STR "%d: " fmt "\n", \ - ubi->ubi_num, ##__VA_ARGS__) +__printf(2, 3) +void ubi_msg(const struct ubi_device *ubi, const char *fmt, ...); + /* UBI warning messages */ -#define ubi_warn(ubi, fmt, ...) pr_warn(UBI_NAME_STR "%d warning: %s: " fmt "\n", \ - ubi->ubi_num, __func__, ##__VA_ARGS__) +__printf(2, 3) +void ubi_warn(const struct ubi_device *ubi, const char *fmt, ...); + /* UBI error messages */ -#define ubi_err(ubi, fmt, ...) pr_err(UBI_NAME_STR "%d error: %s: " fmt "\n", \ - ubi->ubi_num, __func__, ##__VA_ARGS__) +__printf(2, 3) +void ubi_err(const struct ubi_device *ubi, const char *fmt, ...); /* Background thread name pattern */ #define UBI_BGT_NAME_PATTERN "ubi_bgt%dd" -- cgit v1.1 From 20c07a5bf094198ff2382aa5e7c930b3c9807792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Fri, 1 Apr 2016 18:29:23 -0300 Subject: mtd: nand: Drop mtd.owner requirement in nand_scan Since commit 807f16d4db95 ("mtd: core: set some defaults when dev.parent is set"), it's now legal for drivers to call nand_scan and nand_scan_ident without setting mtd.owner. Drop the check and while at it remove the BUG() abuse. Fixes: 807f16d4db95 ("mtd: core: set some defaults when dev.parent is set") Signed-off-by: Ezequiel Garcia Acked-by: Boris Brezillon [Brian: editorial note - while commit 807f16d4db95 wasn't explicitly broken, some follow-up commits in the v4.4 release broke a few drivers, since they would hit this BUG() if they used nand_scan() and were built as modules] Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index b6facac..557b846 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4009,7 +4009,6 @@ static int nand_dt_init(struct nand_chip *chip) * This is the first phase of the normal nand_scan() function. It reads the * flash ID and sets up MTD fields accordingly. * - * The mtd->owner field must be set to the module of the caller. */ int nand_scan_ident(struct mtd_info *mtd, int maxchips, struct nand_flash_dev *table) @@ -4429,19 +4428,12 @@ EXPORT_SYMBOL(nand_scan_tail); * * This fills out all the uninitialized function pointers with the defaults. * The flash ID is read and the mtd/chip structures are filled with the - * appropriate values. The mtd->owner field must be set to the module of the - * caller. + * appropriate values. */ int nand_scan(struct mtd_info *mtd, int maxchips) { int ret; - /* Many callers got this wrong, so check for it for a while... */ - if (!mtd->owner && caller_is_module()) { - pr_crit("%s called with NULL mtd->owner!\n", __func__); - BUG(); - } - ret = nand_scan_ident(mtd, maxchips, NULL); if (!ret) ret = nand_scan_tail(mtd); -- cgit v1.1 From 09cbfeaf1a5a67bfb3201e0c83c810cecb2efa5a Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Fri, 1 Apr 2016 15:29:47 +0300 Subject: mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} macros were introduced *long* time ago with promise that one day it will be possible to implement page cache with bigger chunks than PAGE_SIZE. This promise never materialized. And unlikely will. We have many places where PAGE_CACHE_SIZE assumed to be equal to PAGE_SIZE. And it's constant source of confusion on whether PAGE_CACHE_* or PAGE_* constant should be used in a particular case, especially on the border between fs and mm. Global switching to PAGE_CACHE_SIZE != PAGE_SIZE would cause to much breakage to be doable. Let's stop pretending that pages in page cache are special. They are not. The changes are pretty straight-forward: - << (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> ; - >> (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> ; - PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} -> PAGE_{SIZE,SHIFT,MASK,ALIGN}; - page_cache_get() -> get_page(); - page_cache_release() -> put_page(); This patch contains automated changes generated with coccinelle using script below. For some reason, coccinelle doesn't patch header files. I've called spatch for them manually. The only adjustment after coccinelle is revert of changes to PAGE_CAHCE_ALIGN definition: we are going to drop it later. There are few places in the code where coccinelle didn't reach. I'll fix them manually in a separate patch. Comments and documentation also will be addressed with the separate patch. virtual patch @@ expression E; @@ - E << (PAGE_CACHE_SHIFT - PAGE_SHIFT) + E @@ expression E; @@ - E >> (PAGE_CACHE_SHIFT - PAGE_SHIFT) + E @@ @@ - PAGE_CACHE_SHIFT + PAGE_SHIFT @@ @@ - PAGE_CACHE_SIZE + PAGE_SIZE @@ @@ - PAGE_CACHE_MASK + PAGE_MASK @@ expression E; @@ - PAGE_CACHE_ALIGN(E) + PAGE_ALIGN(E) @@ expression E; @@ - page_cache_get(E) + get_page(E) @@ expression E; @@ - page_cache_release(E) + put_page(E) Signed-off-by: Kirill A. Shutemov Acked-by: Michal Hocko Signed-off-by: Linus Torvalds --- drivers/mtd/devices/block2mtd.c | 6 +++--- drivers/mtd/nand/nandsim.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index e2c0057..7c887f1 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -75,7 +75,7 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) break; } - page_cache_release(page); + put_page(page); pages--; index++; } @@ -124,7 +124,7 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len, return PTR_ERR(page); memcpy(buf, page_address(page) + offset, cpylen); - page_cache_release(page); + put_page(page); if (retlen) *retlen += cpylen; @@ -164,7 +164,7 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, unlock_page(page); balance_dirty_pages_ratelimited(mapping); } - page_cache_release(page); + put_page(page); if (retlen) *retlen += cpylen; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 1fd5195..a58169a2 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -1339,7 +1339,7 @@ static void put_pages(struct nandsim *ns) int i; for (i = 0; i < ns->held_cnt; i++) - page_cache_release(ns->held_pages[i]); + put_page(ns->held_pages[i]); } /* Get page cache pages in advance to provide NOFS memory allocation */ @@ -1349,8 +1349,8 @@ static int get_pages(struct nandsim *ns, struct file *file, size_t count, loff_t struct page *page; struct address_space *mapping = file->f_mapping; - start_index = pos >> PAGE_CACHE_SHIFT; - end_index = (pos + count - 1) >> PAGE_CACHE_SHIFT; + start_index = pos >> PAGE_SHIFT; + end_index = (pos + count - 1) >> PAGE_SHIFT; if (end_index - start_index + 1 > NS_MAX_HELD_PAGES) return -EINVAL; ns->held_cnt = 0; -- cgit v1.1