From: Marek Vasut <marek.vasut@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 5/5] PXA: PXA3xx NAND Driver
Date: Sat, 10 Jul 2010 00:24:27 +0200 [thread overview]
Message-ID: <201007100024.28013.marek.vasut@gmail.com> (raw)
In-Reply-To: <20100709200400.GB7056@schlenkerla.am.freescale.net>
Dne P? 9. ?ervence 2010 22:04:00 Scott Wood napsal(a):
> On Tue, Jul 06, 2010 at 03:12:49AM +0200, Marek Vasut wrote:
> > From: Compulab uboot <none@none>
>
> Hmm?
Well I was unable to figure out who was the author, though the license of the
code is GPL so it should be OK ? I'll try poking around a little bit more, but
it's unlikely I'll find some more info.
I dropped this patch from -next until this is fixed so -next can be pulled.
Thanks for reviewing.
>
> > Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> > ---
> >
> > drivers/mtd/nand/Makefile | 1 +
> > drivers/mtd/nand/pxa3xx_nand.c | 848
> > ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 849
> > insertions(+), 0 deletions(-)
> > create mode 100644 drivers/mtd/nand/pxa3xx_nand.c
> >
> > diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> > index 28f27da..cd840cd 100644
> > --- a/drivers/mtd/nand/Makefile
> > +++ b/drivers/mtd/nand/Makefile
> > @@ -50,6 +50,7 @@ COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o
> >
> > COBJS-$(CONFIG_NAND_SPEAR) += spr_nand.o
> > COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
> > COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
> >
> > +COBJS-$(CONFIG_NAND_PXA3XX) += pxa3xx_nand.o
> >
> > endif
> >
> > COBJS := $(COBJS-y)
> >
> > diff --git a/drivers/mtd/nand/pxa3xx_nand.c
> > b/drivers/mtd/nand/pxa3xx_nand.c new file mode 100644
> > index 0000000..380c918
> > --- /dev/null
> > +++ b/drivers/mtd/nand/pxa3xx_nand.c
> > @@ -0,0 +1,848 @@
> > +/*
> > + * drivers/mtd/nand/pxa3xx_nand.c
> > + *
> > + * Copyright ? 2005 Intel Corporation
> > + * Copyright ? 2006 Marvell International Ltd.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <common.h>
> > +
> > +#if defined(CONFIG_CMD_NAND)
>
> The makefile already limits compilation of this file to when
> CONFIG_NAND_PXA3XX is defined.
>
> > +#ifdef CONFIG_NEW_NAND_CODE
>
> Hmm?
>
> > +#define WAIT_EVENT_TIMEOUT (2 * CONFIG_SYS_HZ/10)
> > +
> > +static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
> > +{
> > + int timeout = WAIT_EVENT_TIMEOUT;
> > + uint32_t ndsr;
> > +
> > + while (timeout--) {
> > + ndsr = NDSR & NDSR_MASK;
> > + if (ndsr & event) {
> > + NDSR = ndsr;
> > + return 0;
> > + }
> > + udelay(10);
> > + }
>
> You're defining WAIT_EVENT_TIMEOUT in terms of CONFIG_SYS_HZ ticks (which
> are supposed to be 1ms, but in any case you should only use CONFIG_SYS_HZ
> when you're interacting with get_ticks() or similar), but you're
> interpreting it as a number of 10us intervals.
>
> > + if (info->col_addr_cycles == 2) {
> > + /* large block, 2 cycles for column address
> > + * row address starts from 3rd cycle
> > + */
> > + info->ndcb1 |= page_addr << 16;
> > + if (info->row_addr_cycles == 3)
> > + info->ndcb2 = (page_addr >> 16) & 0xff;
> > + } else
> > + /* small block, 1 cycles for column address
> > + * row address starts from 2nd cycle
> > + */
> > + info->ndcb1 = page_addr << 8;
>
> If you put braces on one half of the if, please put it on the other half
> (and also when you have a multi-line body even if it's technically only one
> statement).
>
> > +/* calculate delta between OSCR values start and now */
> > +static unsigned long get_delta(unsigned long start)
> > +{
> > + unsigned long cur = OSCR;
> > +
> > + if(cur < start) /* OSCR overflowed */
> > + return (cur + (start^0xffffffff));
> > + else
> > + return (cur - start);
> > +}
>
> What's wrong with get_ticks()?
>
> > +
> > +/* wait_event with timeout */
> > +static unsigned int wait_event(unsigned long event)
> > +{
> > + unsigned long ndsr, timeout, start = OSCR;
> > +
> > + if(!event)
> > + return 0xff000000;
> > +
> > + if(event & (NDSR_CS0_CMDD | NDSR_CS0_BBD))
> > + timeout = CONFIG_SYS_NAND_PROG_ERASE_TO * OSCR_CLK_FREQ;
> > + else
> > + timeout = CONFIG_SYS_NAND_OTHER_TO * OSCR_CLK_FREQ;
> > +
> > + while(1) {
>
> Space after keywords like "if" and "while".
>
> > +static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t
> > event) +{
> > + unsigned int status;
> > +
> > + if (write_cmd(info)) {
> > + info->retcode = ERR_SENDCMD;
> > + goto fail_stop;
> > + }
> > +
> > + info->state = STATE_CMD_HANDLE;
> > +
> > + status = wait_event(event);
> > + if (status & (NDSR_RDDREQ | NDSR_DBERR)) {
> > + if (status & NDSR_DBERR)
> > + info->retcode = ERR_DBERR;
> > +
> > + info->state = STATE_PIO_READING;
> > + } else if (status & NDSR_WRDREQ) {
> > + info->state = STATE_PIO_WRITING;
> > + } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) {
> > + if (status & NDSR_CS0_BBD)
> > + info->retcode = ERR_BBERR;
> > +
> > + info->state = STATE_READY;
> > + }
> > +/* NDSR = status; */
>
> Why commented out?
>
> > +fail_stop:
> > + NDCR &= ~NDCR_ND_RUN;
> > + udelay(10);
> > + return -ETIMEDOUT;
>
> Why is the udelay needed?
>
> > + default:
> > + printk(KERN_ERR "non-supported command.\n");
>
> That's a bit vague -- tell the user this message comes from the NAND
> driver, and what the bad command is.
>
> > +/*
> > + * not required for Monahans DFC
> > + */
> > +static void pxa3xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned
> > int ctrl) +{
> > + return;
> > +}
>
> Just don't provide it at all.
>
> > +static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
> > +{
> > + const struct pxa3xx_nand_flash *f = info->flash_info;
> > + const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
> > + uint8_t id_buff[8];
> > + int i;
> > + unsigned long *long_buf;
> > +
> > + if (prepare_other_cmd(info, cmdset->read_id)) {
> > + printk(KERN_ERR "failed to prepare command\n");
> > + return -EINVAL;
> > + }
> > +
> > + /* Send command */
> > + if (write_cmd(info))
> > + goto fail_timeout;
> > +
> > + /* Wait for CMDDM(command done successfully) */
> > + if (wait_for_event(info, NDSR_RDDREQ))
> > + goto fail_timeout;
> > +
> > + for (i = 0; i < 8; i += 4) {
> > + long_buf = (unsigned long *) &id_buff[i];
> > + *long_buf = NDDB;
> > + }
> > + *id = id_buff[0] | (id_buff[1] << 8);
> > + return 0;
> > +
> > +fail_timeout:
> > + NDCR &= ~NDCR_ND_RUN;
> > + udelay(10);
> > + return -ETIMEDOUT;
> > +}
> > +
>
> Why is this done differently here than when the generic layer issues a
> READID command?
>
> > +static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
> > + const struct pxa3xx_nand_flash *f)
> > +{
> > + uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
> > +
> > + if (f->page_size != 2048 && f->page_size != 512)
> > + return -EINVAL;
> > +
> > + if (f->flash_width != 16 && f->flash_width != 8)
> > + return -EINVAL;
> > +
> > + /* calculate flash information */
> > + info->oob_size = (f->page_size == 2048) ? 64 : 16;
> > + info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
> > +
> > + /* calculate addressing information */
> > + info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
> > +
> > + if (f->num_blocks * f->page_per_block > 65536)
> > + info->row_addr_cycles = 3;
> > + else
> > + info->row_addr_cycles = 2;
>
> This looks duplicative of pxa3xx_nand_detect_config.
>
> > + /* set info fields needed to __readid */
> > + info->flash_info = &default_flash;
> > + info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2;
> > + info->reg_ndcr = ndcr;
> > +
> > + if (__readid(info, &id))
> > + return -ENODEV;
> > +
> > + /* Lookup the flash id */
> > + id = (id >> 8) & 0xff; /* device id is byte 2 */
> > +
> > + for (i = 0; nand_flash_ids[i].name != NULL; i++) {
> > + if (id == nand_flash_ids[i].id) {
> > + type = &nand_flash_ids[i];
> > + break;
> > + }
> > + }
>
> Why do you need to do this here? The generic NAND code will look this up.
>
> > +static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info)
> > +{
> > + uint32_t id = -1;
> > + int i;
> > +
> > + if (pxa3xx_nand_detect_config(info) == 0)
> > + return 0;
> > +
> > + for (i = 0; i < 1; ++i) {
>
> What's this one-iteration loop for?
>
> > + if (pxa3xx_nand_config_flash(info, info->flash_info))
> > + continue;
> > +
> > + if (__readid(info, &id))
> > + continue;
> > +
> > + return 0;
> > + }
> > +
> > + printf("failed to detect configured nand flash; found %04x instead
> > of\n", id);
>
> Instead of what? Did you really "find" anything in this case?
>
> pxa3xx_nand_detect_config already does the __readid, why do you need to do
> it again here? You don't do anything with the id if __readid succeeds.
>
> > +
> > + return -ENODEV;
> > +}
> > +
> > +static struct nand_ecclayout hw_smallpage_ecclayout = {
> > + .eccbytes = 6,
> > + .eccpos = {8, 9, 10, 11, 12, 13 },
> > + .oobfree = { {2, 6} }
> > +};
>
> Normally with small page NAND the bad block marker is at byte 5, at least
> with 8-bit chips.
>
> If you really have bad block information somewhere else, you'll want to
> provide a non-default badblock_pattern.
>
> > +#else
> > +#error "U-Boot legacy NAND support not available for Monahans DFC."
> > +#endif
> > +#endif
>
> Legacy NAND has been removed from u-boot altogether. Please don't
> reintroduce references to it.
>
> -Scott
next prev parent reply other threads:[~2010-07-09 22:24 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-06 1:12 [U-Boot] [PATCH 1/5] Enable PXAFB for PXA27X and PXA3XX Marek Vasut
2010-07-06 1:12 ` [U-Boot] [PATCH 2/5] PXA: Add hardware init helper macros Marek Vasut
2010-07-06 1:12 ` [U-Boot] [PATCH 3/5] PXA: Add PWM2 and PWM3 regs to pxa-regs.h Marek Vasut
2010-07-06 1:12 ` [U-Boot] [PATCH 4/5] PXA: Add OneNAND booting support to start.S Marek Vasut
2010-07-06 1:12 ` [U-Boot] [PATCH 5/5] PXA: PXA3xx NAND Driver Marek Vasut
2010-07-09 20:04 ` Scott Wood
2010-07-09 22:24 ` Marek Vasut [this message]
2010-07-12 15:55 ` Scott Wood
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201007100024.28013.marek.vasut@gmail.com \
--to=marek.vasut@gmail.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.