summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_denali_dt.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2020-11-10 15:07:38 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2020-11-10 15:07:38 +0100
commit7b1d8b4b3561c043a79d5933a7c1eb9266dc328d (patch)
tree9c398aa20e22763a239d11eecf6fb4c1d06d4c97 /drivers/mtd/nand/nand_denali_dt.c
parent0b0eada569b198aa3882cfec5874bc35a8a0fa14 (diff)
parent4db0f1c3dbe6173fdf91cbeb83e250719332c6a3 (diff)
downloadbarebox-7b1d8b4b3561c043a79d5933a7c1eb9266dc328d.tar.gz
barebox-7b1d8b4b3561c043a79d5933a7c1eb9266dc328d.tar.xz
Merge branch 'for-next/mtd-nand'
Diffstat (limited to 'drivers/mtd/nand/nand_denali_dt.c')
-rw-r--r--drivers/mtd/nand/nand_denali_dt.c97
1 files changed, 84 insertions, 13 deletions
diff --git a/drivers/mtd/nand/nand_denali_dt.c b/drivers/mtd/nand/nand_denali_dt.c
index e3024549cd..877c40714a 100644
--- a/drivers/mtd/nand/nand_denali_dt.c
+++ b/drivers/mtd/nand/nand_denali_dt.c
@@ -24,58 +24,128 @@
#include <errno.h>
#include <linux/clk.h>
+#include <linux/spinlock.h>
#include "denali.h"
struct denali_dt {
- struct denali_nand_info denali;
- struct clk *clk;
+ struct denali_controller denali;
+ struct clk *clk; /* core clock */
+ struct clk *clk_x; /* bus interface clock */
+ struct clk *clk_ecc; /* ECC circuit clock */
};
+struct denali_dt_data {
+ unsigned int revision;
+ unsigned int caps;
+ unsigned int oob_skip_bytes;
+ const struct nand_ecc_caps *ecc_caps;
+};
+
+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,
+};
+
+static int denali_dt_chip_init(struct denali_controller *denali,
+ struct device_node *chip_np)
+{
+ struct denali_chip *dchip;
+ u32 bank;
+ int nsels, i, ret;
+
+ nsels = of_property_count_elems_of_size(chip_np, "reg", sizeof(u32));
+ if (nsels < 0)
+ return nsels;
+
+ dchip = xzalloc(sizeof(*dchip) + sizeof(struct denali_chip_sel) *nsels);
+
+ dchip->nsels = nsels;
+
+ for (i = 0; i < nsels; i++) {
+ ret = of_property_read_u32_index(chip_np, "reg", i, &bank);
+ if (ret)
+ return ret;
+
+ dchip->sels[i].bank = bank;
+
+ nand_set_flash_node(&dchip->chip, chip_np);
+ }
+
+ return denali_chip_init(denali, dchip);
+}
static int denali_dt_probe(struct device_d *ofdev)
{
struct resource *iores;
struct denali_dt *dt;
- struct denali_nand_info *denali;
+ struct denali_controller *denali;
+ struct denali_dt_data *data;
+ struct device_node *np;
int ret;
if (!IS_ENABLED(CONFIG_OFDEVICE))
return 1;
+ ret = dev_get_drvdata(ofdev, (const void **)&data);
+ if (ret)
+ return ret;
+
dt = kzalloc(sizeof(*dt), GFP_KERNEL);
if (!dt)
return -ENOMEM;
denali = &dt->denali;
- denali->platform = DT;
denali->dev = ofdev;
iores = dev_request_mem_resource(ofdev, 0);
if (IS_ERR(iores))
return PTR_ERR(iores);
- denali->flash_mem = IOMEM(iores->start);
+ denali->host = IOMEM(iores->start);
iores = dev_request_mem_resource(ofdev, 1);
if (IS_ERR(iores))
return PTR_ERR(iores);
- denali->flash_reg = IOMEM(iores->start);
+ denali->reg = IOMEM(iores->start);
- dt->clk = clk_get(ofdev, NULL);
- if (IS_ERR(dt->clk)) {
- dev_err(ofdev, "no clk available\n");
+ dt->clk = clk_get(ofdev, "nand");
+ if (IS_ERR(dt->clk))
return PTR_ERR(dt->clk);
- }
+
+ dt->clk_x = clk_get(ofdev, "nand_x");
+ if (IS_ERR(dt->clk_x))
+ return PTR_ERR(dt->clk_x);
+
+ dt->clk_ecc = clk_get(ofdev, "ecc");
+ if (IS_ERR(dt->clk_ecc))
+ return PTR_ERR(dt->clk_ecc);
+
clk_enable(dt->clk);
+ clk_enable(dt->clk_x);
+ clk_enable(dt->clk_ecc);
+
+ denali->clk_rate = clk_get_rate(dt->clk);
+ denali->clk_x_rate = clk_get_rate(dt->clk_x);
- denali->have_hw_ecc_fixup = of_property_read_bool(ofdev->device_node,
- "have-hw-ecc-fixup");
+ denali->revision = data->revision;
+ denali->caps = data->caps;
+ denali->oob_skip_bytes = data->oob_skip_bytes;
+ denali->ecc_caps = data->ecc_caps;
ret = denali_init(denali);
if (ret)
goto out_disable_clk;
+ for_each_child_of_node(ofdev->device_node, np) {
+ ret = denali_dt_chip_init(denali, np);
+ if (ret)
+ goto out_disable_clk;
+ }
+
return 0;
out_disable_clk:
@@ -86,7 +156,8 @@ out_disable_clk:
static __maybe_unused struct of_device_id denali_nand_compatible[] = {
{
- .compatible = "altr,socfpga-denali-nand"
+ .compatible = "altr,socfpga-denali-nand",
+ .data = &denali_socfpga_data,
}, {
/* sentinel */
}