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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox