* [PATCH v2] mtd: brcmnand: Add v7.2 controller support
@ 2016-05-31 17:23 Florian Fainelli
2016-06-02 17:13 ` Boris Brezillon
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Florian Fainelli @ 2016-05-31 17:23 UTC (permalink / raw)
To: linux-mtd
Cc: thomas.petazzoni, Florian Fainelli, Rob Herring, Pawel Moll,
Mark Rutland, Ian Campbell, Kumar Gala, Brian Norris, Kamal Dasu,
Boris Brezillon, Richard Weinberger, David Woodhouse,
Simon Arlott,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list, open list:BROADCOM STB NAND FLASH DRIVER
The 7.2 controller differs in a few area compared to its predecssor (7.1):
- NAND scrambler, which we are not using just yet
- higher ECC levels (up to 120 bits) per 1KB data blocks, also not supported yet
- up to 128B OOB
This patchs adds the ncessary code to support such a controller
generation and updates the Device Tree binding.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
Changes in v2:
- fixed a bunch of conditionals on the versions which should
have been exclusive (spotted by Thomas)
.../devicetree/bindings/mtd/brcm,brcmnand.txt | 1 +
drivers/mtd/nand/brcmnand/brcmnand.c | 91 ++++++++++++++++++----
2 files changed, 78 insertions(+), 14 deletions(-)
diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
index deb24cbdda82..c8d71e75cb09 100644
--- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
+++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
@@ -27,6 +27,7 @@ Required properties:
brcm,brcmnand-v6.2
brcm,brcmnand-v7.0
brcm,brcmnand-v7.1
+ brcm,brcmnand-v7.2
brcm,brcmnand
- reg : the register start and length for NAND register region.
(optional) Flash DMA register range (if present)
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index b76ad7c0144f..0a54a0f5a4b1 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -340,6 +340,36 @@ static const u16 brcmnand_regs_v71[] = {
[BRCMNAND_FC_BASE] = 0x400,
};
+/* BRCMNAND v7.2 */
+static const u16 brcmnand_regs_v72[] = {
+ [BRCMNAND_CMD_START] = 0x04,
+ [BRCMNAND_CMD_EXT_ADDRESS] = 0x08,
+ [BRCMNAND_CMD_ADDRESS] = 0x0c,
+ [BRCMNAND_INTFC_STATUS] = 0x14,
+ [BRCMNAND_CS_SELECT] = 0x18,
+ [BRCMNAND_CS_XOR] = 0x1c,
+ [BRCMNAND_LL_OP] = 0x20,
+ [BRCMNAND_CS0_BASE] = 0x50,
+ [BRCMNAND_CS1_BASE] = 0,
+ [BRCMNAND_CORR_THRESHOLD] = 0xdc,
+ [BRCMNAND_CORR_THRESHOLD_EXT] = 0xe0,
+ [BRCMNAND_UNCORR_COUNT] = 0xfc,
+ [BRCMNAND_CORR_COUNT] = 0x100,
+ [BRCMNAND_CORR_EXT_ADDR] = 0x10c,
+ [BRCMNAND_CORR_ADDR] = 0x110,
+ [BRCMNAND_UNCORR_EXT_ADDR] = 0x114,
+ [BRCMNAND_UNCORR_ADDR] = 0x118,
+ [BRCMNAND_SEMAPHORE] = 0x150,
+ [BRCMNAND_ID] = 0x194,
+ [BRCMNAND_ID_EXT] = 0x198,
+ [BRCMNAND_LL_RDATA] = 0x19c,
+ [BRCMNAND_OOB_READ_BASE] = 0x200,
+ [BRCMNAND_OOB_READ_10_BASE] = 0,
+ [BRCMNAND_OOB_WRITE_BASE] = 0x400,
+ [BRCMNAND_OOB_WRITE_10_BASE] = 0,
+ [BRCMNAND_FC_BASE] = 0x600,
+};
+
enum brcmnand_cs_reg {
BRCMNAND_CS_CFG_EXT = 0,
BRCMNAND_CS_CFG,
@@ -435,7 +465,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
}
/* Register offsets */
- if (ctrl->nand_version >= 0x0701)
+ if (ctrl->nand_version >= 0x0702)
+ ctrl->reg_offsets = brcmnand_regs_v72;
+ else if (ctrl->nand_version >= 0x0701)
ctrl->reg_offsets = brcmnand_regs_v71;
else if (ctrl->nand_version >= 0x0600)
ctrl->reg_offsets = brcmnand_regs_v60;
@@ -480,7 +512,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
}
/* Maximum spare area sector size (per 512B) */
- if (ctrl->nand_version >= 0x0600)
+ if (ctrl->nand_version >= 0x0702)
+ ctrl->max_oob = 128;
+ else if (ctrl->nand_version >= 0x0600)
ctrl->max_oob = 64;
else if (ctrl->nand_version >= 0x0500)
ctrl->max_oob = 32;
@@ -583,14 +617,20 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val)
enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD;
int cs = host->cs;
- if (ctrl->nand_version >= 0x0600)
+ if (ctrl->nand_version >= 0x0702)
+ bits = 7;
+ else if (ctrl->nand_version >= 0x0600)
bits = 6;
else if (ctrl->nand_version >= 0x0500)
bits = 5;
else
bits = 4;
- if (ctrl->nand_version >= 0x0600) {
+ if (ctrl->nand_version >= 0x0702) {
+ if (cs >= 4)
+ reg = BRCMNAND_CORR_THRESHOLD_EXT;
+ shift = (cs % 4) * bits;
+ } else if (ctrl->nand_version >= 0x0600) {
if (cs >= 5)
reg = BRCMNAND_CORR_THRESHOLD_EXT;
shift = (cs % 5) * bits;
@@ -631,19 +671,28 @@ enum {
static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
{
- if (ctrl->nand_version >= 0x0600)
+ if (ctrl->nand_version >= 0x0702)
+ return GENMASK(7, 0);
+ else if (ctrl->nand_version >= 0x0600)
return GENMASK(6, 0);
else
return GENMASK(5, 0);
}
#define NAND_ACC_CONTROL_ECC_SHIFT 16
+#define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13
static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl)
{
u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f;
- return mask << NAND_ACC_CONTROL_ECC_SHIFT;
+ mask <<= NAND_ACC_CONTROL_ECC_SHIFT;
+
+ /* v7.2 includes additional ECC levels */
+ if (ctrl->nand_version >= 0x0702)
+ mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT;
+
+ return mask;
}
static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
@@ -667,7 +716,9 @@ static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
static inline int brcmnand_sector_1k_shift(struct brcmnand_controller *ctrl)
{
- if (ctrl->nand_version >= 0x0600)
+ if (ctrl->nand_version >= 0x0702)
+ return 9;
+ else if (ctrl->nand_version >= 0x0600)
return 7;
else if (ctrl->nand_version >= 0x0500)
return 6;
@@ -773,10 +824,16 @@ enum brcmnand_llop_type {
* Internal support functions
***********************************************************************/
-static inline bool is_hamming_ecc(struct brcmnand_cfg *cfg)
+static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl,
+ struct brcmnand_cfg *cfg)
{
- return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 &&
- cfg->ecc_level == 15;
+ if (ctrl->nand_version <= 0x0701)
+ return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 &&
+ cfg->ecc_level == 15;
+ else
+ return cfg->sector_size_1k == 0 && ((cfg->spare_area_size == 16 &&
+ cfg->ecc_level == 15) ||
+ (cfg->spare_area_size == 28 && cfg->ecc_level == 16));
}
/*
@@ -931,7 +988,7 @@ static int brcmstb_choose_ecc_layout(struct brcmnand_host *host)
if (p->sector_size_1k)
ecc_level <<= 1;
- if (is_hamming_ecc(p)) {
+ if (is_hamming_ecc(host->ctrl, p)) {
ecc->bytes = 3 * sectors;
mtd_set_ooblayout(mtd, &brcmnand_hamming_ooblayout_ops);
return 0;
@@ -1857,7 +1914,8 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
return 0;
}
-static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg)
+static void brcmnand_print_cfg(struct brcmnand_host *host,
+ char *buf, struct brcmnand_cfg *cfg)
{
buf += sprintf(buf,
"%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit",
@@ -1868,7 +1926,7 @@ static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg)
cfg->spare_area_size, cfg->device_width);
/* Account for Hamming ECC and for BCH 512B vs 1KiB sectors */
- if (is_hamming_ecc(cfg))
+ if (is_hamming_ecc(host->ctrl, cfg))
sprintf(buf, ", Hamming ECC");
else if (cfg->sector_size_1k)
sprintf(buf, ", BCH-%u (1KiB sector)", cfg->ecc_level << 1);
@@ -1987,7 +2045,7 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
brcmnand_set_ecc_enabled(host, 1);
- brcmnand_print_cfg(msg, cfg);
+ brcmnand_print_cfg(host, msg, cfg);
dev_info(ctrl->dev, "detected %s\n", msg);
/* Configure ACC_CONTROL */
@@ -1995,6 +2053,10 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
tmp = nand_readreg(ctrl, offs);
tmp &= ~ACC_CONTROL_PARTIAL_PAGE;
tmp &= ~ACC_CONTROL_RD_ERASED;
+
+ /* We need to turn on Read from erased paged protected by ECC */
+ if (ctrl->nand_version >= 0x0702)
+ tmp |= ACC_CONTROL_RD_ERASED;
tmp &= ~ACC_CONTROL_FAST_PGM_RDIN;
if (ctrl->features & BRCMNAND_HAS_PREFETCH) {
/*
@@ -2195,6 +2257,7 @@ static const struct of_device_id brcmnand_of_match[] = {
{ .compatible = "brcm,brcmnand-v6.2" },
{ .compatible = "brcm,brcmnand-v7.0" },
{ .compatible = "brcm,brcmnand-v7.1" },
+ { .compatible = "brcm,brcmnand-v7.2" },
{},
};
MODULE_DEVICE_TABLE(of, brcmnand_of_match);
--
2.7.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] mtd: brcmnand: Add v7.2 controller support
2016-05-31 17:23 [PATCH v2] mtd: brcmnand: Add v7.2 controller support Florian Fainelli
@ 2016-06-02 17:13 ` Boris Brezillon
2016-06-02 19:36 ` Kamal Dasu
2016-06-03 1:47 ` Rob Herring
2016-06-03 10:05 ` Boris Brezillon
2 siblings, 1 reply; 5+ messages in thread
From: Boris Brezillon @ 2016-06-02 17:13 UTC (permalink / raw)
To: Florian Fainelli
Cc: linux-mtd, thomas.petazzoni, Mark Rutland, Pawel Moll,
Ian Campbell, Kamal Dasu, open list, Richard Weinberger,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Rob Herring, open list:BROADCOM STB NAND FLASH DRIVER,
Kumar Gala, Simon Arlott, Brian Norris, David Woodhouse
On Tue, 31 May 2016 10:23:02 -0700
Florian Fainelli <f.fainelli@gmail.com> wrote:
> The 7.2 controller differs in a few area compared to its predecssor (7.1):
>
> - NAND scrambler, which we are not using just yet
> - higher ECC levels (up to 120 bits) per 1KB data blocks, also not supported yet
> - up to 128B OOB
>
> This patchs adds the ncessary code to support such a controller
> generation and updates the Device Tree binding.
>
This patch looks good to me. Brian, Kamal, do you want to add your ack?
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> Changes in v2:
>
> - fixed a bunch of conditionals on the versions which should
> have been exclusive (spotted by Thomas)
>
> .../devicetree/bindings/mtd/brcm,brcmnand.txt | 1 +
> drivers/mtd/nand/brcmnand/brcmnand.c | 91 ++++++++++++++++++----
> 2 files changed, 78 insertions(+), 14 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> index deb24cbdda82..c8d71e75cb09 100644
> --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> @@ -27,6 +27,7 @@ Required properties:
> brcm,brcmnand-v6.2
> brcm,brcmnand-v7.0
> brcm,brcmnand-v7.1
> + brcm,brcmnand-v7.2
> brcm,brcmnand
> - reg : the register start and length for NAND register region.
> (optional) Flash DMA register range (if present)
> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
> index b76ad7c0144f..0a54a0f5a4b1 100644
> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
> @@ -340,6 +340,36 @@ static const u16 brcmnand_regs_v71[] = {
> [BRCMNAND_FC_BASE] = 0x400,
> };
>
> +/* BRCMNAND v7.2 */
> +static const u16 brcmnand_regs_v72[] = {
> + [BRCMNAND_CMD_START] = 0x04,
> + [BRCMNAND_CMD_EXT_ADDRESS] = 0x08,
> + [BRCMNAND_CMD_ADDRESS] = 0x0c,
> + [BRCMNAND_INTFC_STATUS] = 0x14,
> + [BRCMNAND_CS_SELECT] = 0x18,
> + [BRCMNAND_CS_XOR] = 0x1c,
> + [BRCMNAND_LL_OP] = 0x20,
> + [BRCMNAND_CS0_BASE] = 0x50,
> + [BRCMNAND_CS1_BASE] = 0,
> + [BRCMNAND_CORR_THRESHOLD] = 0xdc,
> + [BRCMNAND_CORR_THRESHOLD_EXT] = 0xe0,
> + [BRCMNAND_UNCORR_COUNT] = 0xfc,
> + [BRCMNAND_CORR_COUNT] = 0x100,
> + [BRCMNAND_CORR_EXT_ADDR] = 0x10c,
> + [BRCMNAND_CORR_ADDR] = 0x110,
> + [BRCMNAND_UNCORR_EXT_ADDR] = 0x114,
> + [BRCMNAND_UNCORR_ADDR] = 0x118,
> + [BRCMNAND_SEMAPHORE] = 0x150,
> + [BRCMNAND_ID] = 0x194,
> + [BRCMNAND_ID_EXT] = 0x198,
> + [BRCMNAND_LL_RDATA] = 0x19c,
> + [BRCMNAND_OOB_READ_BASE] = 0x200,
> + [BRCMNAND_OOB_READ_10_BASE] = 0,
> + [BRCMNAND_OOB_WRITE_BASE] = 0x400,
> + [BRCMNAND_OOB_WRITE_10_BASE] = 0,
> + [BRCMNAND_FC_BASE] = 0x600,
> +};
> +
> enum brcmnand_cs_reg {
> BRCMNAND_CS_CFG_EXT = 0,
> BRCMNAND_CS_CFG,
> @@ -435,7 +465,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
> }
>
> /* Register offsets */
> - if (ctrl->nand_version >= 0x0701)
> + if (ctrl->nand_version >= 0x0702)
> + ctrl->reg_offsets = brcmnand_regs_v72;
> + else if (ctrl->nand_version >= 0x0701)
> ctrl->reg_offsets = brcmnand_regs_v71;
> else if (ctrl->nand_version >= 0x0600)
> ctrl->reg_offsets = brcmnand_regs_v60;
> @@ -480,7 +512,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
> }
>
> /* Maximum spare area sector size (per 512B) */
> - if (ctrl->nand_version >= 0x0600)
> + if (ctrl->nand_version >= 0x0702)
> + ctrl->max_oob = 128;
> + else if (ctrl->nand_version >= 0x0600)
> ctrl->max_oob = 64;
> else if (ctrl->nand_version >= 0x0500)
> ctrl->max_oob = 32;
> @@ -583,14 +617,20 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val)
> enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD;
> int cs = host->cs;
>
> - if (ctrl->nand_version >= 0x0600)
> + if (ctrl->nand_version >= 0x0702)
> + bits = 7;
> + else if (ctrl->nand_version >= 0x0600)
> bits = 6;
> else if (ctrl->nand_version >= 0x0500)
> bits = 5;
> else
> bits = 4;
>
> - if (ctrl->nand_version >= 0x0600) {
> + if (ctrl->nand_version >= 0x0702) {
> + if (cs >= 4)
> + reg = BRCMNAND_CORR_THRESHOLD_EXT;
> + shift = (cs % 4) * bits;
> + } else if (ctrl->nand_version >= 0x0600) {
> if (cs >= 5)
> reg = BRCMNAND_CORR_THRESHOLD_EXT;
> shift = (cs % 5) * bits;
> @@ -631,19 +671,28 @@ enum {
>
> static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
> {
> - if (ctrl->nand_version >= 0x0600)
> + if (ctrl->nand_version >= 0x0702)
> + return GENMASK(7, 0);
> + else if (ctrl->nand_version >= 0x0600)
> return GENMASK(6, 0);
> else
> return GENMASK(5, 0);
> }
>
> #define NAND_ACC_CONTROL_ECC_SHIFT 16
> +#define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13
>
> static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl)
> {
> u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f;
>
> - return mask << NAND_ACC_CONTROL_ECC_SHIFT;
> + mask <<= NAND_ACC_CONTROL_ECC_SHIFT;
> +
> + /* v7.2 includes additional ECC levels */
> + if (ctrl->nand_version >= 0x0702)
> + mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT;
> +
> + return mask;
> }
>
> static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
> @@ -667,7 +716,9 @@ static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
>
> static inline int brcmnand_sector_1k_shift(struct brcmnand_controller *ctrl)
> {
> - if (ctrl->nand_version >= 0x0600)
> + if (ctrl->nand_version >= 0x0702)
> + return 9;
> + else if (ctrl->nand_version >= 0x0600)
> return 7;
> else if (ctrl->nand_version >= 0x0500)
> return 6;
> @@ -773,10 +824,16 @@ enum brcmnand_llop_type {
> * Internal support functions
> ***********************************************************************/
>
> -static inline bool is_hamming_ecc(struct brcmnand_cfg *cfg)
> +static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl,
> + struct brcmnand_cfg *cfg)
> {
> - return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 &&
> - cfg->ecc_level == 15;
> + if (ctrl->nand_version <= 0x0701)
> + return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 &&
> + cfg->ecc_level == 15;
> + else
> + return cfg->sector_size_1k == 0 && ((cfg->spare_area_size == 16 &&
> + cfg->ecc_level == 15) ||
> + (cfg->spare_area_size == 28 && cfg->ecc_level == 16));
> }
>
> /*
> @@ -931,7 +988,7 @@ static int brcmstb_choose_ecc_layout(struct brcmnand_host *host)
> if (p->sector_size_1k)
> ecc_level <<= 1;
>
> - if (is_hamming_ecc(p)) {
> + if (is_hamming_ecc(host->ctrl, p)) {
> ecc->bytes = 3 * sectors;
> mtd_set_ooblayout(mtd, &brcmnand_hamming_ooblayout_ops);
> return 0;
> @@ -1857,7 +1914,8 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
> return 0;
> }
>
> -static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg)
> +static void brcmnand_print_cfg(struct brcmnand_host *host,
> + char *buf, struct brcmnand_cfg *cfg)
> {
> buf += sprintf(buf,
> "%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit",
> @@ -1868,7 +1926,7 @@ static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg)
> cfg->spare_area_size, cfg->device_width);
>
> /* Account for Hamming ECC and for BCH 512B vs 1KiB sectors */
> - if (is_hamming_ecc(cfg))
> + if (is_hamming_ecc(host->ctrl, cfg))
> sprintf(buf, ", Hamming ECC");
> else if (cfg->sector_size_1k)
> sprintf(buf, ", BCH-%u (1KiB sector)", cfg->ecc_level << 1);
> @@ -1987,7 +2045,7 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
>
> brcmnand_set_ecc_enabled(host, 1);
>
> - brcmnand_print_cfg(msg, cfg);
> + brcmnand_print_cfg(host, msg, cfg);
> dev_info(ctrl->dev, "detected %s\n", msg);
>
> /* Configure ACC_CONTROL */
> @@ -1995,6 +2053,10 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
> tmp = nand_readreg(ctrl, offs);
> tmp &= ~ACC_CONTROL_PARTIAL_PAGE;
> tmp &= ~ACC_CONTROL_RD_ERASED;
> +
> + /* We need to turn on Read from erased paged protected by ECC */
> + if (ctrl->nand_version >= 0x0702)
> + tmp |= ACC_CONTROL_RD_ERASED;
> tmp &= ~ACC_CONTROL_FAST_PGM_RDIN;
> if (ctrl->features & BRCMNAND_HAS_PREFETCH) {
> /*
> @@ -2195,6 +2257,7 @@ static const struct of_device_id brcmnand_of_match[] = {
> { .compatible = "brcm,brcmnand-v6.2" },
> { .compatible = "brcm,brcmnand-v7.0" },
> { .compatible = "brcm,brcmnand-v7.1" },
> + { .compatible = "brcm,brcmnand-v7.2" },
> {},
> };
> MODULE_DEVICE_TABLE(of, brcmnand_of_match);
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] mtd: brcmnand: Add v7.2 controller support
2016-06-02 17:13 ` Boris Brezillon
@ 2016-06-02 19:36 ` Kamal Dasu
0 siblings, 0 replies; 5+ messages in thread
From: Kamal Dasu @ 2016-06-02 19:36 UTC (permalink / raw)
To: Boris Brezillon
Cc: Florian Fainelli, linux-mtd, thomas.petazzoni, Mark Rutland,
Pawel Moll, Ian Campbell, Kamal Dasu, open list,
Richard Weinberger,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Rob Herring, open list:BROADCOM STB NAND FLASH DRIVER,
Kumar Gala, Simon Arlott, Brian Norris, David Woodhouse
This patch looks good to me.
Acked-by: Kamal Dasu <kdasu.kdev@gmail.com>
Thanks
Kamal
On Thu, Jun 2, 2016 at 1:13 PM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> On Tue, 31 May 2016 10:23:02 -0700
> Florian Fainelli <f.fainelli@gmail.com> wrote:
>
>> The 7.2 controller differs in a few area compared to its predecssor (7.1):
>>
>> - NAND scrambler, which we are not using just yet
>> - higher ECC levels (up to 120 bits) per 1KB data blocks, also not supported yet
>> - up to 128B OOB
>>
>> This patchs adds the ncessary code to support such a controller
>> generation and updates the Device Tree binding.
>>
>
> This patch looks good to me. Brian, Kamal, do you want to add your ack?
>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>> Changes in v2:
>>
>> - fixed a bunch of conditionals on the versions which should
>> have been exclusive (spotted by Thomas)
>>
>> .../devicetree/bindings/mtd/brcm,brcmnand.txt | 1 +
>> drivers/mtd/nand/brcmnand/brcmnand.c | 91 ++++++++++++++++++----
>> 2 files changed, 78 insertions(+), 14 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>> index deb24cbdda82..c8d71e75cb09 100644
>> --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>> +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>> @@ -27,6 +27,7 @@ Required properties:
>> brcm,brcmnand-v6.2
>> brcm,brcmnand-v7.0
>> brcm,brcmnand-v7.1
>> + brcm,brcmnand-v7.2
>> brcm,brcmnand
>> - reg : the register start and length for NAND register region.
>> (optional) Flash DMA register range (if present)
>> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
>> index b76ad7c0144f..0a54a0f5a4b1 100644
>> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
>> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
>> @@ -340,6 +340,36 @@ static const u16 brcmnand_regs_v71[] = {
>> [BRCMNAND_FC_BASE] = 0x400,
>> };
>>
>> +/* BRCMNAND v7.2 */
>> +static const u16 brcmnand_regs_v72[] = {
>> + [BRCMNAND_CMD_START] = 0x04,
>> + [BRCMNAND_CMD_EXT_ADDRESS] = 0x08,
>> + [BRCMNAND_CMD_ADDRESS] = 0x0c,
>> + [BRCMNAND_INTFC_STATUS] = 0x14,
>> + [BRCMNAND_CS_SELECT] = 0x18,
>> + [BRCMNAND_CS_XOR] = 0x1c,
>> + [BRCMNAND_LL_OP] = 0x20,
>> + [BRCMNAND_CS0_BASE] = 0x50,
>> + [BRCMNAND_CS1_BASE] = 0,
>> + [BRCMNAND_CORR_THRESHOLD] = 0xdc,
>> + [BRCMNAND_CORR_THRESHOLD_EXT] = 0xe0,
>> + [BRCMNAND_UNCORR_COUNT] = 0xfc,
>> + [BRCMNAND_CORR_COUNT] = 0x100,
>> + [BRCMNAND_CORR_EXT_ADDR] = 0x10c,
>> + [BRCMNAND_CORR_ADDR] = 0x110,
>> + [BRCMNAND_UNCORR_EXT_ADDR] = 0x114,
>> + [BRCMNAND_UNCORR_ADDR] = 0x118,
>> + [BRCMNAND_SEMAPHORE] = 0x150,
>> + [BRCMNAND_ID] = 0x194,
>> + [BRCMNAND_ID_EXT] = 0x198,
>> + [BRCMNAND_LL_RDATA] = 0x19c,
>> + [BRCMNAND_OOB_READ_BASE] = 0x200,
>> + [BRCMNAND_OOB_READ_10_BASE] = 0,
>> + [BRCMNAND_OOB_WRITE_BASE] = 0x400,
>> + [BRCMNAND_OOB_WRITE_10_BASE] = 0,
>> + [BRCMNAND_FC_BASE] = 0x600,
>> +};
>> +
>> enum brcmnand_cs_reg {
>> BRCMNAND_CS_CFG_EXT = 0,
>> BRCMNAND_CS_CFG,
>> @@ -435,7 +465,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
>> }
>>
>> /* Register offsets */
>> - if (ctrl->nand_version >= 0x0701)
>> + if (ctrl->nand_version >= 0x0702)
>> + ctrl->reg_offsets = brcmnand_regs_v72;
>> + else if (ctrl->nand_version >= 0x0701)
>> ctrl->reg_offsets = brcmnand_regs_v71;
>> else if (ctrl->nand_version >= 0x0600)
>> ctrl->reg_offsets = brcmnand_regs_v60;
>> @@ -480,7 +512,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
>> }
>>
>> /* Maximum spare area sector size (per 512B) */
>> - if (ctrl->nand_version >= 0x0600)
>> + if (ctrl->nand_version >= 0x0702)
>> + ctrl->max_oob = 128;
>> + else if (ctrl->nand_version >= 0x0600)
>> ctrl->max_oob = 64;
>> else if (ctrl->nand_version >= 0x0500)
>> ctrl->max_oob = 32;
>> @@ -583,14 +617,20 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val)
>> enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD;
>> int cs = host->cs;
>>
>> - if (ctrl->nand_version >= 0x0600)
>> + if (ctrl->nand_version >= 0x0702)
>> + bits = 7;
>> + else if (ctrl->nand_version >= 0x0600)
>> bits = 6;
>> else if (ctrl->nand_version >= 0x0500)
>> bits = 5;
>> else
>> bits = 4;
>>
>> - if (ctrl->nand_version >= 0x0600) {
>> + if (ctrl->nand_version >= 0x0702) {
>> + if (cs >= 4)
>> + reg = BRCMNAND_CORR_THRESHOLD_EXT;
>> + shift = (cs % 4) * bits;
>> + } else if (ctrl->nand_version >= 0x0600) {
>> if (cs >= 5)
>> reg = BRCMNAND_CORR_THRESHOLD_EXT;
>> shift = (cs % 5) * bits;
>> @@ -631,19 +671,28 @@ enum {
>>
>> static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
>> {
>> - if (ctrl->nand_version >= 0x0600)
>> + if (ctrl->nand_version >= 0x0702)
>> + return GENMASK(7, 0);
>> + else if (ctrl->nand_version >= 0x0600)
>> return GENMASK(6, 0);
>> else
>> return GENMASK(5, 0);
>> }
>>
>> #define NAND_ACC_CONTROL_ECC_SHIFT 16
>> +#define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13
>>
>> static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl)
>> {
>> u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f;
>>
>> - return mask << NAND_ACC_CONTROL_ECC_SHIFT;
>> + mask <<= NAND_ACC_CONTROL_ECC_SHIFT;
>> +
>> + /* v7.2 includes additional ECC levels */
>> + if (ctrl->nand_version >= 0x0702)
>> + mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT;
>> +
>> + return mask;
>> }
>>
>> static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
>> @@ -667,7 +716,9 @@ static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
>>
>> static inline int brcmnand_sector_1k_shift(struct brcmnand_controller *ctrl)
>> {
>> - if (ctrl->nand_version >= 0x0600)
>> + if (ctrl->nand_version >= 0x0702)
>> + return 9;
>> + else if (ctrl->nand_version >= 0x0600)
>> return 7;
>> else if (ctrl->nand_version >= 0x0500)
>> return 6;
>> @@ -773,10 +824,16 @@ enum brcmnand_llop_type {
>> * Internal support functions
>> ***********************************************************************/
>>
>> -static inline bool is_hamming_ecc(struct brcmnand_cfg *cfg)
>> +static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl,
>> + struct brcmnand_cfg *cfg)
>> {
>> - return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 &&
>> - cfg->ecc_level == 15;
>> + if (ctrl->nand_version <= 0x0701)
>> + return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 &&
>> + cfg->ecc_level == 15;
>> + else
>> + return cfg->sector_size_1k == 0 && ((cfg->spare_area_size == 16 &&
>> + cfg->ecc_level == 15) ||
>> + (cfg->spare_area_size == 28 && cfg->ecc_level == 16));
>> }
>>
>> /*
>> @@ -931,7 +988,7 @@ static int brcmstb_choose_ecc_layout(struct brcmnand_host *host)
>> if (p->sector_size_1k)
>> ecc_level <<= 1;
>>
>> - if (is_hamming_ecc(p)) {
>> + if (is_hamming_ecc(host->ctrl, p)) {
>> ecc->bytes = 3 * sectors;
>> mtd_set_ooblayout(mtd, &brcmnand_hamming_ooblayout_ops);
>> return 0;
>> @@ -1857,7 +1914,8 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
>> return 0;
>> }
>>
>> -static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg)
>> +static void brcmnand_print_cfg(struct brcmnand_host *host,
>> + char *buf, struct brcmnand_cfg *cfg)
>> {
>> buf += sprintf(buf,
>> "%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit",
>> @@ -1868,7 +1926,7 @@ static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg)
>> cfg->spare_area_size, cfg->device_width);
>>
>> /* Account for Hamming ECC and for BCH 512B vs 1KiB sectors */
>> - if (is_hamming_ecc(cfg))
>> + if (is_hamming_ecc(host->ctrl, cfg))
>> sprintf(buf, ", Hamming ECC");
>> else if (cfg->sector_size_1k)
>> sprintf(buf, ", BCH-%u (1KiB sector)", cfg->ecc_level << 1);
>> @@ -1987,7 +2045,7 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
>>
>> brcmnand_set_ecc_enabled(host, 1);
>>
>> - brcmnand_print_cfg(msg, cfg);
>> + brcmnand_print_cfg(host, msg, cfg);
>> dev_info(ctrl->dev, "detected %s\n", msg);
>>
>> /* Configure ACC_CONTROL */
>> @@ -1995,6 +2053,10 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
>> tmp = nand_readreg(ctrl, offs);
>> tmp &= ~ACC_CONTROL_PARTIAL_PAGE;
>> tmp &= ~ACC_CONTROL_RD_ERASED;
>> +
>> + /* We need to turn on Read from erased paged protected by ECC */
>> + if (ctrl->nand_version >= 0x0702)
>> + tmp |= ACC_CONTROL_RD_ERASED;
>> tmp &= ~ACC_CONTROL_FAST_PGM_RDIN;
>> if (ctrl->features & BRCMNAND_HAS_PREFETCH) {
>> /*
>> @@ -2195,6 +2257,7 @@ static const struct of_device_id brcmnand_of_match[] = {
>> { .compatible = "brcm,brcmnand-v6.2" },
>> { .compatible = "brcm,brcmnand-v7.0" },
>> { .compatible = "brcm,brcmnand-v7.1" },
>> + { .compatible = "brcm,brcmnand-v7.2" },
>> {},
>> };
>> MODULE_DEVICE_TABLE(of, brcmnand_of_match);
>
>
>
> --
> Boris Brezillon, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] mtd: brcmnand: Add v7.2 controller support
2016-05-31 17:23 [PATCH v2] mtd: brcmnand: Add v7.2 controller support Florian Fainelli
2016-06-02 17:13 ` Boris Brezillon
@ 2016-06-03 1:47 ` Rob Herring
2016-06-03 10:05 ` Boris Brezillon
2 siblings, 0 replies; 5+ messages in thread
From: Rob Herring @ 2016-06-03 1:47 UTC (permalink / raw)
To: Florian Fainelli
Cc: linux-mtd, thomas.petazzoni, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Brian Norris, Kamal Dasu,
Boris Brezillon, Richard Weinberger, David Woodhouse,
Simon Arlott,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list, open list:BROADCOM STB NAND FLASH DRIVER
On Tue, May 31, 2016 at 10:23:02AM -0700, Florian Fainelli wrote:
> The 7.2 controller differs in a few area compared to its predecssor (7.1):
>
> - NAND scrambler, which we are not using just yet
> - higher ECC levels (up to 120 bits) per 1KB data blocks, also not supported yet
> - up to 128B OOB
>
> This patchs adds the ncessary code to support such a controller
s/patchs/patch/
s/ncessary/necessary/
> generation and updates the Device Tree binding.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> Changes in v2:
>
> - fixed a bunch of conditionals on the versions which should
> have been exclusive (spotted by Thomas)
>
> .../devicetree/bindings/mtd/brcm,brcmnand.txt | 1 +
With those changes,
Acked-by: Rob Herring <robh@kernel.org>
> drivers/mtd/nand/brcmnand/brcmnand.c | 91 ++++++++++++++++++----
> 2 files changed, 78 insertions(+), 14 deletions(-)
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] mtd: brcmnand: Add v7.2 controller support
2016-05-31 17:23 [PATCH v2] mtd: brcmnand: Add v7.2 controller support Florian Fainelli
2016-06-02 17:13 ` Boris Brezillon
2016-06-03 1:47 ` Rob Herring
@ 2016-06-03 10:05 ` Boris Brezillon
2 siblings, 0 replies; 5+ messages in thread
From: Boris Brezillon @ 2016-06-03 10:05 UTC (permalink / raw)
To: Florian Fainelli
Cc: linux-mtd, thomas.petazzoni, Rob Herring, Pawel Moll,
Mark Rutland, Ian Campbell, Kumar Gala, Brian Norris, Kamal Dasu,
Richard Weinberger, David Woodhouse, Simon Arlott,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list, open list:BROADCOM STB NAND FLASH DRIVER
On Tue, 31 May 2016 10:23:02 -0700
Florian Fainelli <f.fainelli@gmail.com> wrote:
> The 7.2 controller differs in a few area compared to its predecssor (7.1):
>
> - NAND scrambler, which we are not using just yet
> - higher ECC levels (up to 120 bits) per 1KB data blocks, also not supported yet
> - up to 128B OOB
>
> This patchs adds the ncessary code to support such a controller
> generation and updates the Device Tree binding.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Applied with Rob's fixes.
Thanks,
Boris
> ---
> Changes in v2:
>
> - fixed a bunch of conditionals on the versions which should
> have been exclusive (spotted by Thomas)
>
> .../devicetree/bindings/mtd/brcm,brcmnand.txt | 1 +
> drivers/mtd/nand/brcmnand/brcmnand.c | 91 ++++++++++++++++++----
> 2 files changed, 78 insertions(+), 14 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> index deb24cbdda82..c8d71e75cb09 100644
> --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> @@ -27,6 +27,7 @@ Required properties:
> brcm,brcmnand-v6.2
> brcm,brcmnand-v7.0
> brcm,brcmnand-v7.1
> + brcm,brcmnand-v7.2
> brcm,brcmnand
> - reg : the register start and length for NAND register region.
> (optional) Flash DMA register range (if present)
> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
> index b76ad7c0144f..0a54a0f5a4b1 100644
> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
> @@ -340,6 +340,36 @@ static const u16 brcmnand_regs_v71[] = {
> [BRCMNAND_FC_BASE] = 0x400,
> };
>
> +/* BRCMNAND v7.2 */
> +static const u16 brcmnand_regs_v72[] = {
> + [BRCMNAND_CMD_START] = 0x04,
> + [BRCMNAND_CMD_EXT_ADDRESS] = 0x08,
> + [BRCMNAND_CMD_ADDRESS] = 0x0c,
> + [BRCMNAND_INTFC_STATUS] = 0x14,
> + [BRCMNAND_CS_SELECT] = 0x18,
> + [BRCMNAND_CS_XOR] = 0x1c,
> + [BRCMNAND_LL_OP] = 0x20,
> + [BRCMNAND_CS0_BASE] = 0x50,
> + [BRCMNAND_CS1_BASE] = 0,
> + [BRCMNAND_CORR_THRESHOLD] = 0xdc,
> + [BRCMNAND_CORR_THRESHOLD_EXT] = 0xe0,
> + [BRCMNAND_UNCORR_COUNT] = 0xfc,
> + [BRCMNAND_CORR_COUNT] = 0x100,
> + [BRCMNAND_CORR_EXT_ADDR] = 0x10c,
> + [BRCMNAND_CORR_ADDR] = 0x110,
> + [BRCMNAND_UNCORR_EXT_ADDR] = 0x114,
> + [BRCMNAND_UNCORR_ADDR] = 0x118,
> + [BRCMNAND_SEMAPHORE] = 0x150,
> + [BRCMNAND_ID] = 0x194,
> + [BRCMNAND_ID_EXT] = 0x198,
> + [BRCMNAND_LL_RDATA] = 0x19c,
> + [BRCMNAND_OOB_READ_BASE] = 0x200,
> + [BRCMNAND_OOB_READ_10_BASE] = 0,
> + [BRCMNAND_OOB_WRITE_BASE] = 0x400,
> + [BRCMNAND_OOB_WRITE_10_BASE] = 0,
> + [BRCMNAND_FC_BASE] = 0x600,
> +};
> +
> enum brcmnand_cs_reg {
> BRCMNAND_CS_CFG_EXT = 0,
> BRCMNAND_CS_CFG,
> @@ -435,7 +465,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
> }
>
> /* Register offsets */
> - if (ctrl->nand_version >= 0x0701)
> + if (ctrl->nand_version >= 0x0702)
> + ctrl->reg_offsets = brcmnand_regs_v72;
> + else if (ctrl->nand_version >= 0x0701)
> ctrl->reg_offsets = brcmnand_regs_v71;
> else if (ctrl->nand_version >= 0x0600)
> ctrl->reg_offsets = brcmnand_regs_v60;
> @@ -480,7 +512,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
> }
>
> /* Maximum spare area sector size (per 512B) */
> - if (ctrl->nand_version >= 0x0600)
> + if (ctrl->nand_version >= 0x0702)
> + ctrl->max_oob = 128;
> + else if (ctrl->nand_version >= 0x0600)
> ctrl->max_oob = 64;
> else if (ctrl->nand_version >= 0x0500)
> ctrl->max_oob = 32;
> @@ -583,14 +617,20 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val)
> enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD;
> int cs = host->cs;
>
> - if (ctrl->nand_version >= 0x0600)
> + if (ctrl->nand_version >= 0x0702)
> + bits = 7;
> + else if (ctrl->nand_version >= 0x0600)
> bits = 6;
> else if (ctrl->nand_version >= 0x0500)
> bits = 5;
> else
> bits = 4;
>
> - if (ctrl->nand_version >= 0x0600) {
> + if (ctrl->nand_version >= 0x0702) {
> + if (cs >= 4)
> + reg = BRCMNAND_CORR_THRESHOLD_EXT;
> + shift = (cs % 4) * bits;
> + } else if (ctrl->nand_version >= 0x0600) {
> if (cs >= 5)
> reg = BRCMNAND_CORR_THRESHOLD_EXT;
> shift = (cs % 5) * bits;
> @@ -631,19 +671,28 @@ enum {
>
> static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
> {
> - if (ctrl->nand_version >= 0x0600)
> + if (ctrl->nand_version >= 0x0702)
> + return GENMASK(7, 0);
> + else if (ctrl->nand_version >= 0x0600)
> return GENMASK(6, 0);
> else
> return GENMASK(5, 0);
> }
>
> #define NAND_ACC_CONTROL_ECC_SHIFT 16
> +#define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13
>
> static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl)
> {
> u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f;
>
> - return mask << NAND_ACC_CONTROL_ECC_SHIFT;
> + mask <<= NAND_ACC_CONTROL_ECC_SHIFT;
> +
> + /* v7.2 includes additional ECC levels */
> + if (ctrl->nand_version >= 0x0702)
> + mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT;
> +
> + return mask;
> }
>
> static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
> @@ -667,7 +716,9 @@ static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
>
> static inline int brcmnand_sector_1k_shift(struct brcmnand_controller *ctrl)
> {
> - if (ctrl->nand_version >= 0x0600)
> + if (ctrl->nand_version >= 0x0702)
> + return 9;
> + else if (ctrl->nand_version >= 0x0600)
> return 7;
> else if (ctrl->nand_version >= 0x0500)
> return 6;
> @@ -773,10 +824,16 @@ enum brcmnand_llop_type {
> * Internal support functions
> ***********************************************************************/
>
> -static inline bool is_hamming_ecc(struct brcmnand_cfg *cfg)
> +static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl,
> + struct brcmnand_cfg *cfg)
> {
> - return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 &&
> - cfg->ecc_level == 15;
> + if (ctrl->nand_version <= 0x0701)
> + return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 &&
> + cfg->ecc_level == 15;
> + else
> + return cfg->sector_size_1k == 0 && ((cfg->spare_area_size == 16 &&
> + cfg->ecc_level == 15) ||
> + (cfg->spare_area_size == 28 && cfg->ecc_level == 16));
> }
>
> /*
> @@ -931,7 +988,7 @@ static int brcmstb_choose_ecc_layout(struct brcmnand_host *host)
> if (p->sector_size_1k)
> ecc_level <<= 1;
>
> - if (is_hamming_ecc(p)) {
> + if (is_hamming_ecc(host->ctrl, p)) {
> ecc->bytes = 3 * sectors;
> mtd_set_ooblayout(mtd, &brcmnand_hamming_ooblayout_ops);
> return 0;
> @@ -1857,7 +1914,8 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
> return 0;
> }
>
> -static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg)
> +static void brcmnand_print_cfg(struct brcmnand_host *host,
> + char *buf, struct brcmnand_cfg *cfg)
> {
> buf += sprintf(buf,
> "%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit",
> @@ -1868,7 +1926,7 @@ static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg)
> cfg->spare_area_size, cfg->device_width);
>
> /* Account for Hamming ECC and for BCH 512B vs 1KiB sectors */
> - if (is_hamming_ecc(cfg))
> + if (is_hamming_ecc(host->ctrl, cfg))
> sprintf(buf, ", Hamming ECC");
> else if (cfg->sector_size_1k)
> sprintf(buf, ", BCH-%u (1KiB sector)", cfg->ecc_level << 1);
> @@ -1987,7 +2045,7 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
>
> brcmnand_set_ecc_enabled(host, 1);
>
> - brcmnand_print_cfg(msg, cfg);
> + brcmnand_print_cfg(host, msg, cfg);
> dev_info(ctrl->dev, "detected %s\n", msg);
>
> /* Configure ACC_CONTROL */
> @@ -1995,6 +2053,10 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
> tmp = nand_readreg(ctrl, offs);
> tmp &= ~ACC_CONTROL_PARTIAL_PAGE;
> tmp &= ~ACC_CONTROL_RD_ERASED;
> +
> + /* We need to turn on Read from erased paged protected by ECC */
> + if (ctrl->nand_version >= 0x0702)
> + tmp |= ACC_CONTROL_RD_ERASED;
> tmp &= ~ACC_CONTROL_FAST_PGM_RDIN;
> if (ctrl->features & BRCMNAND_HAS_PREFETCH) {
> /*
> @@ -2195,6 +2257,7 @@ static const struct of_device_id brcmnand_of_match[] = {
> { .compatible = "brcm,brcmnand-v6.2" },
> { .compatible = "brcm,brcmnand-v7.0" },
> { .compatible = "brcm,brcmnand-v7.1" },
> + { .compatible = "brcm,brcmnand-v7.2" },
> {},
> };
> MODULE_DEVICE_TABLE(of, brcmnand_of_match);
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-06-03 10:05 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-31 17:23 [PATCH v2] mtd: brcmnand: Add v7.2 controller support Florian Fainelli
2016-06-02 17:13 ` Boris Brezillon
2016-06-02 19:36 ` Kamal Dasu
2016-06-03 1:47 ` Rob Herring
2016-06-03 10:05 ` Boris Brezillon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).