[u-boot][PATCH v2 0/8] rawnand: omap_gpmc: driver model support

Hi Michael & Dario,
This series adds driver model support for rawnand: omap_gpmc and omap_elm drivers.
This will enable the driver to be used on K2/K3 platforms as well.
This series along with remaining patches required to get NAND working on AM6x EVM is available here https://github.com/rogerq/u-boot/commits/for-v2023.01/am64-nand-base-2.0
cheers, -roger
Changelog: v2: - Fixed build warning and failures for am335x_guardian, chiliboard, and cm_t32 - use __maybe_unused struct nand_chip to fix build warning - make elm_probe() a NOP if ELM_BASE is defined. This should not interfere with existing platforms that don't use Driver Model for ELM driver.
Roger Quadros (8): mtd: rawnand: omap_gpmc: Fix BCH6/16 HW based correction mtd: rawnand: nand_base: Allow base driver to be used in SPL without nand_bbt dt-bindings: mtd: Add ti,gpmc-nand DT binding documentation mtd: rawnand: omap_gpmc: support u-boot driver model mtd: rawnand: omap_gpmc: Add SPL NAND support mtd: rawnand: omap_gpmc: Enable SYS_NAND_PAGE_COUNT for OMAP_GPMC dt-bindings: mtd: Add ti,elm DT binding documentation mtd: rawnand: omap_elm: u-boot driver model support
doc/device-tree-bindings/mtd/ti,elm.yaml | 72 +++ .../mtd/ti,gpmc-nand.yaml | 129 +++++ drivers/mtd/nand/raw/Kconfig | 9 +- drivers/mtd/nand/raw/Makefile | 2 +- drivers/mtd/nand/raw/nand_base.c | 18 +- drivers/mtd/nand/raw/omap_elm.c | 35 +- .../mtd => drivers/mtd/nand/raw}/omap_elm.h | 6 + drivers/mtd/nand/raw/omap_gpmc.c | 441 +++++++++++++----- 8 files changed, 604 insertions(+), 108 deletions(-) create mode 100644 doc/device-tree-bindings/mtd/ti,elm.yaml create mode 100644 doc/device-tree-bindings/mtd/ti,gpmc-nand.yaml rename {include/linux/mtd => drivers/mtd/nand/raw}/omap_elm.h (97%)

