diff options
author | Artem Bityutskiy <artem.bityutskiy@linux.intel.com> | 2012-02-02 06:54:25 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-02-04 03:04:57 -0500 |
commit | 500823195d0c9eec2a4637484f30cc93ec633d4a (patch) | |
tree | 9fa140cfce10567d10f5e7e708f71193ff9ec228 /drivers/mtd | |
parent | 1a30871fe635d3e92972e6b93e39ff65bb57e52d (diff) |
Revert "mtd: atmel_nand: optimize read/write buffer functions"
This reverts commit fb5427508abbd635e877fabdf55795488119c2d6.
The reason is that it breaks 16 bits NAND flash as it was reported by
Nikolaus Voss and confirmed by Eric BĂ©nard.
Nicolas Ferre <nicolas.ferre@atmel.com> alco confirmed:
"After double checking with designers, I must admit that I misunderstood
the way of optimizing accesses to SMC. 16 bit nand is not so common
those days..."
Reported-by: Nikolaus Voss <n.voss@weinmann.de>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Cc: stable@kernel.org [3.1+]
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 45 |
1 files changed, 41 insertions, 4 deletions
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 | /* |