Skip to content

Commit

Permalink
nand: omap2: Remove horrible ifdefs to fix module probe
Browse files Browse the repository at this point in the history
The current code abuses ifdefs to determine if the selected ECC scheme
is supported by the running kernel. As a result the code is hard to read,
and it also fails to load as a module.

This commit removes all the ifdefs and instead introduces a function
omap2_nand_ecc_check() to check if the ECC is supported by using
IS_ENABLED(CONFIG_xxx).

Since IS_ENABLED() is true when a config is =y or =m, this change fixes the
module so it can be loaded with no issues.

Acked-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
  • Loading branch information
Ezequiel García authored and Brian Norris committed Sep 22, 2014
1 parent 2a960cc commit 93af53b
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 59 deletions.
130 changes: 71 additions & 59 deletions drivers/mtd/nand/omap2.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,13 @@

#define BADBLOCK_MARKER_LENGTH 2

#ifdef CONFIG_MTD_NAND_OMAP_BCH
static u_char bch16_vector[] = {0xf5, 0x24, 0x1c, 0xd0, 0x61, 0xb3, 0xf1, 0x55,
0x2e, 0x2c, 0x86, 0xa3, 0xed, 0x36, 0x1b, 0x78,
0x48, 0x76, 0xa9, 0x3b, 0x97, 0xd1, 0x7a, 0x93,
0x07, 0x0e};
static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
0xac, 0x6b, 0xff, 0x99, 0x7b};
static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
#endif

/* oob info generated runtime depending on ecc algorithm and layout selected */
static struct nand_ecclayout omap_oobinfo;
Expand Down Expand Up @@ -1292,7 +1290,6 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
return 0;
}

#ifdef CONFIG_MTD_NAND_OMAP_BCH
/**
* erased_sector_bitflips - count bit flips
* @data: data sector buffer
Expand Down Expand Up @@ -1593,33 +1590,71 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
/**
* is_elm_present - checks for presence of ELM module by scanning DT nodes
* @omap_nand_info: NAND device structure containing platform data
* @bch_type: 0x0=BCH4, 0x1=BCH8, 0x2=BCH16
*/
static int is_elm_present(struct omap_nand_info *info,
struct device_node *elm_node, enum bch_ecc bch_type)
static bool is_elm_present(struct omap_nand_info *info,
struct device_node *elm_node)
{
struct platform_device *pdev;
struct nand_ecc_ctrl *ecc = &info->nand.ecc;
int err;

/* check whether elm-id is passed via DT */
if (!elm_node) {
pr_err("nand: error: ELM DT node not found\n");
return -ENODEV;
return false;
}
pdev = of_find_device_by_node(elm_node);
/* check whether ELM device is registered */
if (!pdev) {
pr_err("nand: error: ELM device not found\n");
return -ENODEV;
return false;
}
/* ELM module available, now configure it */
info->elm_dev = &pdev->dev;
err = elm_config(info->elm_dev, bch_type,
(info->mtd.writesize / ecc->size), ecc->size, ecc->bytes);
return true;
}