The BCH detection hardware can generate ECC bytes for multiple sectors in one go. Use that feature.
correct() only corrects one sector at a time so we need to call it repeatedly for each sector.
Signed-off-by: Roger Quadros rogerq@kernel.org Reviewed-by: Michael Trimarchi michael@amarulasolutions.com --- drivers/mtd/nand/raw/omap_gpmc.c | 325 +++++++++++++++++++++---------- 1 file changed, 223 insertions(+), 102 deletions(-)
diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index 69fc09be097..e772a914c88 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -27,6 +27,9 @@
#define BADBLOCK_MARKER_LENGTH 2 #define SECTOR_BYTES 512 +#define ECCSIZE0_SHIFT 12 +#define ECCSIZE1_SHIFT 22 +#define ECC1RESULTSIZE 0x1 #define ECCCLEAR (0x1 << 8) #define ECCRESULTREG1 (0x1 << 0) /* 4 bit padding to make byte aligned, 56 = 52 + 4 */ @@ -186,72 +189,35 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat, __maybe_unused static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode) { - struct nand_chip *nand = mtd_to_nand(mtd); - struct omap_nand_info *info = nand_get_controller_data(nand); + struct nand_chip *nand = mtd_to_nand(mtd); + struct omap_nand_info *info = nand_get_controller_data(nand); unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0; - unsigned int ecc_algo = 0; - unsigned int bch_type = 0; - unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00; - u32 ecc_size_config_val = 0; - u32 ecc_config_val = 0; - int cs = info->cs; + u32 val;
- /* configure GPMC for specific ecc-scheme */ - switch (info->ecc_scheme) { - case OMAP_ECC_HAM1_CODE_SW: - return; - case OMAP_ECC_HAM1_CODE_HW: - ecc_algo = 0x0; - bch_type = 0x0; - bch_wrapmode = 0x00; - eccsize0 = 0xFF; - eccsize1 = 0xFF; + /* Clear ecc and enable bits */ + writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control); + + /* program ecc and result sizes */ + val = ((((nand->ecc.size >> 1) - 1) << ECCSIZE1_SHIFT) | + ECC1RESULTSIZE); + writel(val, &gpmc_cfg->ecc_size_config); + + switch (mode) { + case NAND_ECC_READ: + case NAND_ECC_WRITE: + writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control); break; - case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: - case OMAP_ECC_BCH8_CODE_HW: - ecc_algo = 0x1; - bch_type = 0x1; - if (mode == NAND_ECC_WRITE) { - bch_wrapmode = 0x01; - eccsize0 = 0; /* extra bits in nibbles per sector */ - eccsize1 = 28; /* OOB bits in nibbles per sector */ - } else { - bch_wrapmode = 0x01; - eccsize0 = 26; /* ECC bits in nibbles per sector */ - eccsize1 = 2; /* non-ECC bits in nibbles per sector */ - } - break; - case OMAP_ECC_BCH16_CODE_HW: - ecc_algo = 0x1; - bch_type = 0x2; - if (mode == NAND_ECC_WRITE) { - bch_wrapmode = 0x01; - eccsize0 = 0; /* extra bits in nibbles per sector */ - eccsize1 = 52; /* OOB bits in nibbles per sector */ - } else { - bch_wrapmode = 0x01; - eccsize0 = 52; /* ECC bits in nibbles per sector */ - eccsize1 = 0; /* non-ECC bits in nibbles per sector */ - } + case NAND_ECC_READSYN: + writel(ECCCLEAR, &gpmc_cfg->ecc_control); break; default: - return; + printf("%s: error: unrecognized Mode[%d]!\n", __func__, mode); + break; } - /* Clear ecc and enable bits */ - writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control); - /* Configure ecc size for BCH */ - ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12); - writel(ecc_size_config_val, &gpmc_cfg->ecc_size_config); - - /* Configure device details for BCH engine */ - ecc_config_val = ((ecc_algo << 16) | /* HAM1 | BCHx */ - (bch_type << 12) | /* BCH4/BCH8/BCH16 */ - (bch_wrapmode << 8) | /* wrap mode */ - (dev_width << 7) | /* bus width */ - (0x0 << 4) | /* number of sectors */ - (cs << 1) | /* ECC CS */ - (0x1)); /* enable ECC */ - writel(ecc_config_val, &gpmc_cfg->ecc_config); + + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ + val = (dev_width << 7) | (info->cs << 1) | (0x1); + writel(val, &gpmc_cfg->ecc_config); }
/* @@ -270,6 +236,124 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode) */ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code) +{ + u32 val; + + val = readl(&gpmc_cfg->ecc1_result); + ecc_code[0] = val & 0xFF; + ecc_code[1] = (val >> 16) & 0xFF; + ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0); + + return 0; +} + +/* GPMC ecc engine settings for read */ +#define BCH_WRAPMODE_1 1 /* BCH wrap mode 1 */ +#define BCH8R_ECC_SIZE0 0x1a /* ecc_size0 = 26 */ +#define BCH8R_ECC_SIZE1 0x2 /* ecc_size1 = 2 */ +#define BCH4R_ECC_SIZE0 0xd /* ecc_size0 = 13 */ +#define BCH4R_ECC_SIZE1 0x3 /* ecc_size1 = 3 */ + +/* GPMC ecc engine settings for write */ +#define BCH_WRAPMODE_6 6 /* BCH wrap mode 6 */ +#define BCH_ECC_SIZE0 0x0 /* ecc_size0 = 0, no oob protection */ +#define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */ + +/** + * omap_enable_hwecc_bch - Program GPMC to perform BCH ECC calculation + * @mtd: MTD device structure + * @mode: Read/Write mode + * + * When using BCH with SW correction (i.e. no ELM), sector size is set + * to 512 bytes and we use BCH_WRAPMODE_6 wrapping mode + * for both reading and writing with: + * eccsize0 = 0 (no additional protected byte in spare area) + * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) + */ +static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, + int mode) +{ + unsigned int bch_type; + unsigned int dev_width, nsectors; + struct nand_chip *chip = mtd_to_nand(mtd); + struct omap_nand_info *info = nand_get_controller_data(chip); + u32 val, wr_mode; + unsigned int ecc_size1, ecc_size0; + + /* GPMC configurations for calculating ECC */ + switch (info->ecc_scheme) { + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: + bch_type = 1; + nsectors = 1; + wr_mode = BCH_WRAPMODE_6; + ecc_size0 = BCH_ECC_SIZE0; + ecc_size1 = BCH_ECC_SIZE1; + break; + case OMAP_ECC_BCH8_CODE_HW: + bch_type = 1; + nsectors = chip->ecc.steps; + if (mode == NAND_ECC_READ) { + wr_mode = BCH_WRAPMODE_1; + ecc_size0 = BCH8R_ECC_SIZE0; + ecc_size1 = BCH8R_ECC_SIZE1; + } else { + wr_mode = BCH_WRAPMODE_6; + ecc_size0 = BCH_ECC_SIZE0; + ecc_size1 = BCH_ECC_SIZE1; + } + break; + case OMAP_ECC_BCH16_CODE_HW: + bch_type = 0x2; + nsectors = chip->ecc.steps; + if (mode == NAND_ECC_READ) { + wr_mode = 0x01; + ecc_size0 = 52; /* ECC bits in nibbles per sector */ + ecc_size1 = 0; /* non-ECC bits in nibbles per sector */ + } else { + wr_mode = 0x01; + ecc_size0 = 0; /* extra bits in nibbles per sector */ + ecc_size1 = 52; /* OOB bits in nibbles per sector */ + } + break; + default: + return; + } + + writel(ECCRESULTREG1, &gpmc_cfg->ecc_control); + + /* Configure ecc size for BCH */ + val = (ecc_size1 << ECCSIZE1_SHIFT) | (ecc_size0 << ECCSIZE0_SHIFT); + writel(val, &gpmc_cfg->ecc_size_config); + + dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; + + /* BCH configuration */ + val = ((1 << 16) | /* enable BCH */ + (bch_type << 12) | /* BCH4/BCH8/BCH16 */ + (wr_mode << 8) | /* wrap mode */ + (dev_width << 7) | /* bus width */ + (((nsectors - 1) & 0x7) << 4) | /* number of sectors */ + (info->cs << 1) | /* ECC CS */ + (0x1)); /* enable ECC */ + + writel(val, &gpmc_cfg->ecc_config); + + /* Clear ecc and enable bits */ + writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control); +} + +/** + * _omap_calculate_ecc_bch - Generate BCH ECC bytes for one sector + * @mtd: MTD device structure + * @dat: The pointer to data on which ecc is computed + * @ecc_code: The ecc_code buffer + * @sector: The sector number (for a multi sector page) + * + * Support calculating of BCH4/8/16 ECC vectors for one sector + * within a page. Sector number is in @sector. + */ +static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat, + u8 *ecc_code, int sector) { struct nand_chip *chip = mtd_to_nand(mtd); struct omap_nand_info *info = nand_get_controller_data(chip); @@ -278,17 +362,11 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, int8_t i = 0, j;
switch (info->ecc_scheme) { - case OMAP_ECC_HAM1_CODE_HW: - val = readl(&gpmc_cfg->ecc1_result); - ecc_code[0] = val & 0xFF; - ecc_code[1] = (val >> 16) & 0xFF; - ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0); - break; #ifdef CONFIG_BCH case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: #endif case OMAP_ECC_BCH8_CODE_HW: - ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3]; + ptr = &gpmc_cfg->bch_result_0_3[sector].bch_result_x[3]; val = readl(ptr); ecc_code[i++] = (val >> 0) & 0xFF; ptr--; @@ -300,23 +378,24 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, ecc_code[i++] = (val >> 0) & 0xFF; ptr--; } + break; case OMAP_ECC_BCH16_CODE_HW: - val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[2]); + val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[2]); ecc_code[i++] = (val >> 8) & 0xFF; ecc_code[i++] = (val >> 0) & 0xFF; - val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[1]); + val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[1]); ecc_code[i++] = (val >> 24) & 0xFF; ecc_code[i++] = (val >> 16) & 0xFF; ecc_code[i++] = (val >> 8) & 0xFF; ecc_code[i++] = (val >> 0) & 0xFF; - val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[0]); + val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[0]); ecc_code[i++] = (val >> 24) & 0xFF; ecc_code[i++] = (val >> 16) & 0xFF; ecc_code[i++] = (val >> 8) & 0xFF; ecc_code[i++] = (val >> 0) & 0xFF; for (j = 3; j >= 0; j--) { - val = readl(&gpmc_cfg->bch_result_0_3[0].bch_result_x[j] + val = readl(&gpmc_cfg->bch_result_0_3[sector].bch_result_x[j] ); ecc_code[i++] = (val >> 24) & 0xFF; ecc_code[i++] = (val >> 16) & 0xFF; @@ -329,18 +408,18 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, } /* ECC scheme specific syndrome customizations */ switch (info->ecc_scheme) { - case OMAP_ECC_HAM1_CODE_HW: - break; #ifdef CONFIG_BCH case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: - + /* Add constant polynomial to remainder, so that + * ECC of blank pages results in 0x0 on reading back + */ for (i = 0; i < chip->ecc.bytes; i++) - *(ecc_code + i) = *(ecc_code + i) ^ - bch8_polynomial[i]; + ecc_code[i] ^= bch8_polynomial[i]; break; #endif case OMAP_ECC_BCH8_CODE_HW: - ecc_code[chip->ecc.bytes - 1] = 0x00; + /* Set 14th ECC byte as 0x0 for ROM compatibility */ + ecc_code[chip->ecc.bytes - 1] = 0x0; break; case OMAP_ECC_BCH16_CODE_HW: break; @@ -350,6 +429,22 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, return 0; }
+/** + * omap_calculate_ecc_bch - ECC generator for 1 sector + * @mtd: MTD device structure + * @dat: The pointer to data on which ecc is computed + * @ecc_code: The ecc_code buffer + * + * Support calculating of BCH4/8/16 ECC vectors for one sector. This is used + * when SW based correction is required as ECC is required for one sector + * at a time. + */ +static int omap_calculate_ecc_bch(struct mtd_info *mtd, + const u_char *dat, u_char *ecc_calc) +{ + return _omap_calculate_ecc_bch(mtd, dat, ecc_calc, 0); +} + static inline void omap_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); @@ -474,6 +569,35 @@ static void omap_nand_read_prefetch(struct mtd_info *mtd, uint8_t *buf, int len) #endif /* CONFIG_NAND_OMAP_GPMC_PREFETCH */
#ifdef CONFIG_NAND_OMAP_ELM + +/** + * omap_calculate_ecc_bch_multi - Generate ECC for multiple sectors + * @mtd: MTD device structure + * @dat: The pointer to data on which ecc is computed + * @ecc_code: The ecc_code buffer + * + * Support calculating of BCH4/8/16 ecc vectors for the entire page in one go. + */ +static int omap_calculate_ecc_bch_multi(struct mtd_info *mtd, + const u_char *dat, u_char *ecc_calc) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + int eccbytes = chip->ecc.bytes; + unsigned long nsectors; + int i, ret; + + nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1; + for (i = 0; i < nsectors; i++) { + ret = _omap_calculate_ecc_bch(mtd, dat, ecc_calc, i); + if (ret) + return ret; + + ecc_calc += eccbytes; + } + + return 0; +} + /* * omap_reverse_list - re-orders list elements in reverse order [internal] * @list: pointer to start of list @@ -626,52 +750,49 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; + int ecctotal = chip->ecc.total; int eccsteps = chip->ecc.steps; uint8_t *p = buf; uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; uint8_t *oob = chip->oob_poi; - uint32_t data_pos; uint32_t oob_pos;
- data_pos = 0; /* oob area start */ oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0]; oob += chip->ecc.layout->eccpos[0];
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize, - oob += eccbytes) { - chip->ecc.hwctl(mtd, NAND_ECC_READ); - /* read data */ - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, -1); - chip->read_buf(mtd, p, eccsize); - - /* read respective ecc from oob area */ - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1); - chip->read_buf(mtd, oob, eccbytes); - /* read syndrome */ - chip->ecc.calculate(mtd, p, &ecc_calc[i]); - - data_pos += eccsize; - oob_pos += eccbytes; - } + /* Enable ECC engine */ + chip->ecc.hwctl(mtd, NAND_ECC_READ); + + /* read entire page */ + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, -1); + chip->read_buf(mtd, buf, mtd->writesize); + + /* read all ecc bytes from oob area */ + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1); + chip->read_buf(mtd, oob, ecctotal); + + /* Calculate ecc bytes */ + omap_calculate_ecc_bch_multi(mtd, buf, ecc_calc);
for (i = 0; i < chip->ecc.total; i++) ecc_code[i] = chip->oob_poi[eccpos[i]];
+ /* error detect & correct */ eccsteps = chip->ecc.steps; p = buf;
for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; - stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); if (stat < 0) mtd->ecc_stats.failed++; else mtd->ecc_stats.corrected += stat; } + return 0; } #endif /* CONFIG_NAND_OMAP_ELM */ @@ -819,9 +940,9 @@ static int omap_select_ecc_scheme(struct nand_chip *nand, nand->ecc.strength = 8; nand->ecc.size = SECTOR_BYTES; nand->ecc.bytes = 13; - nand->ecc.hwctl = omap_enable_hwecc; + nand->ecc.hwctl = omap_enable_hwecc_bch; nand->ecc.correct = omap_correct_data_bch_sw; - nand->ecc.calculate = omap_calculate_ecc; + nand->ecc.calculate = omap_calculate_ecc_bch; /* define ecc-layout */ ecclayout->eccbytes = nand->ecc.bytes * eccsteps; ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; @@ -860,9 +981,9 @@ static int omap_select_ecc_scheme(struct nand_chip *nand, nand->ecc.strength = 8; nand->ecc.size = SECTOR_BYTES; nand->ecc.bytes = 14; - nand->ecc.hwctl = omap_enable_hwecc; + nand->ecc.hwctl = omap_enable_hwecc_bch; nand->ecc.correct = omap_correct_data_bch; - nand->ecc.calculate = omap_calculate_ecc; + nand->ecc.calculate = omap_calculate_ecc_bch; nand->ecc.read_page = omap_read_page_bch; /* define ecc-layout */ ecclayout->eccbytes = nand->ecc.bytes * eccsteps; @@ -893,9 +1014,9 @@ static int omap_select_ecc_scheme(struct nand_chip *nand, nand->ecc.size = SECTOR_BYTES; nand->ecc.bytes = 26; nand->ecc.strength = 16; - nand->ecc.hwctl = omap_enable_hwecc; + nand->ecc.hwctl = omap_enable_hwecc_bch; nand->ecc.correct = omap_correct_data_bch; - nand->ecc.calculate = omap_calculate_ecc; + nand->ecc.calculate = omap_calculate_ecc_bch; nand->ecc.read_page = omap_read_page_bch; /* define ecc-layout */ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;

