From: Boris Brezillon <boris.brezillon@free-electrons.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [RFC 04/11] mtd/nand: add page status table (pst)
Date: Sun, 14 Jun 2015 13:52:02 +0200 [thread overview]
Message-ID: <20150614135202.30a2fd23@bbrezillon> (raw)
In-Reply-To: <1433505164-24112-5-git-send-email-r.spliet@ultimaker.com>
On Fri, 5 Jun 2015 13:52:37 +0200
Roy Spliet <r.spliet@ultimaker.com> wrote:
Ditto (this work hasn't been accepted in Linux).
> From: yassin <yassinjaffer@gmail.com>
>
> Signed-off-by: Roy Spliet <r.spliet@ultimaker.com>
> ---
> drivers/mtd/nand/nand_base.c | 154 +++++++++++++++++++++++++++++++++++++++++++
> include/linux/mtd/nand.h | 21 ++++++
> 2 files changed, 175 insertions(+)
>
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index dbeb092..1c514a0 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -1185,6 +1185,138 @@ EXPORT_SYMBOL(nand_lock);
> #endif
>
> /**
> + * nand_page_is_empty - check wether a NAND page contains only FFs
> + * @mtd: mtd info
> + * @data: data buffer
> + * @oob: oob buffer
> + *
> + * Reads the data stored in the databuf buffer and check if it contains only
> + * FFs.
> + *
> + * Return true if it does else return false.
> + */
> +bool nand_page_is_empty(struct mtd_info *mtd, void *data, void *oob)
> +{
> + u8 *buf;
> + int length;
> + u32 pattern = 0xffffffff;
> + int bitflips = 0;
> + int cnt;
> +
> + buf = data;
> + length = mtd->writesize;
> + while (length) {
> + cnt = length < sizeof(pattern) ? length : sizeof(pattern);
> + if (memcmp(&pattern, buf, cnt)) {
> + int i;
> + for (i = 0; i < cnt * 8; i++) {
> + if (!(buf[i / 8] &
> + (1 << (i % 8)))) {
> + bitflips++;
> + if (bitflips > mtd->ecc_strength)
> + return false;
> + }
> + }
> + }
> +
> + buf += sizeof(pattern);
> + length -= sizeof(pattern);
> + }
> +
> + buf = oob;
> + length = mtd->oobsize;
> + while (length) {
> + cnt = length < sizeof(pattern) ? length : sizeof(pattern);
> + if (memcmp(&pattern, buf, cnt)) {
> + int i;
> + for (i = 0; i < cnt * 8; i++) {
> + if (!(buf[i / 8] &
> + (1 << (i % 8)))) {
> + bitflips++;
> + if (bitflips > mtd->ecc_strength)
> + return false;
> + }
> + }
> + }
> +
> + buf += sizeof(pattern);
> + length -= sizeof(pattern);
> + }
> +
> + return true;
> +}
> +EXPORT_SYMBOL(nand_page_is_empty);
> +
> +/**
> + * nand_page_get_status - retrieve page status from the page status table (pst)
> + * @mtd: mtd info
> + * @page: page you want to get status on
> + *
> + * Return the page status.
> + */
> +int nand_page_get_status(struct mtd_info *mtd, int page)
> +{
> + struct nand_chip *chip = mtd->priv;
> + u8 shift = (page % 4) * 2;
> + uint64_t offset = page / 4;
> + int ret = NAND_PAGE_STATUS_UNKNOWN;
> +
> + if (chip->pst)
> + ret = (chip->pst[offset] >> shift) & 0x3;
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(nand_page_get_status);
> +
> +/**
> + * nand_page_set_status - assign page status from in the page status table
> + * @mtd: mtd info
> + * @page: page you want to get status on
> + * @status: new status to assign
> + */
> +void nand_page_set_status(struct mtd_info *mtd, int page,
> + enum nand_page_status status)
> +{
> + struct nand_chip *chip = mtd->priv;
> + u8 shift;
> + uint64_t offset;
> +
> + if (!chip->pst)
> + return;
> +
> + shift = (page % 4) * 2;
> + offset = page / 4;
> + chip->pst[offset] &= ~(0x3 << shift);
> + chip->pst[offset] |= (status & 0x3) << shift;
> +}
> +EXPORT_SYMBOL(nand_page_set_status);
> +
> +/**
> + * nand_pst_create - create a page status table
> + * @mtd: mtd info
> + *
> + * Allocate a page status table and assign it to the mtd device.
> + *
> + * Returns 0 in case of success or -ERRNO in case of error.
> + */
> +int nand_pst_create(struct mtd_info *mtd)
> +{
> + struct nand_chip *chip = mtd->priv;
> +
> + if (chip->pst)
> + return 0;
> +
> + chip->pst = kzalloc(mtd->size >>
> + (chip->page_shift + mtd->subpage_sft + 2),
> + GFP_KERNEL);
> + if (!chip->pst)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(nand_pst_create);
> +
> +/**
> * nand_read_page_raw - [INTERN] read raw page data without ecc
> * @mtd: mtd info structure
> * @chip: nand chip info structure
> @@ -2521,6 +2653,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
> int bytes = mtd->writesize;
> int cached = writelen > bytes && page != blockmask;
> uint8_t *wbuf = buf;
> + int subpage;
>
> WATCHDOG_RESET();
> /* Partial page write? */
> @@ -2547,6 +2680,14 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
> if (ret)
> break;
>
> + for (subpage = column / chip->subpagesize;
> + subpage < (column + writelen) / chip->subpagesize;
> + subpage++)
> + nand_page_set_status(mtd,
> + (page << mtd->subpage_sft) +
> + subpage,
> + NAND_PAGE_FILLED);
> +
> writelen -= bytes;
> if (!writelen)
> break;
> @@ -2804,6 +2945,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
> int page, status, pages_per_block, ret, chipnr;
> struct nand_chip *chip = mtd->priv;
> loff_t len;
> + int i;
>
> pr_debug("%s: start = 0x%012llx, len = %llu\n",
> __func__, (unsigned long long)instr->addr,
> @@ -2880,6 +3022,18 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
> goto erase_exit;
> }
>
> + for (i = 0; i < pages_per_block; i++) {
> + int subpage;
> + for (subpage = 0;
> + subpage < 1 << mtd->subpage_sft;
> + subpage++) {
> + nand_page_set_status(mtd,
> + ((page + i) << mtd->subpage_sft) +
> + subpage,
> + NAND_PAGE_EMPTY);
> + }
> + }
> +
> /* Increment page address and decrement length */
> len -= (1ULL << chip->phys_erase_shift);
> page += pages_per_block;
> diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> index 0cdb3b9..ef6a783 100644
> --- a/include/linux/mtd/nand.h
> +++ b/include/linux/mtd/nand.h
> @@ -547,6 +547,24 @@ struct nand_ecc_ctrl {
> int page);
> };
>
> +/*
> + * Constants for page status
> + */
> +enum nand_page_status {
> + NAND_PAGE_STATUS_UNKNOWN,
> + NAND_PAGE_EMPTY,
> + NAND_PAGE_FILLED,
> +};
> +
> +bool nand_page_is_empty(struct mtd_info *mtd, void *data, void *oob);
> +
> +int nand_page_get_status(struct mtd_info *mtd, int page);
> +
> +void nand_page_set_status(struct mtd_info *mtd, int page,
> + enum nand_page_status status);
> +
> +int nand_pst_create(struct mtd_info *mtd);
> +
> /**
> * struct nand_buffers - buffer structure for read/write
> * @ecccalc: buffer pointer for calculated ECC, size is oobsize.
> @@ -660,6 +678,7 @@ struct nand_buffers {
> * @bbt_md: [REPLACEABLE] bad block table mirror descriptor
> * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial
> * bad block scan.
> + * @pst: [INTERN] page status table
> * @controller: [REPLACEABLE] a pointer to a hardware controller
> * structure which is shared among multiple independent
> * devices.
> @@ -750,6 +769,8 @@ struct nand_chip {
>
> struct nand_bbt_descr *badblock_pattern;
>
> + uint8_t *pst;
> +
> void *priv;
> };
>
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
next prev parent reply other threads:[~2015-06-14 11:52 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-05 11:52 [U-Boot] [RFC] Sunxi NAND support for U-Boot Roy Spliet
2015-06-05 11:52 ` [U-Boot] [RFC 01/11] mtd/nand: define struct nand_timings Roy Spliet
2015-06-05 11:52 ` [U-Boot] [RFC 02/11] mtd/nand: add ONFI timing mode to nand_timings converter Roy Spliet
2015-06-05 22:02 ` Scott Wood
2015-06-08 8:11 ` Roy Spliet
2015-06-08 8:34 ` [U-Boot] [linux-sunxi] " Michal Suchanek
2015-06-08 8:41 ` Roy Spliet
2015-06-14 11:59 ` Boris Brezillon
2015-06-08 20:24 ` [U-Boot] " Scott Wood
2015-06-10 8:33 ` Hans de Goede
2015-06-10 19:06 ` Scott Wood
2015-06-05 11:52 ` [U-Boot] [RFC 03/11] mtd/nand: support ONFI timing mode retrieval for non-ONFI Roy Spliet
2015-06-14 11:53 ` Boris Brezillon
2015-06-05 11:52 ` [U-Boot] [RFC 04/11] mtd/nand: add page status table (pst) Roy Spliet
2015-06-14 11:52 ` Boris Brezillon [this message]
2015-06-05 11:52 ` [U-Boot] [RFC 05/11] mtd/nand: take nand_ecc_ctrl initialization out of nand_scan_tail Roy Spliet
2015-06-14 11:50 ` Boris Brezillon
2015-06-05 11:52 ` [U-Boot] [RFC 06/11] mtd/nand: Add randomisation layer Roy Spliet
2015-06-14 11:47 ` Boris Brezillon
2015-06-05 11:52 ` [U-Boot] [RFC 07/11] mtd/nand Add Sunxi NAND driver Roy Spliet
2015-06-14 11:42 ` Boris Brezillon
2015-06-14 11:45 ` Boris Brezillon
2015-06-05 11:52 ` [U-Boot] [RFC 08/11] mtd/nand: Add DT definitions for Olimex Lime Roy Spliet
2015-06-14 11:39 ` Boris Brezillon
2015-06-05 11:52 ` [U-Boot] [RFC 09/11] sunxi/nand: Enable UBI and NAND commands Roy Spliet
2015-06-06 15:13 ` Hans de Goede
2015-06-06 15:36 ` Ian Campbell
2015-06-08 7:38 ` Roy Spliet
2015-06-08 9:12 ` Ian Campbell
2015-06-05 11:52 ` [U-Boot] [RFC 10/11] mtd/nand: Define bootcmd for nand Roy Spliet
2015-06-05 11:52 ` [U-Boot] [RFC 11/11] mtd/nand: Sunxi NAND boot partition definitions Roy Spliet
2015-06-07 16:48 ` [U-Boot] [linux-sunxi] " Michal Suchanek
2015-06-08 8:38 ` Roy Spliet
2015-06-08 8:54 ` Michal Suchanek
2015-06-08 9:11 ` Roy Spliet
2015-06-08 10:48 ` Yassin
2015-06-08 11:35 ` Roy Spliet
2015-06-14 11:31 ` Boris Brezillon
2015-06-15 8:00 ` Hans de Goede
2015-06-08 13:16 ` Hans de Goede
2015-06-08 13:56 ` Roy Spliet
2015-06-14 11:25 ` Boris Brezillon
2015-06-14 11:56 ` Michal Suchanek
2015-06-14 12:18 ` Boris Brezillon
2015-06-14 17:42 ` Michal Suchanek
2015-06-14 19:07 ` Boris Brezillon
2015-06-06 15:09 ` [U-Boot] [RFC] Sunxi NAND support for U-Boot Hans de Goede
2015-06-06 15:11 ` Hans de Goede
2015-06-14 11:13 ` Boris Brezillon
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=20150614135202.30a2fd23@bbrezillon \
--to=boris.brezillon@free-electrons.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.