diff options
-rw-r--r-- | drivers/mtd/nand/denali.c | 27 | ||||
-rw-r--r-- | drivers/mtd/nand/denali.h | 7 | ||||
-rw-r--r-- | drivers/mtd/nand/denali_dt.c | 30 |
3 files changed, 50 insertions, 14 deletions
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 47cf37d1d9b..54718f418c6 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -10,7 +10,7 @@ #include <malloc.h> #include <nand.h> #include <linux/errno.h> -#include <asm/io.h> +#include <linux/io.h> #include "denali.h" @@ -433,17 +433,13 @@ static void find_valid_banks(struct denali_nand_info *denali) */ static void detect_max_banks(struct denali_nand_info *denali) { - uint32_t features = readl(denali->flash_reg + FEATURES); - /* - * Read the revision register, so we can calculate the max_banks - * properly: the encoding changed from rev 5.0 to 5.1 - */ - u32 revision = MAKE_COMPARABLE_REVISION( - readl(denali->flash_reg + REVISION)); - if (revision < REVISION_5_1) - denali->max_banks = 2 << (features & FEATURES__N_BANKS); - else - denali->max_banks = 1 << (features & FEATURES__N_BANKS); + uint32_t features = ioread32(denali->flash_reg + FEATURES); + + denali->max_banks = 1 << (features & FEATURES__N_BANKS); + + /* the encoding changed from rev 5.0 to 5.1 */ + if (denali->revision < 0x0501) + denali->max_banks <<= 1; } static void detect_partition_feature(struct denali_nand_info *denali) @@ -1154,6 +1150,13 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, static void denali_hw_init(struct denali_nand_info *denali) { /* + * The REVISION register may not be reliable. Platforms are allowed to + * override it. + */ + if (!denali->revision) + denali->revision = swab16(ioread32(denali->flash_reg + REVISION)); + + /* * tell driver how many bit controller will skip before writing * ECC code in OOB. This is normally used for bad block marker */ diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 694bce53a95..08db48843da 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -166,8 +166,6 @@ #define REVISION 0x370 #define REVISION__VALUE 0xffff -#define MAKE_COMPARABLE_REVISION(x) swab16((x) & REVISION__VALUE) -#define REVISION_5_1 0x00000501 #define ONFI_DEVICE_FEATURES 0x380 #define ONFI_DEVICE_FEATURES__VALUE 0x003f @@ -462,8 +460,13 @@ struct denali_nand_info { uint32_t blksperchip; uint32_t bbtskipbytes; uint32_t max_banks; + unsigned int revision; + unsigned int caps; }; +#define DENALI_CAP_HW_ECC_FIXUP BIT(0) +#define DENALI_CAP_DMA_64BIT BIT(1) + int denali_init(struct denali_nand_info *denali); #endif /* __DENALI_H__ */ diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index 0a6155c748c..4afd679a04b 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c @@ -12,15 +12,38 @@ #include "denali.h" +struct denali_dt_data { + unsigned int revision; + unsigned int caps; +}; + +static const struct denali_dt_data denali_socfpga_data = { + .caps = DENALI_CAP_HW_ECC_FIXUP, +}; + +static const struct denali_dt_data denali_uniphier_v5a_data = { + .caps = DENALI_CAP_HW_ECC_FIXUP | + DENALI_CAP_DMA_64BIT, +}; + +static const struct denali_dt_data denali_uniphier_v5b_data = { + .revision = 0x0501, + .caps = DENALI_CAP_HW_ECC_FIXUP | + DENALI_CAP_DMA_64BIT, +}; + static const struct udevice_id denali_nand_dt_ids[] = { { .compatible = "altr,socfpga-denali-nand", + .data = (unsigned long)&denali_socfpga_data, }, { .compatible = "socionext,uniphier-denali-nand-v5a", + .data = (unsigned long)&denali_uniphier_v5a_data, }, { .compatible = "socionext,uniphier-denali-nand-v5b", + .data = (unsigned long)&denali_uniphier_v5b_data, }, { /* sentinel */ } }; @@ -28,9 +51,16 @@ static const struct udevice_id denali_nand_dt_ids[] = { static int denali_dt_probe(struct udevice *dev) { struct denali_nand_info *denali = dev_get_priv(dev); + const struct denali_dt_data *data; struct resource res; int ret; + data = (void *)dev_get_driver_data(dev); + if (data) { + denali->revision = data->revision; + denali->caps = data->caps; + } + ret = dev_read_resource_byname(dev, "denali_reg", &res); if (ret) return ret; |