Hi
On Tue, Dec 20, 2022 at 11:22 AM Roger Quadros rogerq@kernel.org wrote:
The BCH detection hardware can generate ECC bytes for multiple sectors in one go. Use that feature.
correct() only corrects one sector at a time so we need to call it repeatedly for each sector.
Signed-off-by: Roger Quadros rogerq@kernel.org Reviewed-by: Michael Trimarchi michael@amarulasolutions.com
drivers/mtd/nand/raw/omap_gpmc.c | 325 +++++++++++++++++++++---------- 1 file changed, 223 insertions(+), 102 deletions(-)
diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index 69fc09be097..e772a914c88 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -27,6 +27,9 @@
#define BADBLOCK_MARKER_LENGTH 2 #define SECTOR_BYTES 512 +#define ECCSIZE0_SHIFT 12 +#define ECCSIZE1_SHIFT 22 +#define ECC1RESULTSIZE 0x1 #define ECCCLEAR (0x1 << 8) #define ECCRESULTREG1 (0x1 << 0) /* 4 bit padding to make byte aligned, 56 = 52 + 4 */ @@ -186,72 +189,35 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat, __maybe_unused static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode) {
struct nand_chip *nand = mtd_to_nand(mtd);
struct omap_nand_info *info = nand_get_controller_data(nand);
struct nand_chip *nand = mtd_to_nand(mtd);
struct omap_nand_info *info = nand_get_controller_data(nand); unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
unsigned int ecc_algo = 0;
unsigned int bch_type = 0;
unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00;
u32 ecc_size_config_val = 0;
u32 ecc_config_val = 0;
int cs = info->cs;
u32 val;
/* configure GPMC for specific ecc-scheme */
switch (info->ecc_scheme) {
case OMAP_ECC_HAM1_CODE_SW:
return;
case OMAP_ECC_HAM1_CODE_HW:
ecc_algo = 0x0;
bch_type = 0x0;
bch_wrapmode = 0x00;
eccsize0 = 0xFF;
eccsize1 = 0xFF;
/* Clear ecc and enable bits */
writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
/* program ecc and result sizes */
val = ((((nand->ecc.size >> 1) - 1) << ECCSIZE1_SHIFT) |
ECC1RESULTSIZE);
writel(val, &gpmc_cfg->ecc_size_config);
switch (mode) {
case NAND_ECC_READ:
case NAND_ECC_WRITE:
writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control); break;
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
case OMAP_ECC_BCH8_CODE_HW:
ecc_algo = 0x1;
bch_type = 0x1;
if (mode == NAND_ECC_WRITE) {
bch_wrapmode = 0x01;
eccsize0 = 0; /* extra bits in nibbles per sector */
eccsize1 = 28; /* OOB bits in nibbles per sector */
} else {
bch_wrapmode = 0x01;
eccsize0 = 26; /* ECC bits in nibbles per sector */
eccsize1 = 2; /* non-ECC bits in nibbles per sector */
}
break;
case OMAP_ECC_BCH16_CODE_HW:
ecc_algo = 0x1;
bch_type = 0x2;
if (mode == NAND_ECC_WRITE) {
bch_wrapmode = 0x01;
eccsize0 = 0; /* extra bits in nibbles per sector */
eccsize1 = 52; /* OOB bits in nibbles per sector */
} else {
bch_wrapmode = 0x01;
eccsize0 = 52; /* ECC bits in nibbles per sector */
eccsize1 = 0; /* non-ECC bits in nibbles per sector */
}
case NAND_ECC_READSYN:
writel(ECCCLEAR, &gpmc_cfg->ecc_control); break; default:
return;
printf("%s: error: unrecognized Mode[%d]!\n", __func__, mode);
break; }
/* Clear ecc and enable bits */
writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
/* Configure ecc size for BCH */
ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12);
writel(ecc_size_config_val, &gpmc_cfg->ecc_size_config);
/* Configure device details for BCH engine */
ecc_config_val = ((ecc_algo << 16) | /* HAM1 | BCHx */
(bch_type << 12) | /* BCH4/BCH8/BCH16 */
(bch_wrapmode << 8) | /* wrap mode */
(dev_width << 7) | /* bus width */
(0x0 << 4) | /* number of sectors */
(cs << 1) | /* ECC CS */
(0x1)); /* enable ECC */
writel(ecc_config_val, &gpmc_cfg->ecc_config);
/* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
val = (dev_width << 7) | (info->cs << 1) | (0x1);
writel(val, &gpmc_cfg->ecc_config);
}
/* @@ -270,6 +236,124 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode) */ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code) +{
u32 val;
val = readl(&gpmc_cfg->ecc1_result);
ecc_code[0] = val & 0xFF;
ecc_code[1] = (val >> 16) & 0xFF;
ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
return 0;
+}
+/* GPMC ecc engine settings for read */ +#define BCH_WRAPMODE_1 1 /* BCH wrap mode 1 */ +#define BCH8R_ECC_SIZE0 0x1a /* ecc_size0 = 26 */ +#define BCH8R_ECC_SIZE1 0x2 /* ecc_size1 = 2 */ +#define BCH4R_ECC_SIZE0 0xd /* ecc_size0 = 13 */ +#define BCH4R_ECC_SIZE1 0x3 /* ecc_size1 = 3 */
+/* GPMC ecc engine settings for write */ +#define BCH_WRAPMODE_6 6 /* BCH wrap mode 6 */ +#define BCH_ECC_SIZE0 0x0 /* ecc_size0 = 0, no oob protection */ +#define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */
+/**
- omap_enable_hwecc_bch - Program GPMC to perform BCH ECC calculation
- @mtd: MTD device structure
- @mode: Read/Write mode
- When using BCH with SW correction (i.e. no ELM), sector size is set
- to 512 bytes and we use BCH_WRAPMODE_6 wrapping mode
- for both reading and writing with:
- eccsize0 = 0 (no additional protected byte in spare area)
- eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
- */
+static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd,
int mode)
+{
unsigned int bch_type;
unsigned int dev_width, nsectors;
struct nand_chip *chip = mtd_to_nand(mtd);
struct omap_nand_info *info = nand_get_controller_data(chip);
u32 val, wr_mode;
unsigned int ecc_size1, ecc_size0;
/* GPMC configurations for calculating ECC */
switch (info->ecc_scheme) {
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
bch_type = 1;
nsectors = 1;
wr_mode = BCH_WRAPMODE_6;
ecc_size0 = BCH_ECC_SIZE0;
ecc_size1 = BCH_ECC_SIZE1;
break;
case OMAP_ECC_BCH8_CODE_HW:
bch_type = 1;
nsectors = chip->ecc.steps;
if (mode == NAND_ECC_READ) {
wr_mode = BCH_WRAPMODE_1;
ecc_size0 = BCH8R_ECC_SIZE0;
ecc_size1 = BCH8R_ECC_SIZE1;
} else {
wr_mode = BCH_WRAPMODE_6;
ecc_size0 = BCH_ECC_SIZE0;
ecc_size1 = BCH_ECC_SIZE1;
}
break;
case OMAP_ECC_BCH16_CODE_HW:
bch_type = 0x2;
nsectors = chip->ecc.steps;
if (mode == NAND_ECC_READ) {
wr_mode = 0x01;
ecc_size0 = 52; /* ECC bits in nibbles per sector */
ecc_size1 = 0; /* non-ECC bits in nibbles per sector */
} else {
wr_mode = 0x01;
ecc_size0 = 0; /* extra bits in nibbles per sector */
ecc_size1 = 52; /* OOB bits in nibbles per sector */
}
break;
default:
return;
}
writel(ECCRESULTREG1, &gpmc_cfg->ecc_control);
/* Configure ecc size for BCH */
val = (ecc_size1 << ECCSIZE1_SHIFT) | (ecc_size0 << ECCSIZE0_SHIFT);
writel(val, &gpmc_cfg->ecc_size_config);
dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
/* BCH configuration */
val = ((1 << 16) | /* enable BCH */
(bch_type << 12) | /* BCH4/BCH8/BCH16 */
(wr_mode << 8) | /* wrap mode */
(dev_width << 7) | /* bus width */
(((nsectors - 1) & 0x7) << 4) | /* number of sectors */
(info->cs << 1) | /* ECC CS */
(0x1)); /* enable ECC */
writel(val, &gpmc_cfg->ecc_config);
/* Clear ecc and enable bits */
writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
+}
+/**
- _omap_calculate_ecc_bch - Generate BCH ECC bytes for one sector
- @mtd: MTD device structure
- @dat: The pointer to data on which ecc is computed
- @ecc_code: The ecc_code buffer
- @sector: The sector number (for a multi sector page)
- Support calculating of BCH4/8/16 ECC vectors for one sector
- within a page. Sector number is in @sector.
- */
+static int _omap_calculate_ecc_bch(struct mtd_info *mtd, const u8 *dat,
u8 *ecc_code, int sector)
{ struct nand_chip *chip = mtd_to_nand(mtd); struct omap_nand_info *info = nand_get_controller_data(chip); @@ -278,17 +362,11 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, int8_t i = 0, j;
switch (info->ecc_scheme) {
case OMAP_ECC_HAM1_CODE_HW:
val = readl(&gpmc_cfg->ecc1_result);
ecc_code[0] = val & 0xFF;
ecc_code[1] = (val >> 16) & 0xFF;
ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
break;
#ifdef CONFIG_BCH case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: #endif case OMAP_ECC_BCH8_CODE_HW:
ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
ptr = &gpmc_cfg->bch_result_0_3[sector].bch_result_x[3]; val = readl(ptr); ecc_code[i++] = (val >> 0) & 0xFF; ptr--;
@@ -300,23 +378,24 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, ecc_code[i++] = (val >> 0) & 0xFF; ptr--; }
break; case OMAP_ECC_BCH16_CODE_HW:
val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[2]);
val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[2]); ecc_code[i++] = (val >> 8) & 0xFF; ecc_code[i++] = (val >> 0) & 0xFF;
val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[1]);
val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[1]); ecc_code[i++] = (val >> 24) & 0xFF; ecc_code[i++] = (val >> 16) & 0xFF; ecc_code[i++] = (val >> 8) & 0xFF; ecc_code[i++] = (val >> 0) & 0xFF;
val = readl(&gpmc_cfg->bch_result_4_6[0].bch_result_x[0]);
val = readl(&gpmc_cfg->bch_result_4_6[sector].bch_result_x[0]); ecc_code[i++] = (val >> 24) & 0xFF; ecc_code[i++] = (val >> 16) & 0xFF; ecc_code[i++] = (val >> 8) & 0xFF; ecc_code[i++] = (val >> 0) & 0xFF; for (j = 3; j >= 0; j--) {
val = readl(&gpmc_cfg->bch_result_0_3[0].bch_result_x[j]
val = readl(&gpmc_cfg->bch_result_0_3[sector].bch_result_x[j] ); ecc_code[i++] = (val >> 24) & 0xFF; ecc_code[i++] = (val >> 16) & 0xFF;
@@ -329,18 +408,18 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, } /* ECC scheme specific syndrome customizations */ switch (info->ecc_scheme) {
case OMAP_ECC_HAM1_CODE_HW:
break;
#ifdef CONFIG_BCH case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
/* Add constant polynomial to remainder, so that
* ECC of blank pages results in 0x0 on reading back
*/ for (i = 0; i < chip->ecc.bytes; i++)
*(ecc_code + i) = *(ecc_code + i) ^
bch8_polynomial[i];
ecc_code[i] ^= bch8_polynomial[i]; break;
#endif case OMAP_ECC_BCH8_CODE_HW:
ecc_code[chip->ecc.bytes - 1] = 0x00;
/* Set 14th ECC byte as 0x0 for ROM compatibility */
ecc_code[chip->ecc.bytes - 1] = 0x0; break; case OMAP_ECC_BCH16_CODE_HW: break;
@@ -350,6 +429,22 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, return 0; }
+/**
- omap_calculate_ecc_bch - ECC generator for 1 sector
- @mtd: MTD device structure
- @dat: The pointer to data on which ecc is computed
- @ecc_code: The ecc_code buffer
- Support calculating of BCH4/8/16 ECC vectors for one sector. This is used
- when SW based correction is required as ECC is required for one sector
- at a time.
- */
+static int omap_calculate_ecc_bch(struct mtd_info *mtd,
const u_char *dat, u_char *ecc_calc)
-static int omap_calculate_ecc_bch(struct mtd_info *mtd, +static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, u_char *ecc_calc)
Acked-by: Michael Trimarchi michael@amarulasolutions.com
+{
return _omap_calculate_ecc_bch(mtd, dat, ecc_calc, 0);
+}
static inline void omap_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); @@ -474,6 +569,35 @@ static void omap_nand_read_prefetch(struct mtd_info *mtd, uint8_t *buf, int len) #endif /* CONFIG_NAND_OMAP_GPMC_PREFETCH */
#ifdef CONFIG_NAND_OMAP_ELM
+/**
- omap_calculate_ecc_bch_multi - Generate ECC for multiple sectors
- @mtd: MTD device structure
- @dat: The pointer to data on which ecc is computed
- @ecc_code: The ecc_code buffer
- Support calculating of BCH4/8/16 ecc vectors for the entire page in one go.
- */
+static int omap_calculate_ecc_bch_multi(struct mtd_info *mtd,
const u_char *dat, u_char *ecc_calc)
+{
struct nand_chip *chip = mtd_to_nand(mtd);
int eccbytes = chip->ecc.bytes;
unsigned long nsectors;
int i, ret;
nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
for (i = 0; i < nsectors; i++) {
ret = _omap_calculate_ecc_bch(mtd, dat, ecc_calc, i);
if (ret)
return ret;
ecc_calc += eccbytes;
}
return 0;
+}
/*
- omap_reverse_list - re-orders list elements in reverse order [internal]
- @list: pointer to start of list
@@ -626,52 +750,49 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes;
int ecctotal = chip->ecc.total; int eccsteps = chip->ecc.steps; uint8_t *p = buf; uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; uint8_t *oob = chip->oob_poi;
uint32_t data_pos; uint32_t oob_pos;
data_pos = 0; /* oob area start */ oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0]; oob += chip->ecc.layout->eccpos[0];
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
oob += eccbytes) {
chip->ecc.hwctl(mtd, NAND_ECC_READ);
/* read data */
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, -1);
chip->read_buf(mtd, p, eccsize);
/* read respective ecc from oob area */
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
chip->read_buf(mtd, oob, eccbytes);
/* read syndrome */
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
data_pos += eccsize;
oob_pos += eccbytes;
}
/* Enable ECC engine */
chip->ecc.hwctl(mtd, NAND_ECC_READ);
/* read entire page */
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, -1);
chip->read_buf(mtd, buf, mtd->writesize);
/* read all ecc bytes from oob area */
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
chip->read_buf(mtd, oob, ecctotal);
/* Calculate ecc bytes */
omap_calculate_ecc_bch_multi(mtd, buf, ecc_calc); for (i = 0; i < chip->ecc.total; i++) ecc_code[i] = chip->oob_poi[eccpos[i]];
/* error detect & correct */ eccsteps = chip->ecc.steps; p = buf; for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat;
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); if (stat < 0) mtd->ecc_stats.failed++; else mtd->ecc_stats.corrected += stat; }
return 0;
} #endif /* CONFIG_NAND_OMAP_ELM */ @@ -819,9 +940,9 @@ static int omap_select_ecc_scheme(struct nand_chip *nand, nand->ecc.strength = 8; nand->ecc.size = SECTOR_BYTES; nand->ecc.bytes = 13;
nand->ecc.hwctl = omap_enable_hwecc;
nand->ecc.hwctl = omap_enable_hwecc_bch; nand->ecc.correct = omap_correct_data_bch_sw;
nand->ecc.calculate = omap_calculate_ecc;
nand->ecc.calculate = omap_calculate_ecc_bch; /* define ecc-layout */ ecclayout->eccbytes = nand->ecc.bytes * eccsteps; ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
@@ -860,9 +981,9 @@ static int omap_select_ecc_scheme(struct nand_chip *nand, nand->ecc.strength = 8; nand->ecc.size = SECTOR_BYTES; nand->ecc.bytes = 14;
nand->ecc.hwctl = omap_enable_hwecc;
nand->ecc.hwctl = omap_enable_hwecc_bch; nand->ecc.correct = omap_correct_data_bch;
nand->ecc.calculate = omap_calculate_ecc;
nand->ecc.calculate = omap_calculate_ecc_bch; nand->ecc.read_page = omap_read_page_bch; /* define ecc-layout */ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
@@ -893,9 +1014,9 @@ static int omap_select_ecc_scheme(struct nand_chip *nand, nand->ecc.size = SECTOR_BYTES; nand->ecc.bytes = 26; nand->ecc.strength = 16;
nand->ecc.hwctl = omap_enable_hwecc;
nand->ecc.hwctl = omap_enable_hwecc_bch; nand->ecc.correct = omap_correct_data_bch;
nand->ecc.calculate = omap_calculate_ecc;
nand->ecc.calculate = omap_calculate_ecc_bch; nand->ecc.read_page = omap_read_page_bch; /* define ecc-layout */ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
-- 2.34.1

nand_bbt.c is not being built with the nand_base driver during SPL build. This results in build failures if we try to access any nand_bbt related functions.
Don't use any nand_bbt functions for SPL build.
Signed-off-by: Roger Quadros rogerq@kernel.org --- drivers/mtd/nand/raw/nand_base.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index bc61ad03eb0..9eba360d55f 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -447,7 +447,10 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) { struct nand_chip *chip = mtd_to_nand(mtd); - int res, ret = 0; + int ret = 0; +#ifndef CONFIG_SPL_BUILD + int res; +#endif
if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) { struct erase_info einfo; @@ -465,12 +468,14 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) nand_release_device(mtd); }
+#ifndef CONFIG_SPL_BUILD /* Mark block bad in BBT */ if (chip->bbt) { res = nand_markbad_bbt(mtd, ofs); if (!ret) ret = res; } +#endif
if (!ret) mtd->ecc_stats.badblocks++; @@ -517,7 +522,11 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs) if (!chip->bbt) return 0; /* Return info from the table */ +#ifndef CONFIG_SPL_BUILD return nand_isreserved_bbt(mtd, ofs); +#else + return 0; +#endif }
/** @@ -543,7 +552,11 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt) return chip->block_bad(mtd, ofs);
/* Return info from the table */ +#ifndef CONFIG_SPL_BUILD return nand_isbad_bbt(mtd, ofs, allowbbt); +#else + return 0; +#endif }
/** @@ -3752,8 +3765,11 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->write_byte = busw ? nand_write_byte16 : nand_write_byte; if (!chip->read_buf || chip->read_buf == nand_read_buf) chip->read_buf = busw ? nand_read_buf16 : nand_read_buf; + +#ifndef CONFIG_SPL_BUILD if (!chip->scan_bbt) chip->scan_bbt = nand_default_bbt; +#endif
if (!chip->controller) { chip->controller = &chip->hwcontrol;

Add DT binding documentation for the TI GPMC NAND controller. This is picked up from the Linux Kernel.
Signed-off-by: Roger Quadros rogerq@kernel.org --- .../mtd/ti,gpmc-nand.yaml | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 doc/device-tree-bindings/mtd/ti,gpmc-nand.yaml
diff --git a/doc/device-tree-bindings/mtd/ti,gpmc-nand.yaml b/doc/device-tree-bindings/mtd/ti,gpmc-nand.yaml new file mode 100644 index 00000000000..4ac198814b7 --- /dev/null +++ b/doc/device-tree-bindings/mtd/ti,gpmc-nand.yaml @@ -0,0 +1,129 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mtd/ti,gpmc-nand.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments GPMC NAND Flash controller. + +maintainers: + - Tony Lindgren tony@atomide.com + - Roger Quadros rogerq@kernel.org + +description: + GPMC NAND controller/Flash is represented as a child of the + GPMC controller node. + +properties: + compatible: + items: + - enum: + - ti,am64-nand + - ti,omap2-nand + + reg: + maxItems: 1 + + interrupts: + items: + - description: Interrupt for fifoevent + - description: Interrupt for termcount + + "#address-cells": true + + "#size-cells": true + + ti,nand-ecc-opt: + description: Desired ECC algorithm + $ref: /schemas/types.yaml#/definitions/string + enum: [sw, ham1, bch4, bch8, bch16] + + ti,nand-xfer-type: + description: Data transfer method between controller and chip. + $ref: /schemas/types.yaml#/definitions/string + enum: [prefetch-polled, polled, prefetch-dma, prefetch-irq] + default: prefetch-polled + + ti,elm-id: + description: + phandle to the ELM (Error Location Module). + $ref: /schemas/types.yaml#/definitions/phandle + + nand-bus-width: + description: + Bus width to the NAND chip + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [8, 16] + default: 8 + + rb-gpios: + description: + GPIO connection to R/B signal from NAND chip + maxItems: 1 + +patternProperties: + "@[0-9a-f]+$": + $ref: "/schemas/mtd/partitions/partition.yaml" + +allOf: + - $ref: "/schemas/memory-controllers/ti,gpmc-child.yaml" + +required: + - compatible + - reg + - ti,nand-ecc-opt + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/gpio/gpio.h> + + gpmc: memory-controller@50000000 { + compatible = "ti,am3352-gpmc"; + dmas = <&edma 52 0>; + dma-names = "rxtx"; + clocks = <&l3s_gclk>; + clock-names = "fck"; + reg = <0x50000000 0x2000>; + interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; + gpmc,num-cs = <7>; + gpmc,num-waitpins = <2>; + #address-cells = <2>; + #size-cells = <1>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; + + ranges = <0 0 0x08000000 0x01000000>; /* CS0 space. Min partition = 16MB */ + nand@0,0 { + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* device IO registers */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ + ti,nand-xfer-type = "prefetch-dma"; + ti,nand-ecc-opt = "bch16"; + ti,elm-id = <&elm>; + #address-cells = <1>; + #size-cells = <1>; + + /* NAND generic properties */ + nand-bus-width = <8>; + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ + + /* GPMC properties*/ + gpmc,device-width = <1>; + + partition@0 { + label = "NAND.SPL"; + reg = <0x00000000 0x00040000>; + }; + partition@1 { + label = "NAND.SPL.backup1"; + reg = <0x00040000 0x00040000>; + }; + }; + };

Adds driver model support.
We need to be able to self initialize the NAND controller/chip at probe and so enable CONFIG_SYS_NAND_SELF_INIT.
Doing so requires nand_register() API which is provided by nand.c and needs to be enabled during SPL build via CONFIG_SPL_NAND_INIT. But nand.c also provides nand_init() so we need to get rid of nand_init() in omap_gpmc driver if CONFIG_SPL_NAND_INIT is set.
Signed-off-by: Roger Quadros rogerq@kernel.org --- drivers/mtd/nand/raw/Kconfig | 1 + drivers/mtd/nand/raw/omap_gpmc.c | 64 +++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 8aaba8b1a2c..3f4851b93bd 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -198,6 +198,7 @@ config NAND_LPC32XX_SLC config NAND_OMAP_GPMC bool "Support OMAP GPMC NAND controller" depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || ARCH_K3 + select SYS_NAND_SELF_INIT if ARCH_K3 help Enables omap_gpmc.c driver for OMAPx and AMxxxx platforms. GPMC controller is used for parallel NAND flash devices, and can diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index e772a914c88..61e025db9a5 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -7,6 +7,7 @@ #include <common.h> #include <log.h> #include <asm/io.h> +#include <dm/uclass.h> #include <linux/errno.h>
#ifdef CONFIG_ARCH_OMAP2PLUS @@ -1121,7 +1122,7 @@ int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength) * nand_scan about special functionality. See the defines for further * explanation */ -int board_nand_init(struct nand_chip *nand) +int gpmc_nand_init(struct nand_chip *nand) { int32_t gpmc_config = 0; int cs = cs_next++; @@ -1201,3 +1202,64 @@ int board_nand_init(struct nand_chip *nand)
return 0; } + +/* First NAND chip for SPL use only */ +static __maybe_unused struct nand_chip *nand_chip; + +#if CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT) + +static int gpmc_nand_probe(struct udevice *dev) +{ + struct nand_chip *nand = dev_get_priv(dev); + struct mtd_info *mtd = nand_to_mtd(nand); + int ret; + + gpmc_nand_init(nand); + + ret = nand_scan(mtd, CONFIG_SYS_NAND_MAX_CHIPS); + if (ret) + return ret; + + ret = nand_register(0, mtd); + if (ret) + return ret; + + if (!nand_chip) + nand_chip = nand; + + return 0; +} + +static const struct udevice_id gpmc_nand_ids[] = { + { .compatible = "ti,am64-nand" }, + { .compatible = "ti,omap2-nand" }, + { } +}; + +U_BOOT_DRIVER(gpmc_nand) = { + .name = "gpmc-nand", + .id = UCLASS_MTD, + .of_match = gpmc_nand_ids, + .probe = gpmc_nand_probe, + .priv_auto = sizeof(struct nand_chip), +}; + +void board_nand_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_DRIVER_GET(gpmc_nand), &dev); + if (ret && ret != -ENODEV) + pr_err("%s: Failed to get GPMC device: %d\n", __func__, ret); +} + +#else + +int board_nand_init(struct nand_chip *nand) +{ + return gpmc_nand_init(nand); +} + +#endif /* CONFIG_SYS_NAND_SELF_INIT */

