From: Boris Brezillon <boris.brezillon@free-electrons.com>
To: Marek Vasut <marex@denx.de>
Cc: Peter Pan <peterpandong@micron.com>,
richard@nod.at, computersforpeace@gmail.com,
arnaud.mouiche@gmail.com, thomas.petazzoni@free-electrons.com,
cyrille.pitchen@atmel.com, linux-mtd@lists.infradead.org,
peterpansjtu@gmail.com, linshunquan1@hisilicon.com
Subject: Re: [PATCH v4 4/9] nand: spi: add basic blocks for infrastructure
Date: Thu, 23 Mar 2017 16:40:00 +0100 [thread overview]
Message-ID: <20170323164000.34288ed9@bbrezillon> (raw)
In-Reply-To: <ac67260f-94ba-7336-5cd4-abc8e9c91cf1@denx.de>
On Thu, 23 Mar 2017 12:29:58 +0100
Marek Vasut <marex@denx.de> wrote:
> > +
> > +/*
> > + * spinand_read_status - get status register value
> > + * @chip: SPI NAND device structure
> > + * @status: buffer to store value
> > + * Description:
> > + * After read, write, or erase, the NAND device is expected to set the
> > + * busy status.
> > + * This function is to allow reading the status of the command: read,
> > + * write, and erase.
> > + */
> > +static int spinand_read_status(struct spinand_device *chip, uint8_t *status)
> > +{
> > + return spinand_read_reg(chip, REG_STATUS, status);
> > +}
> > +
> > +/*
> > + * spinand_wait - wait until the command is done
> > + * @chip: SPI NAND device structure
> > + * @s: buffer to store status register value (can be NULL)
> > + */
> > +static int spinand_wait(struct spinand_device *chip, u8 *s)
> > +{
> > + unsigned long timeo = msecs_to_jiffies(400);
> > + u8 status;
> > +
> > + do {
> > + spinand_read_status(chip, &status);
> > + if ((status & STATUS_OIP_MASK) == STATUS_READY)
> > + goto out;
> > + } while (time_before(jiffies, timeo));
> > +
> > + /*
> > + * Extra read, just in case the STATUS_READY bit has changed
> > + * since our last check
> > + */
>
> Is this likely to happen ? Probably not ... so in case you reach this
> place here, timeout happened.
If the timeout is big enough, no. But it does not hurt to do one last
check.
>
> > + spinand_read_status(chip, &status);
> > +out:
> > + if (s)
> > + *s = status;
> > +
> > + return (status & STATUS_OIP_MASK) == STATUS_READY ? 0 : -ETIMEDOUT;
> > +}
> > +
> > +/*
> > + * spinand_read_id - send 9Fh command to get ID
> > + * @chip: SPI NAND device structure
> > + * @buf: buffer to store id
> > + * Description:
> > + * Manufacturers' read ID method is not unique. Some need a dummy before
> > + * reading, some's ID has three byte.
> > + * This function send one byte opcode (9Fh) and then read
> > + * SPINAND_MAX_ID_LEN (4 currently) bytes. Manufacturer's detect function
> > + * need to filter out real ID from the 4 bytes.
> > + */
> > +static int spinand_read_id(struct spinand_device *chip, u8 *buf)
> > +{
> > + struct spinand_op op;
> > +
> > + spinand_op_init(&op);
> > + op.cmd = SPINAND_CMD_READ_ID;
> > + op.n_rx = SPINAND_MAX_ID_LEN;
> > + op.rx_buf = buf;
> > +
> > + return spinand_exec_op(chip, &op);
> > +}
> > +
> > +/*
> > + * spinand_reset - reset device by FFh command.
> > + * @chip: SPI NAND device structure
> > + */
> > +static int spinand_reset(struct spinand_device *chip)
> > +{
> > + struct spinand_op op;
> > + int ret;
> > +
> > + spinand_op_init(&op);
> > + op.cmd = SPINAND_CMD_RESET;
> > +
> > + ret = spinand_exec_op(chip, &op);
> > + if (ret < 0) {
> > + pr_err("spinand reset failed!\n");
>
> Can we use dev_err() ? Also , previous patch had some pr_fmt which added
> "SPI NAND:" prefix, so replace "spinand" with "SPI NAND: " to be
> consistent ...
The underlying dev is not ready/initialized the first time
spinand_reset() is called.
>
> > + goto out;
> > + }
> > + ret = spinand_wait(chip, NULL);
> > +
> > +out:
> > + return ret;
> > +}
> > +/*
> > + * spinand_manufacturer_detect - detect SPI NAND device by each manufacturer
> > + * @chip: SPI NAND device structure
> > + *
> > + * ->detect() should decode raw id in chip->id.data and initialize device
> > + * related part in spinand_device structure if it is the right device.
> > + * ->detect() can not be NULL.
> > + */
> > +static int spinand_manufacturer_detect(struct spinand_device *chip)
> > +{
> > + int i = 0;
> > +
> > + for (; spinand_manufacturers[i]->id != 0x0; i++) {
> > + if (!spinand_manufacturers[i]->ops ||
> > + !spinand_manufacturers[i]->ops->detect) {
> > + pr_err("%s's ops or ops->detect() is be NULL!\n",
> > + spinand_manufacturers[i]->name);
>
> Can this case happen, EVER ? I'd mandate the ->detect to be always set.
I agree. Let's assume ->detect is always != NULL. Same goes for ->ops
(assuming you use the ARRAY_SIZE() approach I suggested below).
>
> > + return -EINVAL;
> > + }
> > + if (spinand_manufacturers[i]->ops->detect(chip)) {
> > + chip->manufacturer.manu = spinand_manufacturers[i];
> > + return 0;
> > + }
> > + }
> > +
> > + return -ENODEV;
> > +}
[...]
> > +/*
> > + * spinand_alloc - [SPI NAND Interface] allocate SPI NAND device instance
> > + * @dev: pointer to device model structure
> > + */
> > +struct spinand_device *spinand_alloc(struct device *dev)
> > +{
> > + struct spinand_device *chip;
> > + struct spinand_ecc_engine *ecc_engine;
> > +
> > + chip = kzalloc(sizeof(*chip), GFP_KERNEL);
> > + if (!chip)
> > + goto err1;
> > +
> > + ecc_engine = kzalloc(sizeof(*ecc_engine), GFP_KERNEL);
> > + if (!ecc_engine)
> > + goto err2;
>
> Just allocate a structure with both chip and ecc_engine in them, then
> you don't have to kzalloc/kfree twice .
Actually, the ECC engine allocation/initialization should not be done
here. At this point, you don't know yet which ECC engine will be used
(on-die, external engine, software ECC, ...).
Let the real ECC implementation allocate the ecc.engine struct
(and overload it if needed).
>
> > + ecc_engine->mode = SPINAND_ECC_ONDIE;
The engine mode (which is more a type than a mode IMO) should be
stored in chip->ecc.type (or chip->ecc.mode) and be used by the
different components (core, vendor or controller code) to determine who
is supposed to provide the ECC engine.
> > + chip->ecc.engine = ecc_engine;
> > + spinand_set_of_node(chip, dev->of_node);
> > + mutex_init(&chip->lock);
> > +
> > + return chip;
> > +
> > +err2:
> > + kfree(chip);
> > +err1:
> > + return ERR_PTR(-ENOMEM);
> > +}
> > +EXPORT_SYMBOL_GPL(spinand_alloc);
> > +
> > +/*
> > + * spinand_free - [SPI NAND Interface] free SPI NAND device instance
> > + * @chip: SPI NAND device structure
> > + */
> > +void spinand_free(struct spinand_device *chip)
> > +{
> > + kfree(chip->ecc.engine);
> > + kfree(chip);
> > +}
> > +EXPORT_SYMBOL_GPL(spinand_free);
> > +
> > +/*
> > + * spinand_register - [SPI NAND Interface] register SPI NAND device
> > + * @chip: SPI NAND device structure
> > + */
> > +int spinand_register(struct spinand_device *chip)
> > +{
> > + int ret;
> > +
> > + ret = spinand_detect(chip);
> > + if (ret) {
> > + pr_err("Detect SPI NAND failed with error %d.\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = spinand_init(chip);
> > + if (ret)
> > + pr_err("Init SPI NAND failed with error %d.\n", ret);
> > +
> > + return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(spinand_register);
> > +
> > +/*
> > + * spinand_unregister - [SPI NAND Interface] unregister SPI NAND device
> > + * @chip: SPI NAND device structure
> > + */
> > +int spinand_unregister(struct spinand_device *chip)
> > +{
> > + struct nand_device *nand = &chip->base;
> > +
> > + nand_unregister(nand);
> > + spinand_manufacturer_cleanup(chip);
> > + kfree(chip->buf);
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(spinand_unregister);
> > +
> > +MODULE_DESCRIPTION("SPI NAND framework");
> > +MODULE_AUTHOR("Peter Pan<peterpandong@micron.com>");
> > +MODULE_LICENSE("GPL v2");
> > diff --git a/drivers/mtd/nand/spi/manufactures.c b/drivers/mtd/nand/spi/manufactures.c
> > new file mode 100644
> > index 0000000..7e0b42d
> > --- /dev/null
> > +++ b/drivers/mtd/nand/spi/manufactures.c
manufacturers.c, but I don't think I want to keep this file anyway.
> > @@ -0,0 +1,24 @@
> > +/**
> > + *
> > + * Copyright (c) 2009-2017 Micron Technology, Inc.
>
> 2009-2017 ? Wow :)
>
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License
> > + * as published by the Free Software Foundation; either version 2
> > + * of the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/mtd/spinand.h>
> > +
> > +struct spinand_manufacturer spinand_manufacturer_end = {0x0, "Unknown", NULL};
> > +
> > +struct spinand_manufacturer *spinand_manufacturers[] = {
> > + &spinand_manufacturer_end,
>
> Just populate the array directly .
BTW, you don't need this sentinel. Just use ARRAY_SIZE() and put this
table directly in the core.
next prev parent reply other threads:[~2017-03-23 15:40 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-23 9:43 [PATCH v4 0/9] Introduction to SPI NAND framework Peter Pan
2017-03-23 9:43 ` [PATCH v4 1/9] mtd: nand: add oob iterator in nand_for_each_page Peter Pan
2017-03-23 11:13 ` Marek Vasut
2017-03-28 1:35 ` Peter Pan
2017-03-29 19:34 ` Boris Brezillon
2017-03-30 8:01 ` Peter Pan
2017-03-30 8:34 ` Boris Brezillon
2017-03-23 9:43 ` [PATCH v4 2/9] mtd: nand: make sure mtd_oob_ops consistent in bbt Peter Pan
2017-03-29 19:48 ` Boris Brezillon
2017-03-23 9:43 ` [PATCH v4 3/9] mtd: nand: add more helpers in nand.h Peter Pan
2017-03-23 11:19 ` Marek Vasut
2017-03-29 19:57 ` Boris Brezillon
2017-03-30 8:04 ` Peter Pan
2017-03-30 8:40 ` Boris Brezillon
2017-03-23 9:43 ` [PATCH v4 4/9] nand: spi: add basic blocks for infrastructure Peter Pan
2017-03-23 11:29 ` Marek Vasut
2017-03-23 15:40 ` Boris Brezillon [this message]
2017-03-23 16:33 ` Marek Vasut
2017-03-30 12:25 ` Arnaud Mouiche
2017-03-30 12:52 ` Boris Brezillon
2017-03-29 22:28 ` Cyrille Pitchen
2017-03-30 12:38 ` Arnaud Mouiche
2017-03-30 12:51 ` Boris Brezillon
2017-03-23 9:43 ` [PATCH v4 5/9] nand: spi: add basic operations support Peter Pan
2017-03-23 9:43 ` [PATCH v4 6/9] nand: spi: Add bad block support Peter Pan
2017-03-23 9:43 ` [PATCH v4 7/9] nand: spi: add Micron spi nand support Peter Pan
2017-03-30 12:31 ` Arnaud Mouiche
2017-03-30 12:57 ` Boris Brezillon
2017-03-23 9:43 ` [PATCH v4 8/9] nand: spi: Add generic SPI controller support Peter Pan
2017-03-23 11:33 ` Marek Vasut
2017-03-28 1:38 ` Peter Pan
2017-03-29 21:37 ` Cyrille Pitchen
2017-03-30 8:28 ` Peter Pan
2017-03-23 9:43 ` [PATCH v4 9/9] MAINTAINERS: Add SPI NAND entry Peter Pan
2017-03-30 12:17 ` [PATCH v4 0/9] Introduction to SPI NAND framework Arnaud Mouiche
2017-04-10 7:33 ` Peter Pan
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=20170323164000.34288ed9@bbrezillon \
--to=boris.brezillon@free-electrons.com \
--cc=arnaud.mouiche@gmail.com \
--cc=computersforpeace@gmail.com \
--cc=cyrille.pitchen@atmel.com \
--cc=linshunquan1@hisilicon.com \
--cc=linux-mtd@lists.infradead.org \
--cc=marex@denx.de \
--cc=peterpandong@micron.com \
--cc=peterpansjtu@gmail.com \
--cc=richard@nod.at \
--cc=thomas.petazzoni@free-electrons.com \
/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.