summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-01-31 13:26:28 -0500
committerTom Rini <trini@konsulko.com>2020-01-31 13:26:28 -0500
commit80e99adbe47d1c8590f9b971ac52257fdc51a5ec (patch)
tree2da762e5bd632c832852fd3d3c18d8b7cdef9e38 /drivers
parent514d00e527320a96c682029f4982955700f1664b (diff)
parent76cd7d47fb8ac191553b741bb424e93c94ca759a (diff)
Merge tag 'uniphier-v2020.04-2' of https://gitlab.denx.de/u-boot/custodians/u-boot-uniphier
UniPhier SoC updates for v2020.04 (2nd) Denali NAND driver changes: - Set up more registers in denali-spl for SOCFPGA - Make clocks optional - Do not assert reset signals in the remove hook - associate SPARE_AREA_SKIP_BYTES with DT compatible - switch to UCLASS_MTD UniPhier platform changes: - fix a bug in dram_init() - specify loadaddr for "source" command
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/raw/Kconfig2
-rw-r--r--drivers/mtd/nand/raw/denali.c15
-rw-r--r--drivers/mtd/nand/raw/denali.h2
-rw-r--r--drivers/mtd/nand/raw/denali_dt.c57
-rw-r--r--drivers/mtd/nand/raw/denali_spl.c7
5 files changed, 52 insertions, 31 deletions
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 7814d84ba0..23201ca720 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -116,7 +116,7 @@ config NAND_DENALI
config NAND_DENALI_DT
bool "Support Denali NAND controller as a DT device"
select NAND_DENALI
- depends on OF_CONTROL && DM
+ depends on OF_CONTROL && DM_MTD
help
Enable the driver for NAND flash on platforms using a Denali NAND
controller as a DT device.
diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index 8537c609fb..be1b3627ad 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -1069,11 +1069,18 @@ static void denali_hw_init(struct denali_nand_info *denali)
denali->revision = swab16(ioread32(denali->reg + REVISION));
/*
- * tell driver how many bit controller will skip before writing
- * ECC code in OOB. This is normally used for bad block marker
+ * Set how many bytes should be skipped before writing data in OOB.
+ * If a platform requests a non-zero value, set it to the register.
+ * Otherwise, read the value out, expecting it has already been set up
+ * by firmware.
*/
- denali->oob_skip_bytes = CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES;
- iowrite32(denali->oob_skip_bytes, denali->reg + SPARE_AREA_SKIP_BYTES);
+ if (denali->oob_skip_bytes)
+ iowrite32(denali->oob_skip_bytes,
+ denali->reg + SPARE_AREA_SKIP_BYTES);
+ else
+ denali->oob_skip_bytes = ioread32(denali->reg +
+ SPARE_AREA_SKIP_BYTES);
+
denali_detect_max_banks(denali);
iowrite32(0x0F, denali->reg + RB_PIN_ENABLED);
iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE);
diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h
index 63ae828768..019deda094 100644
--- a/drivers/mtd/nand/raw/denali.h
+++ b/drivers/mtd/nand/raw/denali.h
@@ -10,7 +10,6 @@
#include <linux/bitops.h>
#include <linux/mtd/rawnand.h>
#include <linux/types.h>
-#include <reset.h>
#define DEVICE_RESET 0x0
#define DEVICE_RESET__BANK(bank) BIT(bank)
@@ -316,7 +315,6 @@ struct denali_nand_info {
void (*host_write)(struct denali_nand_info *denali, u32 addr, u32 data);
void (*setup_dma)(struct denali_nand_info *denali, dma_addr_t dma_addr,
int page, int write);
- struct reset_ctl_bulk resets;
};
#define DENALI_CAP_HW_ECC_FIXUP BIT(0)
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)
diff --git a/drivers/mtd/nand/raw/denali_spl.c b/drivers/mtd/nand/raw/denali_spl.c
index dbaba3cab2..b8b29812aa 100644
--- a/drivers/mtd/nand/raw/denali_spl.c
+++ b/drivers/mtd/nand/raw/denali_spl.c
@@ -173,6 +173,13 @@ void nand_init(void)
page_size = readl(denali_flash_reg + DEVICE_MAIN_AREA_SIZE);
oob_size = readl(denali_flash_reg + DEVICE_SPARE_AREA_SIZE);
pages_per_block = readl(denali_flash_reg + PAGES_PER_BLOCK);
+
+ /* Do as denali_hw_init() does. */
+ writel(CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES,
+ denali_flash_reg + SPARE_AREA_SKIP_BYTES);
+ writel(0x0F, denali_flash_reg + RB_PIN_ENABLED);
+ writel(CHIP_EN_DONT_CARE__FLAG, denali_flash_reg + CHIP_ENABLE_DONT_CARE);
+ writel(0xffff, denali_flash_reg + SPARE_AREA_MARKER);
}
int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)