Enables SPL NAND support for ARCH_K3 by enabling SPL_NAND_INIT and SPL_SYS_NAND_SELF_INIT.
Legacy OMAP2plus platforms still rely on SPL_NAND_AM33XX_BCH instead.
Signed-off-by: Roger Quadros rogerq@kernel.org --- drivers/mtd/nand/raw/Kconfig | 5 ++++ drivers/mtd/nand/raw/Makefile | 2 +- drivers/mtd/nand/raw/omap_gpmc.c | 40 ++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 3f4851b93bd..e53c9284a0d 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -26,6 +26,9 @@ config TPL_SYS_NAND_SELF_INIT config TPL_NAND_INIT bool
+config SPL_NAND_INIT + bool + config SYS_MAX_NAND_DEVICE int "Maximum number of NAND devices to support" default 1 @@ -199,6 +202,8 @@ config NAND_OMAP_GPMC bool "Support OMAP GPMC NAND controller" depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || ARCH_K3 select SYS_NAND_SELF_INIT if ARCH_K3 + select SPL_NAND_INIT if ARCH_K3 + select SPL_SYS_NAND_SELF_INIT if ARCH_K3 help Enables omap_gpmc.c driver for OMAPx and AMxxxx platforms. GPMC controller is used for parallel NAND flash devices, and can diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index a398aa9d886..6fe33d2485b 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o nand_amd.o nand_hynix.o \ nand_macronix.o nand_micron.o \ nand_samsung.o nand_toshiba.o obj-$(CONFIG_SPL_NAND_IDENT) += nand_ids.o nand_timings.o -obj-$(CONFIG_TPL_NAND_INIT) += nand.o +obj-$(CONFIG_$(SPL_TPL_)NAND_INIT) += nand.o ifeq ($(CONFIG_SPL_ENV_SUPPORT),y) obj-$(CONFIG_ENV_IS_IN_NAND) += nand_util.o endif diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index 61e025db9a5..ed6cdf93ad0 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -1263,3 +1263,43 @@ int board_nand_init(struct nand_chip *nand) }
#endif /* CONFIG_SYS_NAND_SELF_INIT */ + +#if defined(CONFIG_SPL_NAND_INIT) + +/* nand_init() is provided by nand.c */ + +/* Unselect after operation */ +void nand_deselect(void) +{ + struct mtd_info *mtd = nand_to_mtd(nand_chip); + + if (nand_chip->select_chip) + nand_chip->select_chip(mtd, -1); +} + +static int nand_is_bad_block(int block) +{ + struct mtd_info *mtd = nand_to_mtd(nand_chip); + + loff_t ofs = block * CONFIG_SYS_NAND_BLOCK_SIZE; + + return nand_chip->block_bad(mtd, ofs); +} + +static int nand_read_page(int block, int page, uchar *dst) +{ + int page_addr = block * CONFIG_SYS_NAND_PAGE_COUNT + page; + loff_t ofs = page_addr * CONFIG_SYS_NAND_PAGE_SIZE; + int ret; + size_t len = CONFIG_SYS_NAND_PAGE_SIZE; + struct mtd_info *mtd = nand_to_mtd(nand_chip); + + ret = nand_read(mtd, ofs, &len, dst); + if (ret) + printf("nand_read failed %d\n", ret); + + return ret; +} + +#include "nand_spl_loaders.c" +#endif /* CONFIG_SPL_NAND_INIT */

