summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/raw/denali_dt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/raw/denali_dt.c')
-rw-r--r--drivers/mtd/nand/raw/denali_dt.c57
1 files changed, 33 insertions, 24 deletions
diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c
index 0ce81324b9..759ad40e51 100644
--- a/drivers/mtd/nand/raw/denali_dt.c
+++ b/drivers/mtd/nand/raw/denali_dt.c
@@ -9,12 +9,14 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/printk.h>
+#include <reset.h>
#include "denali.h"
struct denali_dt_data {
unsigned int revision;
unsigned int caps;
+ unsigned int oob_skip_bytes;
const struct nand_ecc_caps *ecc_caps;
};
@@ -22,6 +24,7 @@ NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps, denali_calc_ecc_bytes,
512, 8, 15);
static const struct denali_dt_data denali_socfpga_data = {
.caps = DENALI_CAP_HW_ECC_FIXUP,
+ .oob_skip_bytes = 2,
.ecc_caps = &denali_socfpga_ecc_caps,
};
@@ -30,6 +33,7 @@ NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps, denali_calc_ecc_bytes,
static const struct denali_dt_data denali_uniphier_v5a_data = {
.caps = DENALI_CAP_HW_ECC_FIXUP |
DENALI_CAP_DMA_64BIT,
+ .oob_skip_bytes = 8,
.ecc_caps = &denali_uniphier_v5a_ecc_caps,
};
@@ -39,6 +43,7 @@ static const struct denali_dt_data denali_uniphier_v5b_data = {
.revision = 0x0501,
.caps = DENALI_CAP_HW_ECC_FIXUP |
DENALI_CAP_DMA_64BIT,
+ .oob_skip_bytes = 8,
.ecc_caps = &denali_uniphier_v5b_ecc_caps,
};
@@ -63,15 +68,18 @@ static int denali_dt_probe(struct udevice *dev)
struct denali_nand_info *denali = dev_get_priv(dev);
const struct denali_dt_data *data;
struct clk clk, clk_x, clk_ecc;
+ struct reset_ctl_bulk resets;
struct resource res;
int ret;
data = (void *)dev_get_driver_data(dev);
- if (data) {
- denali->revision = data->revision;
- denali->caps = data->caps;
- denali->ecc_caps = data->ecc_caps;
- }
+ if (WARN_ON(!data))
+ return -EINVAL;
+
+ denali->revision = data->revision;
+ denali->caps = data->caps;
+ denali->oob_skip_bytes = data->oob_skip_bytes;
+ denali->ecc_caps = data->ecc_caps;
denali->dev = dev;
@@ -91,7 +99,7 @@ static int denali_dt_probe(struct udevice *dev)
if (ret)
ret = clk_get_by_index(dev, 0, &clk);
if (ret)
- return ret;
+ clk.dev = NULL;
ret = clk_get_by_name(dev, "nand_x", &clk_x);
if (ret)
@@ -101,9 +109,11 @@ static int denali_dt_probe(struct udevice *dev)
if (ret)
clk_ecc.dev = NULL;
- ret = clk_enable(&clk);
- if (ret)
- return ret;
+ if (clk.dev) {
+ ret = clk_enable(&clk);
+ if (ret)
+ return ret;
+ }
if (clk_x.dev) {
ret = clk_enable(&clk_x);
@@ -131,30 +141,29 @@ static int denali_dt_probe(struct udevice *dev)
denali->clk_x_rate = 200000000;
}
- ret = reset_get_bulk(dev, &denali->resets);
- if (ret)
+ ret = reset_get_bulk(dev, &resets);
+ if (ret) {
dev_warn(dev, "Can't get reset: %d\n", ret);
- else
- reset_deassert_bulk(&denali->resets);
-
- return denali_init(denali);
-}
+ } else {
+ reset_deassert_bulk(&resets);
-static int denali_dt_remove(struct udevice *dev)
-{
- struct denali_nand_info *denali = dev_get_priv(dev);
+ /*
+ * When the reset is deasserted, the initialization sequence is
+ * kicked (bootstrap process). The driver must wait until it is
+ * finished. Otherwise, it will result in unpredictable behavior.
+ */
+ udelay(200);
+ }
- return reset_release_bulk(&denali->resets);
+ return denali_init(denali);
}
U_BOOT_DRIVER(denali_nand_dt) = {
.name = "denali-nand-dt",
- .id = UCLASS_MISC,
+ .id = UCLASS_MTD,
.of_match = denali_nand_dt_ids,
.probe = denali_dt_probe,
.priv_auto_alloc_size = sizeof(struct denali_nand_info),
- .remove = denali_dt_remove,
- .flags = DM_FLAG_OS_PREPARE,
};
void board_nand_init(void)
@@ -162,7 +171,7 @@ void board_nand_init(void)
struct udevice *dev;
int ret;
- ret = uclass_get_device_by_driver(UCLASS_MISC,
+ ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_GET_DRIVER(denali_nand_dt),
&dev);
if (ret && ret != -ENODEV)