diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/mtdchar.c | 10 | ||||
-rw-r--r-- | drivers/mtd/mtdsuper.c | 54 | ||||
-rw-r--r-- | drivers/mtd/nand/davinci_nand.c | 61 |
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 | ||
1134 | static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags, | 1134 | static 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 | ||
1142 | static struct file_system_type mtd_inodefs_type = { | 1140 | static 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 | */ |
57 | static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags, | 57 | static 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 */ |
92 | already_mounted: | 89 | already_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 | ||
99 | out_error: | 95 | out_error: |
100 | ret = PTR_ERR(sb); | ||
101 | out_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 | */ |
109 | static int get_sb_mtd_nr(struct file_system_type *fs_type, int flags, | 103 | static 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 | */ |
129 | int get_sb_mtd(struct file_system_type *fs_type, int flags, | 121 | struct 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 | ||
208 | not_an_MTD_device: | 198 | not_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 | ||
218 | EXPORT_SYMBOL_GPL(get_sb_mtd); | 208 | EXPORT_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 | ||
79 | static DEFINE_SPINLOCK(davinci_nand_lock); | 82 | static 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 | ||
483 | static 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 | ||
816 | err_scan: | 800 | err_scan: |
801 | err_timing: | ||
817 | clk_disable(info->clk); | 802 | clk_disable(info->clk); |
818 | 803 | ||
819 | err_clk_enable: | 804 | err_clk_enable: |