The symbol is required for NAND support in SPL when using OMAP_GPMC driver.
Signed-off-by: Roger Quadros rogerq@kernel.org --- drivers/mtd/nand/raw/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index e53c9284a0d..458b5faeb65 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -574,7 +574,8 @@ config SYS_NAND_ONFI_DETECTION config SYS_NAND_PAGE_COUNT hex "NAND chip page count" depends on SPL_NAND_SUPPORT && (NAND_ATMEL || NAND_MXC || \ - SPL_NAND_AM33XX_BCH || SPL_NAND_LOAD || SPL_NAND_SIMPLE) + SPL_NAND_AM33XX_BCH || SPL_NAND_LOAD || SPL_NAND_SIMPLE || \ + NAND_OMAP_GPMC) help Number of pages in the NAND chip.

Adds DT binding documentation for the TI Error Location Module. This is picked up from the Linux Kernel.
Signed-off-by: Roger Quadros rogerq@kernel.org --- doc/device-tree-bindings/mtd/ti,elm.yaml | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 doc/device-tree-bindings/mtd/ti,elm.yaml
diff --git a/doc/device-tree-bindings/mtd/ti,elm.yaml b/doc/device-tree-bindings/mtd/ti,elm.yaml new file mode 100644 index 00000000000..87128c00459 --- /dev/null +++ b/doc/device-tree-bindings/mtd/ti,elm.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mtd/ti,elm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments Error Location Module (ELM). + +maintainers: + - Roger Quadros rogerq@kernel.org + +description: + ELM module is used together with GPMC and NAND Flash to detect + errors and the location of the error based on BCH algorithms + so they can be corrected if possible. + +properties: + compatible: + enum: + - ti,am3352-elm + - ti,am64-elm + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + description: Functional clock. + + clock-names: + items: + - const: fck + + power-domains: + maxItems: 1 + + ti,hwmods: + description: + Name of the HWMOD associated with ELM. This is for legacy + platforms only. + $ref: /schemas/types.yaml#/definitions/string + deprecated: true + +required: + - compatible + - reg + - interrupts + +allOf: + - if: + properties: + compatible: + contains: + const: ti,am64-elm + then: + required: + - clocks + - clock-names + - power-domains + +additionalProperties: false + +examples: + - | + elm: ecc@0 { + compatible = "ti,am3352-elm"; + reg = <0x0 0x2000>; + interrupts = <4>; + };

