aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/mtdchar.c10
-rw-r--r--drivers/mtd/mtdsuper.c54
-rw-r--r--drivers/mtd/nand/davinci_nand.c61
3 files changed, 49 insertions, 76 deletions
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3eff1e562ad3..4759d827e8c7 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1131,17 +1131,15 @@ static const struct file_operations mtd_fops = {
1131#endif 1131#endif
1132}; 1132};
1133 1133
1134static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags, 1134static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type,
1135 const char *dev_name, void *data, 1135 int flags, const char *dev_name, void *data)
1136 struct vfsmount *mnt)
1137{ 1136{
1138 return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, 1137 return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC);
1139 mnt);
1140} 1138}
1141 1139
1142static struct file_system_type mtd_inodefs_type = { 1140static struct file_system_type mtd_inodefs_type = {
1143 .name = "mtd_inodefs", 1141 .name = "mtd_inodefs",
1144 .get_sb = mtd_inodefs_get_sb, 1142 .mount = mtd_inodefs_mount,
1145 .kill_sb = kill_anon_super, 1143 .kill_sb = kill_anon_super,
1146}; 1144};
1147 1145
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c
index 38e2ab07e7a3..16b02a1fc100 100644
--- a/drivers/mtd/mtdsuper.c
+++ b/drivers/mtd/mtdsuper.c
@@ -54,11 +54,10 @@ static int get_sb_mtd_set(struct super_block *sb, void *_mtd)
54/* 54/*
55 * get a superblock on an MTD-backed filesystem 55 * get a superblock on an MTD-backed filesystem
56 */ 56 */
57static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags, 57static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags,
58 const char *dev_name, void *data, 58 const char *dev_name, void *data,
59 struct mtd_info *mtd, 59 struct mtd_info *mtd,
60 int (*fill_super)(struct super_block *, void *, int), 60 int (*fill_super)(struct super_block *, void *, int))
61 struct vfsmount *mnt)
62{ 61{
63 struct super_block *sb; 62 struct super_block *sb;
64 int ret; 63 int ret;
@@ -79,57 +78,49 @@ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags,
79 ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); 78 ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
80 if (ret < 0) { 79 if (ret < 0) {
81 deactivate_locked_super(sb); 80 deactivate_locked_super(sb);
82 return ret; 81 return ERR_PTR(ret);
83 } 82 }
84 83
85 /* go */ 84 /* go */
86 sb->s_flags |= MS_ACTIVE; 85 sb->s_flags |= MS_ACTIVE;
87 simple_set_mnt(mnt, sb); 86 return dget(sb->s_root);
88
89 return 0;
90 87
91 /* new mountpoint for an already mounted superblock */ 88 /* new mountpoint for an already mounted superblock */
92already_mounted: 89already_mounted:
93 DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n", 90 DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n",
94 mtd->index, mtd->name); 91 mtd->index, mtd->name);
95 simple_set_mnt(mnt, sb); 92 put_mtd_device(mtd);
96 ret = 0; 93 return dget(sb->s_root);
97 goto out_put;
98 94
99out_error: 95out_error:
100 ret = PTR_ERR(sb);
101out_put:
102 put_mtd_device(mtd); 96 put_mtd_device(mtd);
103 return ret; 97 return ERR_CAST(sb);
104} 98}
105 99
106/* 100/*
107 * get a superblock on an MTD-backed filesystem by MTD device number 101 * get a superblock on an MTD-backed filesystem by MTD device number
108 */ 102 */
109static int get_sb_mtd_nr(struct file_system_type *fs_type, int flags, 103static struct dentry *mount_mtd_nr(struct file_system_type *fs_type, int flags,
110 const char *dev_name, void *data, int mtdnr, 104 const char *dev_name, void *data, int mtdnr,
111 int (*fill_super)(struct super_block *, void *, int), 105 int (*fill_super)(struct super_block *, void *, int))
112 struct vfsmount *mnt)
113{ 106{
114 struct mtd_info *mtd; 107 struct mtd_info *mtd;
115 108
116 mtd = get_mtd_device(NULL, mtdnr); 109 mtd = get_mtd_device(NULL, mtdnr);
117 if (IS_ERR(mtd)) { 110 if (IS_ERR(mtd)) {
118 DEBUG(0, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr); 111 DEBUG(0, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
119 return PTR_ERR(mtd); 112 return ERR_CAST(mtd);
120 } 113 }
121 114
122 return get_sb_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super, 115 return mount_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super);
123 mnt);
124} 116}
125 117
126/* 118/*
127 * set up an MTD-based superblock 119 * set up an MTD-based superblock
128 */ 120 */
129int get_sb_mtd(struct file_system_type *fs_type, int flags, 121struct dentry *mount_mtd(struct file_system_type *fs_type, int flags,
130 const char *dev_name, void *data, 122 const char *dev_name, void *data,
131 int (*fill_super)(struct super_block *, void *, int), 123 int (*fill_super)(struct super_block *, void *, int))
132 struct vfsmount *mnt)
133{ 124{
134#ifdef CONFIG_BLOCK 125#ifdef CONFIG_BLOCK
135 struct block_device *bdev; 126 struct block_device *bdev;
@@ -138,7 +129,7 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags,
138 int mtdnr; 129 int mtdnr;
139 130
140 if (!dev_name) 131 if (!dev_name)
141 return -EINVAL; 132 return ERR_PTR(-EINVAL);
142 133
143 DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name); 134 DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name);
144 135
@@ -156,10 +147,10 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags,
156 147
157 mtd = get_mtd_device_nm(dev_name + 4); 148 mtd = get_mtd_device_nm(dev_name + 4);
158 if (!IS_ERR(mtd)) 149 if (!IS_ERR(mtd))
159 return get_sb_mtd_aux( 150 return mount_mtd_aux(
160 fs_type, flags, 151 fs_type, flags,
161 dev_name, data, mtd, 152 dev_name, data, mtd,
162 fill_super, mnt); 153 fill_super);
163 154
164 printk(KERN_NOTICE "MTD:" 155 printk(KERN_NOTICE "MTD:"
165 " MTD device with name \"%s\" not found.\n", 156 " MTD device with name \"%s\" not found.\n",
@@ -174,9 +165,9 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags,
174 /* It was a valid number */ 165 /* It was a valid number */
175 DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n", 166 DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n",
176 mtdnr); 167 mtdnr);
177 return get_sb_mtd_nr(fs_type, flags, 168 return mount_mtd_nr(fs_type, flags,
178 dev_name, data, 169 dev_name, data,
179 mtdnr, fill_super, mnt); 170 mtdnr, fill_super);
180 } 171 }
181 } 172 }
182 } 173 }
@@ -189,7 +180,7 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags,
189 if (IS_ERR(bdev)) { 180 if (IS_ERR(bdev)) {
190 ret = PTR_ERR(bdev); 181 ret = PTR_ERR(bdev);
191 DEBUG(1, "MTDSB: lookup_bdev() returned %d\n", ret); 182 DEBUG(1, "MTDSB: lookup_bdev() returned %d\n", ret);
192 return ret; 183 return ERR_PTR(ret);
193 } 184 }
194 DEBUG(1, "MTDSB: lookup_bdev() returned 0\n"); 185 DEBUG(1, "MTDSB: lookup_bdev() returned 0\n");
195 186
@@ -202,8 +193,7 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags,
202 if (major != MTD_BLOCK_MAJOR) 193 if (major != MTD_BLOCK_MAJOR)
203 goto not_an_MTD_device; 194 goto not_an_MTD_device;
204 195
205 return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super, 196 return mount_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super);
206 mnt);
207 197
208not_an_MTD_device: 198not_an_MTD_device:
209#endif /* CONFIG_BLOCK */ 199#endif /* CONFIG_BLOCK */
@@ -212,10 +202,10 @@ not_an_MTD_device:
212 printk(KERN_NOTICE 202 printk(KERN_NOTICE
213 "MTD: Attempt to mount non-MTD device \"%s\"\n", 203 "MTD: Attempt to mount non-MTD device \"%s\"\n",
214 dev_name); 204 dev_name);
215 return -EINVAL; 205 return ERR_PTR(-EINVAL);
216} 206}
217 207
218EXPORT_SYMBOL_GPL(get_sb_mtd); 208EXPORT_SYMBOL_GPL(mount_mtd);
219 209
220/* 210/*
221 * destroy an MTD-based superblock 211 * destroy an MTD-based superblock
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index ad51f8ef0d4f..a90fde3ede28 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -35,6 +35,7 @@
35#include <linux/slab.h> 35#include <linux/slab.h>
36 36
37#include <mach/nand.h> 37#include <mach/nand.h>
38#include <mach/aemif.h>
38 39
39#include <asm/mach-types.h> 40#include <asm/mach-types.h>
40 41
@@ -74,6 +75,8 @@ struct davinci_nand_info {
74 uint32_t mask_cle; 75 uint32_t mask_cle;
75 76
76 uint32_t core_chipsel; 77 uint32_t core_chipsel;
78
79 struct davinci_aemif_timing *timing;
77}; 80};
78 81
79static DEFINE_SPINLOCK(davinci_nand_lock); 82static DEFINE_SPINLOCK(davinci_nand_lock);
@@ -480,36 +483,6 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
480 return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0); 483 return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
481} 484}
482 485
483static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
484{
485 uint32_t regval, a1cr;
486
487 /*
488 * NAND FLASH timings @ PLL1 == 459 MHz
489 * - AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz
490 * - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns
491 */
492 regval = 0
493 | (0 << 31) /* selectStrobe */
494 | (0 << 30) /* extWait (never with NAND) */
495 | (1 << 26) /* writeSetup 10 ns */
496 | (3 << 20) /* writeStrobe 40 ns */
497 | (1 << 17) /* writeHold 10 ns */
498 | (0 << 13) /* readSetup 10 ns */
499 | (3 << 7) /* readStrobe 60 ns */
500 | (0 << 4) /* readHold 10 ns */
501 | (3 << 2) /* turnAround ?? ns */
502 | (0 << 0) /* asyncSize 8-bit bus */
503 ;
504 a1cr = davinci_nand_readl(info, A1CR_OFFSET);
505 if (a1cr != regval) {
506 dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \
507 "reg to 0x%08x, was 0x%08x, should be done by " \
508 "bootloader.\n", regval, a1cr);
509 davinci_nand_writel(info, A1CR_OFFSET, regval);
510 }
511}
512
513/*----------------------------------------------------------------------*/ 486/*----------------------------------------------------------------------*/
514 487
515/* An ECC layout for using 4-bit ECC with small-page flash, storing 488/* An ECC layout for using 4-bit ECC with small-page flash, storing
@@ -613,6 +586,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
613 info->chip.options = pdata->options; 586 info->chip.options = pdata->options;
614 info->chip.bbt_td = pdata->bbt_td; 587 info->chip.bbt_td = pdata->bbt_td;
615 info->chip.bbt_md = pdata->bbt_md; 588 info->chip.bbt_md = pdata->bbt_md;
589 info->timing = pdata->timing;
616 590
617 info->ioaddr = (uint32_t __force) vaddr; 591 info->ioaddr = (uint32_t __force) vaddr;
618 592
@@ -690,15 +664,25 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
690 goto err_clk_enable; 664 goto err_clk_enable;
691 } 665 }
692 666
693 /* EMIF timings should normally be set by the boot loader, 667 /*
694 * especially after boot-from-NAND. The *only* reason to 668 * Setup Async configuration register in case we did not boot from
695 * have this special casing for the DM6446 EVM is to work 669 * NAND and so bootloader did not bother to set it up.
696 * with boot-from-NOR ... with CS0 manually re-jumpered
697 * (after startup) so it addresses the NAND flash, not NOR.
698 * Even for dev boards, that's unusually rude...
699 */ 670 */
700 if (machine_is_davinci_evm()) 671 val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
701 nand_dm6446evm_flash_init(info); 672
673 /* Extended Wait is not valid and Select Strobe mode is not used */
674 val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
675 if (info->chip.options & NAND_BUSWIDTH_16)
676 val |= 0x1;
677
678 davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
679
680 ret = davinci_aemif_setup_timing(info->timing, info->base,
681 info->core_chipsel);
682 if (ret < 0) {
683 dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
684 goto err_timing;
685 }
702 686
703 spin_lock_irq(&davinci_nand_lock); 687 spin_lock_irq(&davinci_nand_lock);
704 688
@@ -814,6 +798,7 @@ syndrome_done:
814 return 0; 798 return 0;
815 799
816err_scan: 800err_scan:
801err_timing:
817 clk_disable(info->clk); 802 clk_disable(info->clk);
818 803
819err_clk_enable: 804err_clk_enable: