Add checking size of BCH meta data size in capabilities registers
instead of using fixed value. BCH meta data is used to keep data
from nand flash oob area.
Signed-off-by: Piotr Sroka <[email protected]>
---
.../mtd/nand/raw/cadence-nand-controller.c | 21 ++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
index f6c7102a1e32..5063a8b493a4 100644
--- a/drivers/mtd/nand/raw/cadence-nand-controller.c
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -30,7 +30,6 @@
* Generic mode is used for executing rest of commands.
*/
-#define MAX_OOB_SIZE_PER_SECTOR 32
#define MAX_ADDRESS_CYC 6
#define MAX_ERASE_ADDRESS_CYC 3
#define MAX_DATA_SIZE 0xFFFC
@@ -190,6 +189,7 @@
/* BCH Engine identification register 3. */
#define BCH_CFG_3 0x844
+#define BCH_CFG_3_METADATA_SIZE GENMASK(23, 16)
/* Ready/Busy# line status. */
#define RBN_SETINGS 0x1004
@@ -499,6 +499,7 @@ struct cdns_nand_ctrl {
unsigned long assigned_cs;
struct list_head chips;
+ u8 bch_metadata_size;
};
struct cdns_nand_chip {
@@ -1077,6 +1078,14 @@ static int cadence_nand_read_bch_caps(struct cdns_nand_ctrl *cdns_ctrl)
int max_step_size = 0, nstrengths, i;
u32 reg;
+ reg = readl_relaxed(cdns_ctrl->reg + BCH_CFG_3);
+ cdns_ctrl->bch_metadata_size = FIELD_GET(BCH_CFG_3_METADATA_SIZE, reg);
+ if (cdns_ctrl->bch_metadata_size < 4) {
+ dev_err(cdns_ctrl->dev,
+ "Driver needs at least 4 bytes of BCH meta data\n");
+ return -EIO;
+ }
+
reg = readl_relaxed(cdns_ctrl->reg + BCH_CFG_0);
cdns_ctrl->ecc_strengths[0] = FIELD_GET(BCH_CFG_0_CORR_CAP_0, reg);
cdns_ctrl->ecc_strengths[1] = FIELD_GET(BCH_CFG_0_CORR_CAP_1, reg);
@@ -1170,7 +1179,8 @@ static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl)
writel_relaxed(0xFFFFFFFF, cdns_ctrl->reg + INTR_STATUS);
cadence_nand_get_caps(cdns_ctrl);
- cadence_nand_read_bch_caps(cdns_ctrl);
+ if (cadence_nand_read_bch_caps(cdns_ctrl))
+ return -EIO;
/*
* Set IO width access to 8.
@@ -2587,7 +2597,6 @@ int cadence_nand_attach_chip(struct nand_chip *chip)
struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip);
u32 ecc_size = cdns_chip->sector_count * chip->ecc.bytes;
struct mtd_info *mtd = nand_to_mtd(chip);
- u32 max_oob_data_size;
int ret;
if (chip->options & NAND_BUSWIDTH_16) {
@@ -2628,10 +2637,8 @@ int cadence_nand_attach_chip(struct nand_chip *chip)
cdns_chip->avail_oob_size = mtd->oobsize - ecc_size;
- max_oob_data_size = MAX_OOB_SIZE_PER_SECTOR;
-
- if (cdns_chip->avail_oob_size > max_oob_data_size)
- cdns_chip->avail_oob_size = max_oob_data_size;
+ if (cdns_chip->avail_oob_size > cdns_ctrl->bch_metadata_size)
+ cdns_chip->avail_oob_size = cdns_ctrl->bch_metadata_size;
if ((cdns_chip->avail_oob_size + cdns_chip->bbm_len + ecc_size)
> mtd->oobsize)
--
2.17.1
Reinitilaize complete object before executing CDMA command to make sure
that done flag is ok.
Signed-off-by: Piotr Sroka <[email protected]>
---
drivers/mtd/nand/raw/cadence-nand-controller.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
index 5c1bbb05ab51..efddc5c68afb 100644
--- a/drivers/mtd/nand/raw/cadence-nand-controller.c
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -998,6 +998,7 @@ static int cadence_nand_cdma_send(struct cdns_nand_ctrl *cdns_ctrl,
return status;
cadence_nand_reset_irq(cdns_ctrl);
+ reinit_completion(&cdns_ctrl->complete);
writel_relaxed((u32)cdns_ctrl->dma_cdma_desc,
cdns_ctrl->reg + CMD_REG2);
--
2.17.1
Increase bad block marker size from one byte to two bytes.
Bad block marker is handled by skip bytes feature of HPNFC.
Controller excpects this value to be an even number.
Signed-off-by: Piotr Sroka <[email protected]>
---
drivers/mtd/nand/raw/cadence-nand-controller.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
index 2ebfd0934739..5c1bbb05ab51 100644
--- a/drivers/mtd/nand/raw/cadence-nand-controller.c
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -2612,12 +2612,9 @@ int cadence_nand_attach_chip(struct nand_chip *chip)
chip->options |= NAND_NO_SUBPAGE_WRITE;
cdns_chip->bbm_offs = chip->badblockpos;
- if (chip->options & NAND_BUSWIDTH_16) {
- cdns_chip->bbm_offs &= ~0x01;
- cdns_chip->bbm_len = 2;
- } else {
- cdns_chip->bbm_len = 1;
- }
+ cdns_chip->bbm_offs &= ~0x01;
+ /* this value should be even number */
+ cdns_chip->bbm_len = 2;
ret = nand_ecc_choose_conf(chip,
&cdns_ctrl->ecc_caps,
--
2.17.1
Previously ecc_sector size was used for calculation but its value
was not yet known.
Signed-off-by: Piotr Sroka <[email protected]>
---
drivers/mtd/nand/raw/cadence-nand-controller.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
index 5063a8b493a4..2ebfd0934739 100644
--- a/drivers/mtd/nand/raw/cadence-nand-controller.c
+++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
@@ -2595,7 +2595,7 @@ int cadence_nand_attach_chip(struct nand_chip *chip)
{
struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller);
struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip);
- u32 ecc_size = cdns_chip->sector_count * chip->ecc.bytes;
+ u32 ecc_size;
struct mtd_info *mtd = nand_to_mtd(chip);
int ret;
@@ -2634,6 +2634,7 @@ int cadence_nand_attach_chip(struct nand_chip *chip)
/* Error correction configuration. */
cdns_chip->sector_size = chip->ecc.size;
cdns_chip->sector_count = mtd->writesize / cdns_chip->sector_size;
+ ecc_size = cdns_chip->sector_count * chip->ecc.bytes;
cdns_chip->avail_oob_size = mtd->oobsize - ecc_size;
--
2.17.1
Hi Piotr,
Piotr Sroka <[email protected]> wrote on Mon, 10 Feb 2020 10:55:26
+0100:
There is a typo in the title (available).
> Previously ecc_sector size was used for calculation but its value
> was not yet known.
Can we rework a little bit this? What about:
The value of cdns_chip->sector_count is not known at the moment
of the derivation of ecc_size, leading to a zero value. Fix
this by assigning ecc_size later in the code.
Also, I think it deserves a Fixes/Cc:stable tag!
>
> Signed-off-by: Piotr Sroka <[email protected]>
> ---
> drivers/mtd/nand/raw/cadence-nand-controller.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
> index 5063a8b493a4..2ebfd0934739 100644
> --- a/drivers/mtd/nand/raw/cadence-nand-controller.c
> +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
> @@ -2595,7 +2595,7 @@ int cadence_nand_attach_chip(struct nand_chip *chip)
> {
> struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller);
> struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip);
> - u32 ecc_size = cdns_chip->sector_count * chip->ecc.bytes;
> + u32 ecc_size;
> struct mtd_info *mtd = nand_to_mtd(chip);
> int ret;
>
> @@ -2634,6 +2634,7 @@ int cadence_nand_attach_chip(struct nand_chip *chip)
> /* Error correction configuration. */
> cdns_chip->sector_size = chip->ecc.size;
> cdns_chip->sector_count = mtd->writesize / cdns_chip->sector_size;
> + ecc_size = cdns_chip->sector_count * chip->ecc.bytes;
>
> cdns_chip->avail_oob_size = mtd->oobsize - ecc_size;
>
Thanks,
Miquèl
Hi Piotr,
Piotr Sroka <[email protected]> wrote on Mon, 10 Feb 2020 10:55:27
+0100:
> Increase bad block marker size from one byte to two bytes.
> Bad block marker is handled by skip bytes feature of HPNFC.
> Controller excpects this value to be an even number.
expects
Do we break existing users with this change? Do you know how the
controller behaved until now?
Also needs a Fixes/stable tag I guess?
>
> Signed-off-by: Piotr Sroka <[email protected]>
> ---
> drivers/mtd/nand/raw/cadence-nand-controller.c | 9 +++------
> 1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
> index 2ebfd0934739..5c1bbb05ab51 100644
> --- a/drivers/mtd/nand/raw/cadence-nand-controller.c
> +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
> @@ -2612,12 +2612,9 @@ int cadence_nand_attach_chip(struct nand_chip *chip)
> chip->options |= NAND_NO_SUBPAGE_WRITE;
>
> cdns_chip->bbm_offs = chip->badblockpos;
> - if (chip->options & NAND_BUSWIDTH_16) {
> - cdns_chip->bbm_offs &= ~0x01;
> - cdns_chip->bbm_len = 2;
> - } else {
> - cdns_chip->bbm_len = 1;
> - }
> + cdns_chip->bbm_offs &= ~0x01;
> + /* this value should be even number */
> + cdns_chip->bbm_len = 2;
>
> ret = nand_ecc_choose_conf(chip,
> &cdns_ctrl->ecc_caps,
Thanks,
Miquèl
Hi Piotr,
Piotr Sroka <[email protected]> wrote on Mon, 10 Feb 2020 10:55:28
+0100:
> Reinitilaize complete object before executing CDMA command to make sure
> that done flag is ok.
Looks fine, besides the need for Fixes/Stable tags, what do you think?
>
> Signed-off-by: Piotr Sroka <[email protected]>
> ---
> drivers/mtd/nand/raw/cadence-nand-controller.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c
> index 5c1bbb05ab51..efddc5c68afb 100644
> --- a/drivers/mtd/nand/raw/cadence-nand-controller.c
> +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c
> @@ -998,6 +998,7 @@ static int cadence_nand_cdma_send(struct cdns_nand_ctrl *cdns_ctrl,
> return status;
>
> cadence_nand_reset_irq(cdns_ctrl);
> + reinit_completion(&cdns_ctrl->complete);
>
> writel_relaxed((u32)cdns_ctrl->dma_cdma_desc,
> cdns_ctrl->reg + CMD_REG2);
Thanks,
Miquèl
On Mon, 2020-02-10 at 09:55:28 UTC, Piotr Sroka wrote:
> Reinitilaize complete object before executing CDMA command to make sure
> that done flag is ok.
>
> Signed-off-by: Piotr Sroka <[email protected]>
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.
Miquel
On Mon, 2020-02-10 at 09:55:27 UTC, Piotr Sroka wrote:
> Increase bad block marker size from one byte to two bytes.
> Bad block marker is handled by skip bytes feature of HPNFC.
> Controller excpects this value to be an even number.
>
> Signed-off-by: Piotr Sroka <[email protected]>
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.
Miquel
On Mon, 2020-02-10 at 09:55:26 UTC, Piotr Sroka wrote:
> Previously ecc_sector size was used for calculation but its value
> was not yet known.
>
> Signed-off-by: Piotr Sroka <[email protected]>
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.
Miquel
On Mon, 2020-02-10 at 09:55:25 UTC, Piotr Sroka wrote:
> Add checking size of BCH meta data size in capabilities registers
> instead of using fixed value. BCH meta data is used to keep data
> from nand flash oob area.
>
> Signed-off-by: Piotr Sroka <[email protected]>
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.
Miquel
Hi Piotr,
Miquel Raynal <[email protected]> wrote on Tue, 10 Mar 2020
19:29:51 +0100:
> On Mon, 2020-02-10 at 09:55:26 UTC, Piotr Sroka wrote:
> > Previously ecc_sector size was used for calculation but its value
> > was not yet known.
> >
> > Signed-off-by: Piotr Sroka <[email protected]>
>
> Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.
>
I applied patch 2, 3 and 4 after having changed the commit message as
suggested and with the Fixes/Cc: stable tags added.
Thanks,
Miquèl