Support u-boot driver model. We still retain support legacy way of doing things if ELM_BASE is defined in <asm/arch/hardware.h>
We could completely get rid of that if all platforms defining ELM_BASE get rid of that definition and enable CONFIG_SYS_NAND_SELF_INIT and are verified to work.
Signed-off-by: Roger Quadros rogerq@kernel.org --- drivers/mtd/nand/raw/omap_elm.c | 35 ++++++++++++++++++- .../mtd => drivers/mtd/nand/raw}/omap_elm.h | 6 ++++ drivers/mtd/nand/raw/omap_gpmc.c | 12 ++++++- 3 files changed, 51 insertions(+), 2 deletions(-) rename {include/linux/mtd => drivers/mtd/nand/raw}/omap_elm.h (97%)
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 35c6dd1f1bc..e528a5348d5 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -15,9 +15,14 @@ #include <common.h> #include <asm/io.h> #include <linux/errno.h> -#include <linux/mtd/omap_elm.h> #include <asm/arch/hardware.h>
+#include <dm.h> +#include <linux/ioport.h> +#include <linux/io.h> + +#include "omap_elm.h" + #define DRIVER_NAME "omap-elm" #define ELM_DEFAULT_POLY (0)
@@ -180,6 +185,7 @@ void elm_reset(void) ; }
+#ifdef ELM_BASE /** * elm_init - Initialize ELM module * @@ -191,3 +197,30 @@ void elm_init(void) elm_cfg = (struct elm *)ELM_BASE; elm_reset(); } +#endif + +static int elm_probe(struct udevice *dev) +{ +#ifndef ELM_BASE + struct resource res; + + dev_read_resource(dev, 0, &res); + elm_cfg = devm_ioremap(dev, res.start, resource_size(&res)); + elm_reset(); +#endif + + return 0; +} + +static const struct udevice_id elm_ids[] = { + { .compatible = "ti,am3352-elm" }, + { .compatible = "ti,am64-elm" }, + { } +}; + +U_BOOT_DRIVER(gpmc_elm) = { + .name = DRIVER_NAME, + .id = UCLASS_MTD, + .of_match = elm_ids, + .probe = elm_probe, +}; diff --git a/include/linux/mtd/omap_elm.h b/drivers/mtd/nand/raw/omap_elm.h similarity index 97% rename from include/linux/mtd/omap_elm.h rename to drivers/mtd/nand/raw/omap_elm.h index f3db00d55de..a7f7bacb154 100644 --- a/include/linux/mtd/omap_elm.h +++ b/drivers/mtd/nand/raw/omap_elm.h @@ -74,6 +74,12 @@ int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count, u32 *error_locations); int elm_config(enum bch_level level); void elm_reset(void); +#ifdef ELM_BASE void elm_init(void); +#else +static inline void elm_init(void) +{ +} +#endif #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_ELM_H */ diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index ed6cdf93ad0..9692b78da3c 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -20,7 +20,8 @@ #include <linux/bch.h> #include <linux/compiler.h> #include <nand.h> -#include <linux/mtd/omap_elm.h> + +#include "omap_elm.h"
#ifndef GPMC_MAX_CS #define GPMC_MAX_CS 4 @@ -1249,6 +1250,15 @@ void board_nand_init(void) struct udevice *dev; int ret;
+#ifdef CONFIG_NAND_OMAP_ELM + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_DRIVER_GET(gpmc_elm), &dev); + if (ret && ret != -ENODEV) { + pr_err("%s: Failed to get ELM device: %d\n", __func__, ret); + return; + } +#endif + ret = uclass_get_device_by_driver(UCLASS_MTD, DM_DRIVER_GET(gpmc_nand), &dev); if (ret && ret != -ENODEV)

Hi Roger
On Tue, Dec 20, 2022 at 11:22 AM Roger Quadros rogerq@kernel.org wrote:
Support u-boot driver model. We still retain support legacy way of doing things if ELM_BASE is defined in <asm/arch/hardware.h>
We could completely get rid of that if all platforms defining ELM_BASE get rid of that definition and enable CONFIG_SYS_NAND_SELF_INIT and are verified to work.
Signed-off-by: Roger Quadros rogerq@kernel.org
When you post please include the relative changelog
Michael
drivers/mtd/nand/raw/omap_elm.c | 35 ++++++++++++++++++- .../mtd => drivers/mtd/nand/raw}/omap_elm.h | 6 ++++ drivers/mtd/nand/raw/omap_gpmc.c | 12 ++++++- 3 files changed, 51 insertions(+), 2 deletions(-) rename {include/linux/mtd => drivers/mtd/nand/raw}/omap_elm.h (97%)
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 35c6dd1f1bc..e528a5348d5 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -15,9 +15,14 @@ #include <common.h> #include <asm/io.h> #include <linux/errno.h> -#include <linux/mtd/omap_elm.h> #include <asm/arch/hardware.h>
+#include <dm.h> +#include <linux/ioport.h> +#include <linux/io.h>
+#include "omap_elm.h"
#define DRIVER_NAME "omap-elm" #define ELM_DEFAULT_POLY (0)
@@ -180,6 +185,7 @@ void elm_reset(void) ; }
+#ifdef ELM_BASE /**
- elm_init - Initialize ELM module
@@ -191,3 +197,30 @@ void elm_init(void) elm_cfg = (struct elm *)ELM_BASE; elm_reset(); } +#endif
+static int elm_probe(struct udevice *dev) +{ +#ifndef ELM_BASE
struct resource res;
dev_read_resource(dev, 0, &res);
elm_cfg = devm_ioremap(dev, res.start, resource_size(&res));
elm_reset();
+#endif
return 0;
+}
+static const struct udevice_id elm_ids[] = {
{ .compatible = "ti,am3352-elm" },
{ .compatible = "ti,am64-elm" },
{ }
+};
+U_BOOT_DRIVER(gpmc_elm) = {
.name = DRIVER_NAME,
.id = UCLASS_MTD,
.of_match = elm_ids,
.probe = elm_probe,
+}; diff --git a/include/linux/mtd/omap_elm.h b/drivers/mtd/nand/raw/omap_elm.h similarity index 97% rename from include/linux/mtd/omap_elm.h rename to drivers/mtd/nand/raw/omap_elm.h index f3db00d55de..a7f7bacb154 100644 --- a/include/linux/mtd/omap_elm.h +++ b/drivers/mtd/nand/raw/omap_elm.h @@ -74,6 +74,12 @@ int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count, u32 *error_locations); int elm_config(enum bch_level level); void elm_reset(void); +#ifdef ELM_BASE void elm_init(void); +#else +static inline void elm_init(void) +{ +} +#endif #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_ELM_H */ diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index ed6cdf93ad0..9692b78da3c 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -20,7 +20,8 @@ #include <linux/bch.h> #include <linux/compiler.h> #include <nand.h> -#include <linux/mtd/omap_elm.h>
+#include "omap_elm.h"
#ifndef GPMC_MAX_CS #define GPMC_MAX_CS 4 @@ -1249,6 +1250,15 @@ void board_nand_init(void) struct udevice *dev; int ret;
+#ifdef CONFIG_NAND_OMAP_ELM
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_DRIVER_GET(gpmc_elm), &dev);
if (ret && ret != -ENODEV) {
pr_err("%s: Failed to get ELM device: %d\n", __func__, ret);
return;
}
+#endif
ret = uclass_get_device_by_driver(UCLASS_MTD, DM_DRIVER_GET(gpmc_nand), &dev); if (ret && ret != -ENODEV)
-- 2.34.1

Hi Michael,
On 21/12/2022 19:56, Michael Nazzareno Trimarchi wrote:
Hi Roger
On Tue, Dec 20, 2022 at 11:22 AM Roger Quadros rogerq@kernel.org wrote:
Support u-boot driver model. We still retain support legacy way of doing things if ELM_BASE is defined in <asm/arch/hardware.h>
We could completely get rid of that if all platforms defining ELM_BASE get rid of that definition and enable CONFIG_SYS_NAND_SELF_INIT and are verified to work.
Signed-off-by: Roger Quadros rogerq@kernel.org
When you post please include the relative changelog
I put the changelog in the cover-letter.
cheers, -roger
Michael
drivers/mtd/nand/raw/omap_elm.c | 35 ++++++++++++++++++- .../mtd => drivers/mtd/nand/raw}/omap_elm.h | 6 ++++ drivers/mtd/nand/raw/omap_gpmc.c | 12 ++++++- 3 files changed, 51 insertions(+), 2 deletions(-) rename {include/linux/mtd => drivers/mtd/nand/raw}/omap_elm.h (97%)
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 35c6dd1f1bc..e528a5348d5 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -15,9 +15,14 @@ #include <common.h> #include <asm/io.h> #include <linux/errno.h> -#include <linux/mtd/omap_elm.h> #include <asm/arch/hardware.h>
+#include <dm.h> +#include <linux/ioport.h> +#include <linux/io.h>
+#include "omap_elm.h"
#define DRIVER_NAME "omap-elm" #define ELM_DEFAULT_POLY (0)
@@ -180,6 +185,7 @@ void elm_reset(void) ; }
+#ifdef ELM_BASE /**
- elm_init - Initialize ELM module
@@ -191,3 +197,30 @@ void elm_init(void) elm_cfg = (struct elm *)ELM_BASE; elm_reset(); } +#endif
+static int elm_probe(struct udevice *dev) +{ +#ifndef ELM_BASE
struct resource res;
dev_read_resource(dev, 0, &res);
elm_cfg = devm_ioremap(dev, res.start, resource_size(&res));
elm_reset();
+#endif
return 0;
+}
+static const struct udevice_id elm_ids[] = {
{ .compatible = "ti,am3352-elm" },
{ .compatible = "ti,am64-elm" },
{ }
+};
+U_BOOT_DRIVER(gpmc_elm) = {
.name = DRIVER_NAME,
.id = UCLASS_MTD,
.of_match = elm_ids,
.probe = elm_probe,
+}; diff --git a/include/linux/mtd/omap_elm.h b/drivers/mtd/nand/raw/omap_elm.h similarity index 97% rename from include/linux/mtd/omap_elm.h rename to drivers/mtd/nand/raw/omap_elm.h index f3db00d55de..a7f7bacb154 100644 --- a/include/linux/mtd/omap_elm.h +++ b/drivers/mtd/nand/raw/omap_elm.h @@ -74,6 +74,12 @@ int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count, u32 *error_locations); int elm_config(enum bch_level level); void elm_reset(void); +#ifdef ELM_BASE void elm_init(void); +#else +static inline void elm_init(void) +{ +} +#endif #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_ELM_H */ diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index ed6cdf93ad0..9692b78da3c 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -20,7 +20,8 @@ #include <linux/bch.h> #include <linux/compiler.h> #include <nand.h> -#include <linux/mtd/omap_elm.h>
+#include "omap_elm.h"
#ifndef GPMC_MAX_CS #define GPMC_MAX_CS 4 @@ -1249,6 +1250,15 @@ void board_nand_init(void) struct udevice *dev; int ret;
+#ifdef CONFIG_NAND_OMAP_ELM
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_DRIVER_GET(gpmc_elm), &dev);
if (ret && ret != -ENODEV) {
pr_err("%s: Failed to get ELM device: %d\n", __func__, ret);
return;
}
+#endif
ret = uclass_get_device_by_driver(UCLASS_MTD, DM_DRIVER_GET(gpmc_nand), &dev); if (ret && ret != -ENODEV)
-- 2.34.1

