Devicetree
 help / color / mirror / Atom feed
From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
To: Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
Cc: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A@public.gmane.org,
	devicetree-discuss list
	<devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Subject: Re: [PATCH v3 1/4] NAND: FSL-UPM: add multi chip support
Date: Wed, 25 Mar 2009 07:32:04 -0600	[thread overview]
Message-ID: <fa686aa40903250632o759921c8n1ae8d17286c1f976@mail.gmail.com> (raw)
In-Reply-To: <fa686aa40903250631w6a0cc8b9p3b2e3c1348e0acee-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Wed, Mar 25, 2009 at 7:31 AM, Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> On Wed, Mar 25, 2009 at 4:08 AM, Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org> wrote:
>> This patch adds support for multi-chip NAND devices to the FSL-UPM
>> driver. This requires support for multiple GPIOs for the RNB pins.
>> The NAND chips are selected through address lines defined by the
>> FDT property "chip-offset".
>>
>> Signed-off-by: Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
>
> Hi Wolfgang,
>
> Can you please send a sample device tree snippit for this and add
> documentation updates to your patch for the extended binding?

Oh, and cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org in your next posting.

g.

>> ---
>>  arch/powerpc/sysdev/fsl_lbc.c |    2 +-
>>  drivers/mtd/nand/fsl_upm.c    |   95 +++++++++++++++++++++++++++++++---------
>>  2 files changed, 74 insertions(+), 23 deletions(-)
>>
>> diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
>> index 0494ee5..dceb8d1 100644
>> --- a/arch/powerpc/sysdev/fsl_lbc.c
>> +++ b/arch/powerpc/sysdev/fsl_lbc.c
>> @@ -150,7 +150,7 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
>>
>>        spin_lock_irqsave(&fsl_lbc_lock, flags);
>>
>> -       out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
>> +       out_be32(&fsl_lbc_regs->mar, mar);
>>
>>        switch (upm->width) {
>>        case 8:
>> diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
>> index 7815a40..9b314ce 100644
>> --- a/drivers/mtd/nand/fsl_upm.c
>> +++ b/drivers/mtd/nand/fsl_upm.c
>> @@ -36,8 +36,11 @@ struct fsl_upm_nand {
>>        uint8_t upm_addr_offset;
>>        uint8_t upm_cmd_offset;
>>        void __iomem *io_base;
>> -       int rnb_gpio;
>> +       int rnb_gpio[NAND_MAX_CHIPS];
>>        int chip_delay;
>> +       uint32_t num_chips;
>> +       uint32_t chip_number;
>> +       uint32_t chip_offset;
>>  };
>>
>>  #define to_fsl_upm_nand(mtd) container_of(mtd, struct fsl_upm_nand, mtd)
>> @@ -46,7 +49,7 @@ static int fun_chip_ready(struct mtd_info *mtd)
>>  {
>>        struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
>>
>> -       if (gpio_get_value(fun->rnb_gpio))
>> +       if (gpio_get_value(fun->rnb_gpio[fun->chip_number]))
>>                return 1;
>>
>>        dev_vdbg(fun->dev, "busy\n");
>> @@ -55,9 +58,9 @@ static int fun_chip_ready(struct mtd_info *mtd)
>>
>>  static void fun_wait_rnb(struct fsl_upm_nand *fun)
>>  {
>> -       int cnt = 1000000;
>>
>> -       if (fun->rnb_gpio >= 0) {
>> +       if (fun->rnb_gpio[fun->chip_number] >= 0) {
>> +               int cnt = 1000000;
>>                while (--cnt && !fun_chip_ready(&fun->mtd))
>>                        cpu_relax();
>>                if (!cnt)
>> @@ -69,7 +72,9 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun)
>>
>>  static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>>  {
>> +       struct nand_chip *chip = mtd->priv;
>>        struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
>> +       u32 mar;
>>
>>        if (!(ctrl & fun->last_ctrl)) {
>>                fsl_upm_end_pattern(&fun->upm);
>> @@ -87,11 +92,30 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>>                        fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
>>        }
>>
>> -       fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd);
>> +       mar = cmd << (32 - fun->upm.width);
>> +       if (fun->chip_offset && fun->chip_number > 0)
>> +               mar |= fun->chip_number * fun->chip_offset;
>> +       fsl_upm_run_pattern(&fun->upm, chip->IO_ADDR_R, mar);
>>
>>        fun_wait_rnb(fun);
>>  }
>>
>> +static void fun_select_chip(struct mtd_info *mtd, int chip_nr)
>> +{
>> +       struct nand_chip *chip = mtd->priv;
>> +       struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
>> +
>> +       if (chip_nr == -1) {
>> +               chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
>> +       } else if (chip_nr >= 0) {
>> +               fun->chip_number = chip_nr;
>> +               chip->IO_ADDR_R = chip->IO_ADDR_W =
>> +                       fun->io_base + chip_nr * fun->chip_offset;
>> +       } else {
>> +               BUG();
>> +       }
>> +}
>> +
>>  static uint8_t fun_read_byte(struct mtd_info *mtd)
>>  {
>>        struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
>> @@ -137,8 +161,10 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
>>        fun->chip.read_buf = fun_read_buf;
>>        fun->chip.write_buf = fun_write_buf;
>>        fun->chip.ecc.mode = NAND_ECC_SOFT;
>> +       if (fun->num_chips > 1)
>> +               fun->chip.select_chip = fun_select_chip;
>>
>> -       if (fun->rnb_gpio >= 0)
>> +       if (fun->rnb_gpio[0] >= 0)
>>                fun->chip.dev_ready = fun_chip_ready;
>>
>>        fun->mtd.priv = &fun->chip;
>> @@ -155,7 +181,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
>>                goto err;
>>        }
>>
>> -       ret = nand_scan(&fun->mtd, 1);
>> +       ret = nand_scan(&fun->mtd, fun->num_chips);
>>        if (ret)
>>                goto err;
>>
>> @@ -187,6 +213,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
>>        const uint32_t *prop;
>>        int ret;
>>        int size;
>> +       int i;
>>
>>        fun = kzalloc(sizeof(*fun), GFP_KERNEL);
>>        if (!fun)
>> @@ -208,7 +235,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
>>        if (!prop || size != sizeof(uint32_t)) {
>>                dev_err(&ofdev->dev, "can't get UPM address offset\n");
>>                ret = -EINVAL;
>> -               goto err2;
>> +               goto err1;
>>        }
>>        fun->upm_addr_offset = *prop;
>>
>> @@ -216,21 +243,36 @@ static int __devinit fun_probe(struct of_device *ofdev,
>>        if (!prop || size != sizeof(uint32_t)) {
>>                dev_err(&ofdev->dev, "can't get UPM command offset\n");
>>                ret = -EINVAL;
>> -               goto err2;
>> +               goto err1;
>>        }
>>        fun->upm_cmd_offset = *prop;
>>
>> -       fun->rnb_gpio = of_get_gpio(ofdev->node, 0);
>> -       if (fun->rnb_gpio >= 0) {
>> -               ret = gpio_request(fun->rnb_gpio, dev_name(&ofdev->dev));
>> -               if (ret) {
>> -                       dev_err(&ofdev->dev, "can't request RNB gpio\n");
>> +       prop = of_get_property(ofdev->node, "num-chips", &size);
>> +       if (prop && size == sizeof(uint32_t)) {
>> +               fun->num_chips = *prop;
>> +               if (fun->num_chips >= NAND_MAX_CHIPS) {
>> +                       dev_err(&ofdev->dev, "too much chips");
>> +                       ret = -EINVAL;
>> +                       goto err1;
>> +               }
>> +       } else {
>> +               fun->num_chips = 1;
>> +       }
>> +
>> +       for (i = 0; i < fun->num_chips; i++) {
>> +               fun->rnb_gpio[i] = of_get_gpio(ofdev->node, i);
>> +               if (fun->rnb_gpio[i] >= 0) {
>> +                       ret = gpio_request(fun->rnb_gpio[i],
>> +                                          dev_name(&ofdev->dev));
>> +                       if (ret) {
>> +                               dev_err(&ofdev->dev, "can't request RNB gpio\n");
>> +                               goto err2;
>> +                       }
>> +                       gpio_direction_input(fun->rnb_gpio[i]);
>> +               } else if (fun->rnb_gpio[i]  == -EINVAL) {
>> +                       dev_err(&ofdev->dev, "specified RNB gpio is invalid\n");
>>                        goto err2;
>>                }
>> -               gpio_direction_input(fun->rnb_gpio);
>> -       } else if (fun->rnb_gpio == -EINVAL) {
>> -               dev_err(&ofdev->dev, "specified RNB gpio is invalid\n");
>> -               goto err2;
>>        }
>>
>>        prop = of_get_property(ofdev->node, "chip-delay", NULL);
>> @@ -239,6 +281,10 @@ static int __devinit fun_probe(struct of_device *ofdev,
>>        else
>>                fun->chip_delay = 50;
>>
>> +       prop = of_get_property(ofdev->node, "chip-offset", &size);
>> +       if (prop && size == sizeof(uint32_t))
>> +               fun->chip_offset = *prop;
>> +
>>        fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start,
>>                                          io_res.end - io_res.start + 1);
>>        if (!fun->io_base) {
>> @@ -257,8 +303,10 @@ static int __devinit fun_probe(struct of_device *ofdev,
>>
>>        return 0;
>>  err2:
>> -       if (fun->rnb_gpio >= 0)
>> -               gpio_free(fun->rnb_gpio);
>> +       for (i = 0; i < fun->num_chips; i++) {
>> +               if (fun->rnb_gpio[i] >= 0)
>> +                       gpio_free(fun->rnb_gpio[i]);
>> +       }
>>  err1:
>>        kfree(fun);
>>
>> @@ -268,12 +316,15 @@ err1:
>>  static int __devexit fun_remove(struct of_device *ofdev)
>>  {
>>        struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
>> +       int i;
>>
>>        nand_release(&fun->mtd);
>>        kfree(fun->mtd.name);
>>
>> -       if (fun->rnb_gpio >= 0)
>> -               gpio_free(fun->rnb_gpio);
>> +        for (i = 0; i < fun->num_chips; i++) {
>> +                if (fun->rnb_gpio[i] >= 0)
>> +                        gpio_free(fun->rnb_gpio[i]);
>> +        }
>>
>>        kfree(fun);
>>
>> --
>> 1.6.0.6
>>
>> _______________________________________________
>> Linuxppc-dev mailing list
>> Linuxppc-dev-mnsaURCQ41sdnm+yROfE0A@public.gmane.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>>
>
>
>
> --
> Grant Likely, B.Sc., P.Eng.
> Secret Lab Technologies Ltd.
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

       reply	other threads:[~2009-03-25 13:32 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1237975701-23201-1-git-send-email-wg@grandegger.com>
     [not found] ` <1237975701-23201-2-git-send-email-wg@grandegger.com>
     [not found]   ` <fa686aa40903250631w6a0cc8b9p3b2e3c1348e0acee@mail.gmail.com>
     [not found]     ` <fa686aa40903250631w6a0cc8b9p3b2e3c1348e0acee-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-03-25 13:32       ` Grant Likely [this message]
2009-03-25 13:43         ` [PATCH v3 1/4] NAND: FSL-UPM: add multi chip support Wolfgang Grandegger
     [not found]           ` <49CA3503.5040006-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
2009-03-25 17:26             ` Grant Likely
     [not found]   ` <1237975701-23201-3-git-send-email-wg@grandegger.com>
     [not found]     ` <1237975701-23201-4-git-send-email-wg@grandegger.com>
2009-03-25 15:11       ` [PATCH v3 3/4] powerpc: NAND: FSL UPM: document new bindings Anton Vorontsov
2009-03-25 17:48       ` Grant Likely
2009-03-25 20:48         ` Wolfgang Grandegger
2009-03-26  5:09           ` Grant Likely
     [not found]             ` <fa686aa40903252209r52a1bc1cn995a7da16bc3527f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-03-26  7:42               ` Wolfgang Grandegger
     [not found]                 ` <49CB31CB.2010704-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
2009-03-26 14:27                   ` Grant Likely
     [not found]                     ` <fa686aa40903260727y3266e394g5e574680fe70bbbf-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-03-26 15:33                       ` Wolfgang Grandegger
     [not found]                         ` <49CBA062.5050000-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
2009-03-26 16:04                           ` Grant Likely
2009-03-26 16:35                             ` Wolfgang Grandegger
2009-03-26 17:02                               ` Grant Likely
2009-03-26 17:33                                 ` Anton Vorontsov
2009-03-26 22:14                                   ` Wolfgang Grandegger
2009-03-26 23:22                                     ` Grant Likely
     [not found]                                       ` <fa686aa40903261622wa2a93f9i98435080c7ab6cea-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-03-26 23:32                                         ` Anton Vorontsov
2009-03-27  8:07                                       ` Wolfgang Grandegger

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=fa686aa40903250632o759921c8n1ae8d17286c1f976@mail.gmail.com \
    --to=grant.likely-s3s/wqlpoipyb63q8fvjnq@public.gmane.org \
    --cc=devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org \
    --cc=linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linuxppc-dev-mnsaURCQ41sdnm+yROfE0A@public.gmane.org \
    --cc=wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox