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", |