Hi
On Wed, Dec 21, 2022 at 8:57 PM Roger Quadros rogerq@kernel.org wrote:
Hi Michael,
On 21/12/2022 19:56, Michael Nazzareno Trimarchi wrote:
Hi Roger
On Tue, Dec 20, 2022 at 11:22 AM Roger Quadros rogerq@kernel.org wrote:
Support u-boot driver model. We still retain support legacy way of doing things if ELM_BASE is defined in <asm/arch/hardware.h>
We could completely get rid of that if all platforms defining ELM_BASE get rid of that definition and enable CONFIG_SYS_NAND_SELF_INIT and are verified to work.
Signed-off-by: Roger Quadros rogerq@kernel.org
When you post please include the relative changelog
I put the changelog in the cover-letter.
My bad, I'm always start from patch 1 and look on changes in every single patch
Michael
cheers, -roger
Michael
drivers/mtd/nand/raw/omap_elm.c | 35 ++++++++++++++++++- .../mtd => drivers/mtd/nand/raw}/omap_elm.h | 6 ++++ drivers/mtd/nand/raw/omap_gpmc.c | 12 ++++++- 3 files changed, 51 insertions(+), 2 deletions(-) rename {include/linux/mtd => drivers/mtd/nand/raw}/omap_elm.h (97%)
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 35c6dd1f1bc..e528a5348d5 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -15,9 +15,14 @@ #include <common.h> #include <asm/io.h> #include <linux/errno.h> -#include <linux/mtd/omap_elm.h> #include <asm/arch/hardware.h>
+#include <dm.h> +#include <linux/ioport.h> +#include <linux/io.h>
+#include "omap_elm.h"
#define DRIVER_NAME "omap-elm" #define ELM_DEFAULT_POLY (0)
@@ -180,6 +185,7 @@ void elm_reset(void) ; }
+#ifdef ELM_BASE /**
- elm_init - Initialize ELM module
@@ -191,3 +197,30 @@ void elm_init(void) elm_cfg = (struct elm *)ELM_BASE; elm_reset(); } +#endif
+static int elm_probe(struct udevice *dev) +{ +#ifndef ELM_BASE
struct resource res;
dev_read_resource(dev, 0, &res);
elm_cfg = devm_ioremap(dev, res.start, resource_size(&res));
elm_reset();
+#endif
return 0;
+}
+static const struct udevice_id elm_ids[] = {
{ .compatible = "ti,am3352-elm" },
{ .compatible = "ti,am64-elm" },
{ }
+};
+U_BOOT_DRIVER(gpmc_elm) = {
.name = DRIVER_NAME,
.id = UCLASS_MTD,
.of_match = elm_ids,
.probe = elm_probe,
+}; diff --git a/include/linux/mtd/omap_elm.h b/drivers/mtd/nand/raw/omap_elm.h similarity index 97% rename from include/linux/mtd/omap_elm.h rename to drivers/mtd/nand/raw/omap_elm.h index f3db00d55de..a7f7bacb154 100644 --- a/include/linux/mtd/omap_elm.h +++ b/drivers/mtd/nand/raw/omap_elm.h @@ -74,6 +74,12 @@ int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count, u32 *error_locations); int elm_config(enum bch_level level); void elm_reset(void); +#ifdef ELM_BASE void elm_init(void); +#else +static inline void elm_init(void) +{ +} +#endif #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_ELM_H */ diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index ed6cdf93ad0..9692b78da3c 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -20,7 +20,8 @@ #include <linux/bch.h> #include <linux/compiler.h> #include <nand.h> -#include <linux/mtd/omap_elm.h>
+#include "omap_elm.h"
#ifndef GPMC_MAX_CS #define GPMC_MAX_CS 4 @@ -1249,6 +1250,15 @@ void board_nand_init(void) struct udevice *dev; int ret;
+#ifdef CONFIG_NAND_OMAP_ELM
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_DRIVER_GET(gpmc_elm), &dev);
if (ret && ret != -ENODEV) {
pr_err("%s: Failed to get ELM device: %d\n", __func__, ret);
return;
}
+#endif
ret = uclass_get_device_by_driver(UCLASS_MTD, DM_DRIVER_GET(gpmc_nand), &dev); if (ret && ret != -ENODEV)
-- 2.34.1

Hi Roger
On Wed, Dec 21, 2022 at 9:08 PM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi
On Wed, Dec 21, 2022 at 8:57 PM Roger Quadros rogerq@kernel.org wrote:
Hi Michael,
On 21/12/2022 19:56, Michael Nazzareno Trimarchi wrote:
Hi Roger
On Tue, Dec 20, 2022 at 11:22 AM Roger Quadros rogerq@kernel.org wrote:
Support u-boot driver model. We still retain support legacy way of doing things if ELM_BASE is defined in <asm/arch/hardware.h>
We could completely get rid of that if all platforms defining ELM_BASE get rid of that definition and enable CONFIG_SYS_NAND_SELF_INIT and are verified to work.
Signed-off-by: Roger Quadros rogerq@kernel.org
When you post please include the relative changelog
I put the changelog in the cover-letter.
My bad, I'm always start from patch 1 and look on changes in every single patch
Pipeline is running, I have fixed another minor problem in the build
Michael
Michael
cheers, -roger
Michael
drivers/mtd/nand/raw/omap_elm.c | 35 ++++++++++++++++++- .../mtd => drivers/mtd/nand/raw}/omap_elm.h | 6 ++++ drivers/mtd/nand/raw/omap_gpmc.c | 12 ++++++- 3 files changed, 51 insertions(+), 2 deletions(-) rename {include/linux/mtd => drivers/mtd/nand/raw}/omap_elm.h (97%)
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 35c6dd1f1bc..e528a5348d5 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -15,9 +15,14 @@ #include <common.h> #include <asm/io.h> #include <linux/errno.h> -#include <linux/mtd/omap_elm.h> #include <asm/arch/hardware.h>
+#include <dm.h> +#include <linux/ioport.h> +#include <linux/io.h>
+#include "omap_elm.h"
#define DRIVER_NAME "omap-elm" #define ELM_DEFAULT_POLY (0)
@@ -180,6 +185,7 @@ void elm_reset(void) ; }
+#ifdef ELM_BASE /**
- elm_init - Initialize ELM module
@@ -191,3 +197,30 @@ void elm_init(void) elm_cfg = (struct elm *)ELM_BASE; elm_reset(); } +#endif
+static int elm_probe(struct udevice *dev) +{ +#ifndef ELM_BASE
struct resource res;
dev_read_resource(dev, 0, &res);
elm_cfg = devm_ioremap(dev, res.start, resource_size(&res));
elm_reset();
+#endif
return 0;
+}
+static const struct udevice_id elm_ids[] = {
{ .compatible = "ti,am3352-elm" },
{ .compatible = "ti,am64-elm" },
{ }
+};
+U_BOOT_DRIVER(gpmc_elm) = {
.name = DRIVER_NAME,
.id = UCLASS_MTD,
.of_match = elm_ids,
.probe = elm_probe,
+}; diff --git a/include/linux/mtd/omap_elm.h b/drivers/mtd/nand/raw/omap_elm.h similarity index 97% rename from include/linux/mtd/omap_elm.h rename to drivers/mtd/nand/raw/omap_elm.h index f3db00d55de..a7f7bacb154 100644 --- a/include/linux/mtd/omap_elm.h +++ b/drivers/mtd/nand/raw/omap_elm.h @@ -74,6 +74,12 @@ int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count, u32 *error_locations); int elm_config(enum bch_level level); void elm_reset(void); +#ifdef ELM_BASE void elm_init(void); +#else +static inline void elm_init(void) +{ +} +#endif #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_ELM_H */ diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index ed6cdf93ad0..9692b78da3c 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -20,7 +20,8 @@ #include <linux/bch.h> #include <linux/compiler.h> #include <nand.h> -#include <linux/mtd/omap_elm.h>
+#include "omap_elm.h"
#ifndef GPMC_MAX_CS #define GPMC_MAX_CS 4 @@ -1249,6 +1250,15 @@ void board_nand_init(void) struct udevice *dev; int ret;
+#ifdef CONFIG_NAND_OMAP_ELM
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_DRIVER_GET(gpmc_elm), &dev);
if (ret && ret != -ENODEV) {
pr_err("%s: Failed to get ELM device: %d\n", __func__, ret);
return;
}
+#endif
ret = uclass_get_device_by_driver(UCLASS_MTD, DM_DRIVER_GET(gpmc_nand), &dev); if (ret && ret != -ENODEV)
-- 2.34.1
-- Michael Nazzareno Trimarchi Co-Founder & Chief Executive Officer M. +39 347 913 2170 michael@amarulasolutions.com __________________________________
Amarula Solutions BV Joop Geesinkweg 125, 1114 AB, Amsterdam, NL T. +31 (0)85 111 9172 info@amarulasolutions.com www.amarulasolutions.com

