diff options
author | Ben Dooks <ben@simtec.co.uk> | 2005-03-17 06:31:30 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@mtd.linutronix.de> | 2005-05-23 06:55:50 -0400 |
commit | 3e4ef3bb77f7b87c631ba188d4a4b4eb30b2f16f (patch) | |
tree | 3ca45d8f929bf85f79036d8419519073f79b9d0b /drivers/mtd/nand | |
parent | 09c7933547e383ab89ee1b08ec86899bef3035cf (diff) |
[MTD] NAND s3c2410: Simplify command handling
Updated with tglx's suggestion to simply the command invocation by
simply changing the address of the IO write area
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 118 |
1 files changed, 12 insertions, 106 deletions
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index cb04b3c771e4..64b1d95e3e37 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -11,9 +11,10 @@ | |||
11 | * 23-Sep-2004 BJD Mulitple device support | 11 | * 23-Sep-2004 BJD Mulitple device support |
12 | * 28-Sep-2004 BJD Fixed ECC placement for Hardware mode | 12 | * 28-Sep-2004 BJD Fixed ECC placement for Hardware mode |
13 | * 12-Oct-2004 BJD Fixed errors in use of platform data | 13 | * 12-Oct-2004 BJD Fixed errors in use of platform data |
14 | * 18-Feb-2004 BJD Fix sparse errors | 14 | * 18-Feb-2005 BJD Fix sparse errors |
15 | * 14-Mar-2005 BJD Applied tglx's code reduction patch | ||
15 | * | 16 | * |
16 | * $Id: s3c2410.c,v 1.8 2005/02/18 14:46:12 bjd Exp $ | 17 | * $Id: s3c2410.c,v 1.12 2005/03/17 11:31:26 bjd Exp $ |
17 | * | 18 | * |
18 | * This program is free software; you can redistribute it and/or modify | 19 | * This program is free software; you can redistribute it and/or modify |
19 | * it under the terms of the GNU General Public License as published by | 20 | * it under the terms of the GNU General Public License as published by |
@@ -236,6 +237,7 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) | |||
236 | static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd) | 237 | static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd) |
237 | { | 238 | { |
238 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | 239 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); |
240 | struct nand_chip *chip = mtd->priv; | ||
239 | unsigned long cur; | 241 | unsigned long cur; |
240 | 242 | ||
241 | switch (cmd) { | 243 | switch (cmd) { |
@@ -251,117 +253,22 @@ static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd) | |||
251 | writel(cur, info->regs + S3C2410_NFCONF); | 253 | writel(cur, info->regs + S3C2410_NFCONF); |
252 | break; | 254 | break; |
253 | 255 | ||
254 | /* we don't need to implement these */ | ||
255 | case NAND_CTL_SETCLE: | 256 | case NAND_CTL_SETCLE: |
256 | case NAND_CTL_CLRCLE: | 257 | chip->IO_ADDR_W = info->regs + S3C2410_NFCMD; |
257 | case NAND_CTL_SETALE: | ||
258 | case NAND_CTL_CLRALE: | ||
259 | pr_debug(PFX "s3c2410_nand_hwcontrol(%d) unusedn", cmd); | ||
260 | break; | 258 | break; |
261 | } | ||
262 | } | ||
263 | |||
264 | /* s3c2410_nand_command | ||
265 | * | ||
266 | * This function implements sending commands and the relevant address | ||
267 | * information to the chip, via the hardware controller. Since the | ||
268 | * S3C2410 generates the correct ALE/CLE signaling automatically, we | ||
269 | * do not need to use hwcontrol. | ||
270 | */ | ||
271 | |||
272 | static void s3c2410_nand_command (struct mtd_info *mtd, unsigned command, | ||
273 | int column, int page_addr) | ||
274 | { | ||
275 | register struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | ||
276 | register struct nand_chip *this = mtd->priv; | ||
277 | |||
278 | /* | ||
279 | * Write out the command to the device. | ||
280 | */ | ||
281 | if (command == NAND_CMD_SEQIN) { | ||
282 | int readcmd; | ||
283 | |||
284 | if (column >= mtd->oobblock) { | ||
285 | /* OOB area */ | ||
286 | column -= mtd->oobblock; | ||
287 | readcmd = NAND_CMD_READOOB; | ||
288 | } else if (column < 256) { | ||
289 | /* First 256 bytes --> READ0 */ | ||
290 | readcmd = NAND_CMD_READ0; | ||
291 | } else { | ||
292 | column -= 256; | ||
293 | readcmd = NAND_CMD_READ1; | ||
294 | } | ||
295 | |||
296 | writeb(readcmd, info->regs + S3C2410_NFCMD); | ||
297 | } | ||
298 | writeb(command, info->regs + S3C2410_NFCMD); | ||
299 | |||
300 | /* Set ALE and clear CLE to start address cycle */ | ||
301 | 259 | ||
302 | if (column != -1 || page_addr != -1) { | 260 | case NAND_CTL_SETALE: |
261 | chip->IO_ADDR_W = info->regs + S3C2410_NFADDR; | ||
262 | break; | ||
303 | 263 | ||
304 | /* Serially input address */ | 264 | /* NAND_CTL_CLRCLE: */ |
305 | if (column != -1) { | 265 | /* NAND_CTL_CLRALE: */ |
306 | /* Adjust columns for 16 bit buswidth */ | ||
307 | if (this->options & NAND_BUSWIDTH_16) | ||
308 | column >>= 1; | ||
309 | writeb(column, info->regs + S3C2410_NFADDR); | ||
310 | } | ||
311 | if (page_addr != -1) { | ||
312 | writeb((unsigned char) (page_addr), info->regs + S3C2410_NFADDR); | ||
313 | writeb((unsigned char) (page_addr >> 8), info->regs + S3C2410_NFADDR); | ||
314 | /* One more address cycle for higher density devices */ | ||
315 | if (this->chipsize & 0x0c000000) | ||
316 | writeb((unsigned char) ((page_addr >> 16) & 0x0f), | ||
317 | info->regs + S3C2410_NFADDR); | ||
318 | } | ||
319 | /* Latch in address */ | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * program and erase have their own busy handlers | ||
324 | * status and sequential in needs no delay | ||
325 | */ | ||
326 | switch (command) { | ||
327 | |||
328 | case NAND_CMD_PAGEPROG: | ||
329 | case NAND_CMD_ERASE1: | ||
330 | case NAND_CMD_ERASE2: | ||
331 | case NAND_CMD_SEQIN: | ||
332 | case NAND_CMD_STATUS: | ||
333 | return; | ||
334 | |||
335 | case NAND_CMD_RESET: | ||
336 | if (this->dev_ready) | ||
337 | break; | ||
338 | |||
339 | udelay(this->chip_delay); | ||
340 | writeb(NAND_CMD_STATUS, info->regs + S3C2410_NFCMD); | ||
341 | |||
342 | while ( !(this->read_byte(mtd) & 0x40)); | ||
343 | return; | ||
344 | |||
345 | /* This applies to read commands */ | ||
346 | default: | 266 | default: |
347 | /* | 267 | chip->IO_ADDR_W = info->regs + S3C2410_NFDATA; |
348 | * If we don't have access to the busy pin, we apply the given | 268 | break; |
349 | * command delay | ||
350 | */ | ||
351 | if (!this->dev_ready) { | ||
352 | udelay (this->chip_delay); | ||
353 | return; | ||
354 | } | ||
355 | } | 269 | } |
356 | |||
357 | /* Apply this short delay always to ensure that we do wait tWB in | ||
358 | * any case on any machine. */ | ||
359 | ndelay (100); | ||
360 | /* wait until command is processed */ | ||
361 | while (!this->dev_ready(mtd)); | ||
362 | } | 270 | } |
363 | 271 | ||
364 | |||
365 | /* s3c2410_nand_devready() | 272 | /* s3c2410_nand_devready() |
366 | * | 273 | * |
367 | * returns 0 if the nand is busy, 1 if it is ready | 274 | * returns 0 if the nand is busy, 1 if it is ready |
@@ -529,7 +436,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
529 | chip->IO_ADDR_W = info->regs + S3C2410_NFDATA; | 436 | chip->IO_ADDR_W = info->regs + S3C2410_NFDATA; |
530 | chip->hwcontrol = s3c2410_nand_hwcontrol; | 437 | chip->hwcontrol = s3c2410_nand_hwcontrol; |
531 | chip->dev_ready = s3c2410_nand_devready; | 438 | chip->dev_ready = s3c2410_nand_devready; |
532 | chip->cmdfunc = s3c2410_nand_command; | ||
533 | chip->write_buf = s3c2410_nand_write_buf; | 439 | chip->write_buf = s3c2410_nand_write_buf; |
534 | chip->read_buf = s3c2410_nand_read_buf; | 440 | chip->read_buf = s3c2410_nand_read_buf; |
535 | chip->select_chip = s3c2410_nand_select_chip; | 441 | chip->select_chip = s3c2410_nand_select_chip; |