diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/mtdcore.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 45 | ||||
-rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 18 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 2 |
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 | ||
125 | static int mtd_cls_resume(struct device *dev) | 125 | static 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 | */ | ||
167 | static 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 | |||
174 | static 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 | |||
181 | static 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 | |||
188 | static 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 | |||
164 | static void dma_complete_func(void *completion) | 195 | static void dma_complete_func(void *completion) |
165 | { | 196 | { |
166 | complete(completion); | 197 | complete(completion); |
@@ -235,27 +266,33 @@ err_buf: | |||
235 | static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) | 266 | static 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 | ||
248 | static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | 282 | static 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 | */ |
82 | int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) | 84 | static 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", |