aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/fsl_upm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/fsl_upm.c')
-rw-r--r--drivers/mtd/nand/fsl_upm.c68
1 files changed, 43 insertions, 25 deletions
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 1ebfd87f00b..024e3fffd4b 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -13,6 +13,7 @@
13 13
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/delay.h>
16#include <linux/mtd/nand.h> 17#include <linux/mtd/nand.h>
17#include <linux/mtd/nand_ecc.h> 18#include <linux/mtd/nand_ecc.h>
18#include <linux/mtd/partitions.h> 19#include <linux/mtd/partitions.h>
@@ -36,8 +37,6 @@ struct fsl_upm_nand {
36 uint8_t upm_cmd_offset; 37 uint8_t upm_cmd_offset;
37 void __iomem *io_base; 38 void __iomem *io_base;
38 int rnb_gpio; 39 int rnb_gpio;
39 const uint32_t *wait_pattern;
40 const uint32_t *wait_write;
41 int chip_delay; 40 int chip_delay;
42}; 41};
43 42
@@ -61,10 +60,11 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun)
61 if (fun->rnb_gpio >= 0) { 60 if (fun->rnb_gpio >= 0) {
62 while (--cnt && !fun_chip_ready(&fun->mtd)) 61 while (--cnt && !fun_chip_ready(&fun->mtd))
63 cpu_relax(); 62 cpu_relax();
63 if (!cnt)
64 dev_err(fun->dev, "tired waiting for RNB\n");
65 } else {
66 ndelay(100);
64 } 67 }
65
66 if (!cnt)
67 dev_err(fun->dev, "tired waiting for RNB\n");
68} 68}
69 69
70static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) 70static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -89,8 +89,7 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
89 89
90 fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd); 90 fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd);
91 91
92 if (fun->wait_pattern) 92 fun_wait_rnb(fun);
93 fun_wait_rnb(fun);
94} 93}
95 94
96static uint8_t fun_read_byte(struct mtd_info *mtd) 95static uint8_t fun_read_byte(struct mtd_info *mtd)
@@ -116,14 +115,16 @@ static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
116 115
117 for (i = 0; i < len; i++) { 116 for (i = 0; i < len; i++) {
118 out_8(fun->chip.IO_ADDR_W, buf[i]); 117 out_8(fun->chip.IO_ADDR_W, buf[i]);
119 if (fun->wait_write) 118 fun_wait_rnb(fun);
120 fun_wait_rnb(fun);
121 } 119 }
122} 120}
123 121
124static int __devinit fun_chip_init(struct fsl_upm_nand *fun) 122static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
123 const struct device_node *upm_np,
124 const struct resource *io_res)
125{ 125{
126 int ret; 126 int ret;
127 struct device_node *flash_np;
127#ifdef CONFIG_MTD_PARTITIONS 128#ifdef CONFIG_MTD_PARTITIONS
128 static const char *part_types[] = { "cmdlinepart", NULL, }; 129 static const char *part_types[] = { "cmdlinepart", NULL, };
129#endif 130#endif
@@ -143,18 +144,37 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun)
143 fun->mtd.priv = &fun->chip; 144 fun->mtd.priv = &fun->chip;
144 fun->mtd.owner = THIS_MODULE; 145 fun->mtd.owner = THIS_MODULE;
145 146
147 flash_np = of_get_next_child(upm_np, NULL);
148 if (!flash_np)
149 return -ENODEV;
150
151 fun->mtd.name = kasprintf(GFP_KERNEL, "%x.%s", io_res->start,
152 flash_np->name);
153 if (!fun->mtd.name) {
154 ret = -ENOMEM;
155 goto err;
156 }
157
146 ret = nand_scan(&fun->mtd, 1); 158 ret = nand_scan(&fun->mtd, 1);
147 if (ret) 159 if (ret)
148 return ret; 160 goto err;
149
150 fun->mtd.name = fun->dev->bus_id;
151 161
152#ifdef CONFIG_MTD_PARTITIONS 162#ifdef CONFIG_MTD_PARTITIONS
153 ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0); 163 ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
164
165#ifdef CONFIG_MTD_OF_PARTS
166 if (ret == 0)
167 ret = of_mtd_parse_partitions(fun->dev, &fun->mtd,
168 flash_np, &fun->parts);
169#endif
154 if (ret > 0) 170 if (ret > 0)
155 return add_mtd_partitions(&fun->mtd, fun->parts, ret); 171 ret = add_mtd_partitions(&fun->mtd, fun->parts, ret);
172 else
156#endif 173#endif
157 return add_mtd_device(&fun->mtd); 174 ret = add_mtd_device(&fun->mtd);
175err:
176 of_node_put(flash_np);
177 return ret;
158} 178}
159 179
160static int __devinit fun_probe(struct of_device *ofdev, 180static int __devinit fun_probe(struct of_device *ofdev,
@@ -211,6 +231,12 @@ static int __devinit fun_probe(struct of_device *ofdev,
211 goto err2; 231 goto err2;
212 } 232 }
213 233
234 prop = of_get_property(ofdev->node, "chip-delay", NULL);
235 if (prop)
236 fun->chip_delay = *prop;
237 else
238 fun->chip_delay = 50;
239
214 fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start, 240 fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start,
215 io_res.end - io_res.start + 1); 241 io_res.end - io_res.start + 1);
216 if (!fun->io_base) { 242 if (!fun->io_base) {
@@ -220,17 +246,8 @@ static int __devinit fun_probe(struct of_device *ofdev,
220 246
221 fun->dev = &ofdev->dev; 247 fun->dev = &ofdev->dev;
222 fun->last_ctrl = NAND_CLE; 248 fun->last_ctrl = NAND_CLE;
223 fun->wait_pattern = of_get_property(ofdev->node, "fsl,wait-pattern",
224 NULL);
225 fun->wait_write = of_get_property(ofdev->node, "fsl,wait-write", NULL);
226
227 prop = of_get_property(ofdev->node, "chip-delay", NULL);
228 if (prop)
229 fun->chip_delay = *prop;
230 else
231 fun->chip_delay = 50;
232 249
233 ret = fun_chip_init(fun); 250 ret = fun_chip_init(fun, ofdev->node, &io_res);
234 if (ret) 251 if (ret)
235 goto err2; 252 goto err2;
236 253
@@ -251,6 +268,7 @@ static int __devexit fun_remove(struct of_device *ofdev)
251 struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); 268 struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
252 269
253 nand_release(&fun->mtd); 270 nand_release(&fun->mtd);
271 kfree(fun->mtd.name);
254 272
255 if (fun->rnb_gpio >= 0) 273 if (fun->rnb_gpio >= 0)
256 gpio_free(fun->rnb_gpio); 274 gpio_free(fun->rnb_gpio);