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.
next parent 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