aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/mtdcore.c2
-rw-r--r--drivers/mtd/nand/atmel_nand.c45
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-lib.c18
-rw-r--r--drivers/mtd/nand/nand_base.c2
4 files changed, 57 insertions, 10 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 6ae9ca01388b..9a9ce71a71fc 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -119,7 +119,7 @@ static int mtd_cls_suspend(struct device *dev, pm_message_t state)
119{ 119{
120 struct mtd_info *mtd = dev_get_drvdata(dev); 120 struct mtd_info *mtd = dev_get_drvdata(dev);
121 121
122 return mtd_suspend(mtd); 122 return mtd ? mtd_suspend(mtd) : 0;
123} 123}
124 124
125static int mtd_cls_resume(struct device *dev) 125static int mtd_cls_resume(struct device *dev)
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 4dd056e2e16a..35b4fb55dbd6 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -161,6 +161,37 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
161 !!host->board->rdy_pin_active_low; 161 !!host->board->rdy_pin_active_low;
162} 162}
163 163
164/*
165 * Minimal-overhead PIO for data access.
166 */
167static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
168{
169 struct nand_chip *nand_chip = mtd->priv;
170
171 __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
172}
173
174static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
175{
176 struct nand_chip *nand_chip = mtd->priv;
177
178 __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
179}
180
181static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
182{
183 struct nand_chip *nand_chip = mtd->priv;
184
185 __raw_writesb(nand_chip->IO_ADDR_W, buf, len);
186}
187
188static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
189{
190 struct nand_chip *nand_chip = mtd->priv;
191
192 __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
193}
194
164static void dma_complete_func(void *completion) 195static void dma_complete_func(void *completion)
165{ 196{
166 complete(completion); 197 complete(completion);
@@ -235,27 +266,33 @@ err_buf:
235static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) 266static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
236{ 267{
237 struct nand_chip *chip = mtd->priv; 268 struct nand_chip *chip = mtd->priv;
269 struct atmel_nand_host *host = chip->priv;
238 270
239 if (use_dma && len > mtd->oobsize) 271 if (use_dma && len > mtd->oobsize)
240 /* only use DMA for bigger than oob size: better performances */ 272 /* only use DMA for bigger than oob size: better performances */
241 if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) 273 if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
242 return; 274 return;
243 275
244 /* if no DMA operation possible, use PIO */ 276 if (host->board->bus_width_16)
245 memcpy_fromio(buf, chip->IO_ADDR_R, len); 277 atmel_read_buf16(mtd, buf, len);
278 else
279 atmel_read_buf8(mtd, buf, len);
246} 280}
247 281
248static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) 282static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
249{ 283{
250 struct nand_chip *chip = mtd->priv; 284 struct nand_chip *chip = mtd->priv;
285 struct atmel_nand_host *host = chip->priv;
251 286
252 if (use_dma && len > mtd->oobsize) 287 if (use_dma && len > mtd->oobsize)
253 /* only use DMA for bigger than oob size: better performances */ 288 /* only use DMA for bigger than oob size: better performances */
254 if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) 289 if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
255 return; 290 return;
256 291
257 /* if no DMA operation possible, use PIO */ 292 if (host->board->bus_width_16)
258 memcpy_toio(chip->IO_ADDR_W, buf, len); 293 atmel_write_buf16(mtd, buf, len);
294 else
295 atmel_write_buf8(mtd, buf, len);
259} 296}
260 297
261/* 298/*
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 7f680420bfab..7db6555ed3ba 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)
69 * [1] enable the module. 69 * [1] enable the module.
70 * [2] reset the module. 70 * [2] reset the module.
71 * 71 *
72 * In most of the cases, it's ok. But there is a hardware bug in the BCH block. 72 * In most of the cases, it's ok.
73 * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
73 * If you try to soft reset the BCH block, it becomes unusable until 74 * If you try to soft reset the BCH block, it becomes unusable until
74 * the next hard reset. This case occurs in the NAND boot mode. When the board 75 * the next hard reset. This case occurs in the NAND boot mode. When the board
75 * boots by NAND, the ROM of the chip will initialize the BCH blocks itself. 76 * boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
76 * So If the driver tries to reset the BCH again, the BCH will not work anymore. 77 * So If the driver tries to reset the BCH again, the BCH will not work anymore.
77 * You will see a DMA timeout in this case. 78 * You will see a DMA timeout in this case. The bug has been fixed
79 * in the following chips, such as MX28.
78 * 80 *
79 * To avoid this bug, just add a new parameter `just_enable` for 81 * To avoid this bug, just add a new parameter `just_enable` for
80 * the mxs_reset_block(), and rewrite it here. 82 * the mxs_reset_block(), and rewrite it here.
81 */ 83 */
82int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) 84static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
83{ 85{
84 int ret; 86 int ret;
85 int timeout = 0x400; 87 int timeout = 0x400;
@@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this)
206 if (ret) 208 if (ret)
207 goto err_out; 209 goto err_out;
208 210
209 ret = gpmi_reset_block(r->bch_regs, true); 211 /*
212 * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
213 * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
214 * On the other hand, the MX28 needs the reset, because one case has been
215 * seen where the BCH produced ECC errors constantly after 10000
216 * consecutive reboots. The latter case has not been seen on the MX23 yet,
217 * still we don't know if it could happen there as well.
218 */
219 ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
210 if (ret) 220 if (ret)
211 goto err_out; 221 goto err_out;
212 222
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 35b4565050f1..8a393f9e6027 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2588,7 +2588,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
2588 instr->state = MTD_ERASING; 2588 instr->state = MTD_ERASING;
2589 2589
2590 while (len) { 2590 while (len) {
2591 /* Heck if we have a bad block, we do not erase bad blocks! */ 2591 /* Check if we have a bad block, we do not erase bad blocks! */
2592 if (nand_block_checkbad(mtd, ((loff_t) page) << 2592 if (nand_block_checkbad(mtd, ((loff_t) page) <<
2593 chip->page_shift, 0, allowbbt)) { 2593 chip->page_shift, 0, allowbbt)) {
2594 pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", 2594 pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",