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