Hi Michael,
On 22/12/2022 23:35, Michael Nazzareno Trimarchi wrote:
Hi Roger
On Wed, Dec 21, 2022 at 9:08 PM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi
On Wed, Dec 21, 2022 at 8:57 PM Roger Quadros rogerq@kernel.org wrote:
Hi Michael,
On 21/12/2022 19:56, Michael Nazzareno Trimarchi wrote:
Hi Roger
On Tue, Dec 20, 2022 at 11:22 AM Roger Quadros rogerq@kernel.org wrote:
Support u-boot driver model. We still retain support legacy way of doing things if ELM_BASE is defined in <asm/arch/hardware.h>
We could completely get rid of that if all platforms defining ELM_BASE get rid of that definition and enable CONFIG_SYS_NAND_SELF_INIT and are verified to work.
Signed-off-by: Roger Quadros rogerq@kernel.org
When you post please include the relative changelog
I put the changelog in the cover-letter.
My bad, I'm always start from patch 1 and look on changes in every single patch
Pipeline is running, I have fixed another minor problem in the build
Thanks. You mean __maybe_unused for omap_calculate_ecc_bch()?
cheers, -roger
Michael
Michael
cheers, -roger
Michael
drivers/mtd/nand/raw/omap_elm.c | 35 ++++++++++++++++++- .../mtd => drivers/mtd/nand/raw}/omap_elm.h | 6 ++++ drivers/mtd/nand/raw/omap_gpmc.c | 12 ++++++- 3 files changed, 51 insertions(+), 2 deletions(-) rename {include/linux/mtd => drivers/mtd/nand/raw}/omap_elm.h (97%)
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 35c6dd1f1bc..e528a5348d5 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -15,9 +15,14 @@ #include <common.h> #include <asm/io.h> #include <linux/errno.h> -#include <linux/mtd/omap_elm.h> #include <asm/arch/hardware.h>
+#include <dm.h> +#include <linux/ioport.h> +#include <linux/io.h>
+#include "omap_elm.h"
#define DRIVER_NAME "omap-elm" #define ELM_DEFAULT_POLY (0)
@@ -180,6 +185,7 @@ void elm_reset(void) ; }
+#ifdef ELM_BASE /**
- elm_init - Initialize ELM module
@@ -191,3 +197,30 @@ void elm_init(void) elm_cfg = (struct elm *)ELM_BASE; elm_reset(); } +#endif
+static int elm_probe(struct udevice *dev) +{ +#ifndef ELM_BASE
struct resource res;
dev_read_resource(dev, 0, &res);
elm_cfg = devm_ioremap(dev, res.start, resource_size(&res));
elm_reset();
+#endif
return 0;
+}
+static const struct udevice_id elm_ids[] = {
{ .compatible = "ti,am3352-elm" },
{ .compatible = "ti,am64-elm" },
{ }
+};
+U_BOOT_DRIVER(gpmc_elm) = {
.name = DRIVER_NAME,
.id = UCLASS_MTD,
.of_match = elm_ids,
.probe = elm_probe,
+}; diff --git a/include/linux/mtd/omap_elm.h b/drivers/mtd/nand/raw/omap_elm.h similarity index 97% rename from include/linux/mtd/omap_elm.h rename to drivers/mtd/nand/raw/omap_elm.h index f3db00d55de..a7f7bacb154 100644 --- a/include/linux/mtd/omap_elm.h +++ b/drivers/mtd/nand/raw/omap_elm.h @@ -74,6 +74,12 @@ int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count, u32 *error_locations); int elm_config(enum bch_level level); void elm_reset(void); +#ifdef ELM_BASE void elm_init(void); +#else +static inline void elm_init(void) +{ +} +#endif #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_ELM_H */ diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index ed6cdf93ad0..9692b78da3c 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -20,7 +20,8 @@ #include <linux/bch.h> #include <linux/compiler.h> #include <nand.h> -#include <linux/mtd/omap_elm.h>
+#include "omap_elm.h"
#ifndef GPMC_MAX_CS #define GPMC_MAX_CS 4 @@ -1249,6 +1250,15 @@ void board_nand_init(void) struct udevice *dev; int ret;
+#ifdef CONFIG_NAND_OMAP_ELM
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_DRIVER_GET(gpmc_elm), &dev);
if (ret && ret != -ENODEV) {
pr_err("%s: Failed to get ELM device: %d\n", __func__, ret);
return;
}
+#endif
ret = uclass_get_device_by_driver(UCLASS_MTD, DM_DRIVER_GET(gpmc_nand), &dev); if (ret && ret != -ENODEV)
-- 2.34.1
-- Michael Nazzareno Trimarchi Co-Founder & Chief Executive Officer M. +39 347 913 2170 michael@amarulasolutions.com __________________________________
Amarula Solutions BV Joop Geesinkweg 125, 1114 AB, Amsterdam, NL T. +31 (0)85 111 9172 info@amarulasolutions.com www.amarulasolutions.com

Hi
On Fri, Dec 23, 2022 at 10:34 AM Roger Quadros rogerq@kernel.org wrote:
Hi Michael,
On 22/12/2022 23:35, Michael Nazzareno Trimarchi wrote:
Hi Roger
On Wed, Dec 21, 2022 at 9:08 PM Michael Nazzareno Trimarchi michael@amarulasolutions.com wrote:
Hi
On Wed, Dec 21, 2022 at 8:57 PM Roger Quadros rogerq@kernel.org wrote:
Hi Michael,
On 21/12/2022 19:56, Michael Nazzareno Trimarchi wrote:
Hi Roger
On Tue, Dec 20, 2022 at 11:22 AM Roger Quadros rogerq@kernel.org wrote:
Support u-boot driver model. We still retain support legacy way of doing things if ELM_BASE is defined in <asm/arch/hardware.h>
We could completely get rid of that if all platforms defining ELM_BASE get rid of that definition and enable CONFIG_SYS_NAND_SELF_INIT and are verified to work.
Signed-off-by: Roger Quadros rogerq@kernel.org
When you post please include the relative changelog
I put the changelog in the cover-letter.
My bad, I'm always start from patch 1 and look on changes in every single patch
Pipeline is running, I have fixed another minor problem in the build
Thanks. You mean __maybe_unused for omap_calculate_ecc_bch()?
Yes, now the pipeline is clean
Michael
cheers, -roger
Michael
Michael
cheers, -roger
Michael
drivers/mtd/nand/raw/omap_elm.c | 35 ++++++++++++++++++- .../mtd => drivers/mtd/nand/raw}/omap_elm.h | 6 ++++ drivers/mtd/nand/raw/omap_gpmc.c | 12 ++++++- 3 files changed, 51 insertions(+), 2 deletions(-) rename {include/linux/mtd => drivers/mtd/nand/raw}/omap_elm.h (97%)
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 35c6dd1f1bc..e528a5348d5 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -15,9 +15,14 @@ #include <common.h> #include <asm/io.h> #include <linux/errno.h> -#include <linux/mtd/omap_elm.h> #include <asm/arch/hardware.h>
+#include <dm.h> +#include <linux/ioport.h> +#include <linux/io.h>
+#include "omap_elm.h"
#define DRIVER_NAME "omap-elm" #define ELM_DEFAULT_POLY (0)
@@ -180,6 +185,7 @@ void elm_reset(void) ; }
+#ifdef ELM_BASE /**
- elm_init - Initialize ELM module
@@ -191,3 +197,30 @@ void elm_init(void) elm_cfg = (struct elm *)ELM_BASE; elm_reset(); } +#endif
+static int elm_probe(struct udevice *dev) +{ +#ifndef ELM_BASE
struct resource res;
dev_read_resource(dev, 0, &res);
elm_cfg = devm_ioremap(dev, res.start, resource_size(&res));
elm_reset();
+#endif
return 0;
+}
+static const struct udevice_id elm_ids[] = {
{ .compatible = "ti,am3352-elm" },
{ .compatible = "ti,am64-elm" },
{ }
+};
+U_BOOT_DRIVER(gpmc_elm) = {
.name = DRIVER_NAME,
.id = UCLASS_MTD,
.of_match = elm_ids,
.probe = elm_probe,
+}; diff --git a/include/linux/mtd/omap_elm.h b/drivers/mtd/nand/raw/omap_elm.h similarity index 97% rename from include/linux/mtd/omap_elm.h rename to drivers/mtd/nand/raw/omap_elm.h index f3db00d55de..a7f7bacb154 100644 --- a/include/linux/mtd/omap_elm.h +++ b/drivers/mtd/nand/raw/omap_elm.h @@ -74,6 +74,12 @@ int elm_check_error(u8 *syndrome, enum bch_level bch_type, u32 *error_count, u32 *error_locations); int elm_config(enum bch_level level); void elm_reset(void); +#ifdef ELM_BASE void elm_init(void); +#else +static inline void elm_init(void) +{ +} +#endif #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_ELM_H */ diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index ed6cdf93ad0..9692b78da3c 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -20,7 +20,8 @@ #include <linux/bch.h> #include <linux/compiler.h> #include <nand.h> -#include <linux/mtd/omap_elm.h>
+#include "omap_elm.h"
#ifndef GPMC_MAX_CS #define GPMC_MAX_CS 4 @@ -1249,6 +1250,15 @@ void board_nand_init(void) struct udevice *dev; int ret;
+#ifdef CONFIG_NAND_OMAP_ELM
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_DRIVER_GET(gpmc_elm), &dev);
if (ret && ret != -ENODEV) {
pr_err("%s: Failed to get ELM device: %d\n", __func__, ret);
return;
}
+#endif
ret = uclass_get_device_by_driver(UCLASS_MTD, DM_DRIVER_GET(gpmc_nand), &dev); if (ret && ret != -ENODEV)
-- 2.34.1
-- Michael Nazzareno Trimarchi Co-Founder & Chief Executive Officer M. +39 347 913 2170 michael@amarulasolutions.com __________________________________
Amarula Solutions BV Joop Geesinkweg 125, 1114 AB, Amsterdam, NL T. +31 (0)85 111 9172 info@amarulasolutions.com www.amarulasolutions.com

Hi Roger,
applied to nand-next
Thanks and regards, Dario
On Tue, Dec 20, 2022 at 11:22 AM Roger Quadros rogerq@kernel.org wrote:
Hi Michael & Dario,
This series adds driver model support for rawnand: omap_gpmc and omap_elm drivers.
This will enable the driver to be used on K2/K3 platforms as well.
This series along with remaining patches required to get NAND working on AM6x EVM is available here https://github.com/rogerq/u-boot/commits/for-v2023.01/am64-nand-base-2.0
cheers, -roger
Changelog: v2:
- Fixed build warning and failures for am335x_guardian, chiliboard, and cm_t32 - use __maybe_unused struct nand_chip to fix build warning
- make elm_probe() a NOP if ELM_BASE is defined. This should not interfere with existing platforms that don't use Driver Model for ELM driver.
Roger Quadros (8): mtd: rawnand: omap_gpmc: Fix BCH6/16 HW based correction mtd: rawnand: nand_base: Allow base driver to be used in SPL without nand_bbt dt-bindings: mtd: Add ti,gpmc-nand DT binding documentation mtd: rawnand: omap_gpmc: support u-boot driver model mtd: rawnand: omap_gpmc: Add SPL NAND support mtd: rawnand: omap_gpmc: Enable SYS_NAND_PAGE_COUNT for OMAP_GPMC dt-bindings: mtd: Add ti,elm DT binding documentation mtd: rawnand: omap_elm: u-boot driver model support
doc/device-tree-bindings/mtd/ti,elm.yaml | 72 +++ .../mtd/ti,gpmc-nand.yaml | 129 +++++ drivers/mtd/nand/raw/Kconfig | 9 +- drivers/mtd/nand/raw/Makefile | 2 +- drivers/mtd/nand/raw/nand_base.c | 18 +- drivers/mtd/nand/raw/omap_elm.c | 35 +- .../mtd => drivers/mtd/nand/raw}/omap_elm.h | 6 + drivers/mtd/nand/raw/omap_gpmc.c | 441 +++++++++++++----- 8 files changed, 604 insertions(+), 108 deletions(-) create mode 100644 doc/device-tree-bindings/mtd/ti,elm.yaml create mode 100644 doc/device-tree-bindings/mtd/ti,gpmc-nand.yaml rename {include/linux/mtd => drivers/mtd/nand/raw}/omap_elm.h (97%)
-- 2.34.1
participants (3)
-
Dario Binacchi
-
Michael Nazzareno Trimarchi
-
Roger Quadros