return err;
static bool omap2_nand_ecc_check(struct omap_nand_info *info,
struct omap_nand_platform_data *pdata)
{
bool ecc_needs_bch, ecc_needs_omap_bch, ecc_needs_elm;

switch (info->ecc_opt) {
case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
ecc_needs_omap_bch = false;
ecc_needs_bch = true;
ecc_needs_elm = false;
break;
case OMAP_ECC_BCH4_CODE_HW:
case OMAP_ECC_BCH8_CODE_HW:
case OMAP_ECC_BCH16_CODE_HW:
ecc_needs_omap_bch = true;
ecc_needs_bch = false;
ecc_needs_elm = true;
break;
default:
ecc_needs_omap_bch = false;
ecc_needs_bch = false;
ecc_needs_elm = false;
break;
}

if (ecc_needs_bch && !IS_ENABLED(CONFIG_MTD_NAND_ECC_BCH)) {
dev_err(&info->pdev->dev,
"CONFIG_MTD_NAND_ECC_BCH not enabled\n");
return false;
}
if (ecc_needs_omap_bch && !IS_ENABLED(CONFIG_MTD_NAND_OMAP_BCH)) {
dev_err(&info->pdev->dev,
"CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
return false;
}
if (ecc_needs_elm && !is_elm_present(info, pdata->elm_of_node)) {
dev_err(&info->pdev->dev, "ELM not available\n");
return false;
}

return true;
}
#endif /* CONFIG_MTD_NAND_ECC_BCH */

static int omap_nand_probe(struct platform_device *pdev)
{
Expand Down Expand Up @@ -1797,6 +1832,11 @@ static int omap_nand_probe(struct platform_device *pdev)
goto return_error;
}

if (!omap2_nand_ecc_check(info, pdata)) {
err = -EINVAL;
goto return_error;
}

/* populate MTD interface based on ECC scheme */
ecclayout = &omap_oobinfo;
switch (info->ecc_opt) {
Expand Down Expand Up @@ -1829,7 +1869,6 @@ static int omap_nand_probe(struct platform_device *pdev)
break;

case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
#ifdef CONFIG_MTD_NAND_ECC_BCH
pr_info("nand: using OMAP_ECC_BCH4_CODE_HW_DETECTION_SW\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
Expand Down Expand Up @@ -1861,14 +1900,8 @@ static int omap_nand_probe(struct platform_device *pdev)
err = -EINVAL;
}
break;
#else
pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n");
err = -EINVAL;
goto return_error;
#endif

case OMAP_ECC_BCH4_CODE_HW:
#ifdef CONFIG_MTD_NAND_OMAP_BCH
pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
Expand All @@ -1890,21 +1923,15 @@ static int omap_nand_probe(struct platform_device *pdev)
/* reserved marker already included in ecclayout->eccbytes */
ecclayout->oobfree->offset =
ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
/* This ECC scheme requires ELM H/W block */
if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) {
pr_err("nand: error: could not initialize ELM\n");
err = -ENODEV;

err = elm_config(info->elm_dev, BCH4_ECC,
info->mtd.writesize / nand_chip->ecc.size,
nand_chip->ecc.size, nand_chip->ecc.bytes);
if (err < 0)
goto return_error;
}
break;
#else
pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
err = -EINVAL;
goto return_error;
#endif

case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
#ifdef CONFIG_MTD_NAND_ECC_BCH
pr_info("nand: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
Expand Down Expand Up @@ -1937,14 +1964,8 @@ static int omap_nand_probe(struct platform_device *pdev)
goto return_error;
}
break;
#else
pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n");
err = -EINVAL;
goto return_error;
#endif

case OMAP_ECC_BCH8_CODE_HW:
#ifdef CONFIG_MTD_NAND_OMAP_BCH
pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
Expand All @@ -1956,12 +1977,13 @@ static int omap_nand_probe(struct platform_device *pdev)
nand_chip->ecc.calculate = omap_calculate_ecc_bch;
nand_chip->ecc.read_page = omap_read_page_bch;
nand_chip->ecc.write_page = omap_write_page_bch;
/* This ECC scheme requires ELM H/W block */
err = is_elm_present(info, pdata->elm_of_node, BCH8_ECC);
if (err < 0) {
pr_err("nand: error: could not initialize ELM\n");

err = elm_config(info->elm_dev, BCH8_ECC,
info->mtd.writesize / nand_chip->ecc.size,
nand_chip->ecc.size, nand_chip->ecc.bytes);
if (err < 0)
goto return_error;
}

/* define ECC layout */
ecclayout->eccbytes = nand_chip->ecc.bytes *
(mtd->writesize /
Expand All @@ -1973,14 +1995,8 @@ static int omap_nand_probe(struct platform_device *pdev)
ecclayout->oobfree->offset =
ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
break;
#else
pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
err = -EINVAL;
goto return_error;
#endif

case OMAP_ECC_BCH16_CODE_HW:
#ifdef CONFIG_MTD_NAND_OMAP_BCH
pr_info("using OMAP_ECC_BCH16_CODE_HW ECC scheme\n");
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
Expand All @@ -1991,12 +2007,13 @@ static int omap_nand_probe(struct platform_device *pdev)
nand_chip->ecc.calculate = omap_calculate_ecc_bch;
nand_chip->ecc.read_page = omap_read_page_bch;
nand_chip->ecc.write_page = omap_write_page_bch;
/* This ECC scheme requires ELM H/W block */
err = is_elm_present(info, pdata->elm_of_node, BCH16_ECC);
if (err < 0) {
pr_err("ELM is required for this ECC scheme\n");

err = elm_config(info->elm_dev, BCH16_ECC,
info->mtd.writesize / nand_chip->ecc.size,
nand_chip->ecc.size, nand_chip->ecc.bytes);
if (err < 0)
goto return_error;
}

/* define ECC layout */
ecclayout->eccbytes = nand_chip->ecc.bytes *
(mtd->writesize /
Expand All @@ -2008,11 +2025,6 @@ static int omap_nand_probe(struct platform_device *pdev)
ecclayout->oobfree->offset =
ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
break;
#else
pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
err = -EINVAL;
goto return_error;
#endif
default:
pr_err("nand: error: invalid or unsupported ECC scheme\n");
err = -EINVAL;
Expand Down
16 changes: 16 additions & 0 deletions include/linux/platform_data/elm.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,24 @@ struct elm_errorvec {
int error_loc[16];
};

#if IS_ENABLED(CONFIG_MTD_NAND_OMAP_BCH)
void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc,
struct elm_errorvec *err_vec);
int elm_config(struct device *dev, enum bch_ecc bch_type,
int ecc_steps, int ecc_step_size, int ecc_syndrome_size);
#else
static inline void
elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc,
struct elm_errorvec *err_vec)
{
}

static inline int elm_config(struct device *dev, enum bch_ecc bch_type,
int ecc_steps, int ecc_step_size,
int ecc_syndrome_size)
{
return -ENOSYS;
}
#endif /* CONFIG_MTD_NAND_ECC_BCH */

#endif /* __ELM_H */

0 comments on commit 93af53b

Please sign in to comment.