[U-Boot] [PATCH v10 24/27] env: add spi-nor environment

Jagan Teki
2017-12-28T06:12:30Z

Now spi-nor framework is up so access the environment
through en/spinor.c

Signed-off-by: Suneel Garapati <suneelglinux@gmail.com>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
cmd/nvedit.c | 1 +
env/Kconfig | 27 ++++++++++++
env/Makefile | 1 +
env/env.c | 2 +
env/spinor.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/environment.h | 1 +
6 files changed, 145 insertions(+)
create mode 100644 env/spinor.c

diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 4e79d03..2e5e88d 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -50,6 +50,7 @@ DECLARE_GLOBAL_DATA_PTR;
!defined(CONFIG_ENV_IS_IN_ONENAND) && \
!defined(CONFIG_ENV_IS_IN_SATA) && \
!defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \
+ !defined(CONFIG_ENV_IS_IN_SPI_NOR) && \
!defined(CONFIG_ENV_IS_IN_REMOTE) && \
!defined(CONFIG_ENV_IS_IN_UBI) && \
!defined(CONFIG_ENV_IS_NOWHERE)
diff --git a/env/Kconfig b/env/Kconfig
index 2477bf8..1b694d5 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -329,6 +329,22 @@ config ENV_IS_IN_SPI_FLASH

Define the SPI work mode. If not defined then use SPI_MODE_3.

+config ENV_IS_IN_SPI_NOR
+ bool "Environment is in SPI-NOR flash"
+ depends on !CHAIN_OF_TRUST
+ help
+ Define this if you have a SPI NOR Flash memory device which you
+ want to use for the environment.
+
+ - CONFIG_ENV_OFFSET:
+ - CONFIG_ENV_SIZE:
+
+ These two #defines specify the offset and size of the
+ environment area within the SPI NOR Flash. CONFIG_ENV_OFFSET must be
+ aligned to an erase sector boundary.
+
+ - CONFIG_ENV_SECT_SIZE:
+
config ENV_IS_IN_UBI
bool "Environment in a UBI volume"
depends on !CHAIN_OF_TRUST
@@ -396,6 +412,17 @@ config ENV_FAT_FILE
It's a string of the FAT file name. This file use to store the
environment.

+config ENV_SPI_NOR_DEVNUM
+ int "SPI-NOR device number for the environment"
+ depends on ENV_IS_IN_SPI_NOR
+ default 0
+ help
+ Define this an integer of spi nor device number for the environment.
+ Since spi nor framework assign device numbers automatically by devicetree
+ node definition which start from 0, so assign 0 as default.
+
+ If board need different devnum then, this can be change.
+
if ARCH_SUNXI

config ENV_OFFSET
diff --git a/env/Makefile b/env/Makefile
index 7ce8231..21fe9a4 100644
--- a/env/Makefile
+++ b/env/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_ENV_IS_IN_NVRAM) += nvram.o
obj-$(CONFIG_ENV_IS_IN_ONENAND) += onenand.o
obj-$(CONFIG_ENV_IS_IN_SATA) += sata.o
obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += sf.o
+obj-$(CONFIG_ENV_IS_IN_SPI_NOR) += spinor.o
obj-$(CONFIG_ENV_IS_IN_REMOTE) += remote.o
obj-$(CONFIG_ENV_IS_IN_UBI) += ubi.o
obj-$(CONFIG_ENV_IS_NOWHERE) += nowhere.o
diff --git a/env/env.c b/env/env.c
index 76a5608..be1672c 100644
--- a/env/env.c
+++ b/env/env.c
@@ -44,6 +44,8 @@ static enum env_location env_get_default_location(void)
return ENVL_REMOTE;
else if IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)
return ENVL_SPI_FLASH;
+ else if IS_ENABLED(CONFIG_ENV_IS_IN_SPI_NOR)
+ return ENVL_SPI_NOR;
else if IS_ENABLED(CONFIG_ENV_IS_IN_UBI)
return ENVL_UBI;
else if IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
diff --git a/env/spinor.c b/env/spinor.c
new file mode 100644
index 0000000..bc6fdfa
--- /dev/null
+++ b/env/spinor.c
@@ -0,0 +1,113 @@
+/*
+ * SPI-NOR Environment.
+ *
+ * Copyright (C) 2017 Jagan Teki <jagan@openedev.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <environment.h>
+#include <memalign.h>
+#include <mtd.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct spi_nor *env_init_spinor(void)
+{
+ struct spi_nor *nor;
+ int devnum = CONFIG_ENV_SPI_NOR_DEVNUM;
+
+ nor = find_spi_nor_device(devnum);
+ if (!nor)
+ return NULL;
+
+ if (spi_nor_scan(nor))
+ return NULL;
+
+ return nor;
+}
+
+static int env_spinor_save(void)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
+ struct spi_nor *nor;
+ struct mtd_info *mtd;
+ struct erase_info instr;
+ loff_t len, sector;
+ int ret;
+
+ nor = env_init_spinor();
+ if (!nor)
+ return -EIO;
+
+ ret = env_export(env_new);
+ if (ret)
+ return -EINVAL;
+
+ mtd = spi_nor_get_mtd_info(nor);
+ if (!mtd)
+ return -EIO;
+
+ sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE);
+ len = sector * CONFIG_ENV_SECT_SIZE;
+ instr.mtd = mtd;
+ instr.addr = CONFIG_ENV_OFFSET;
+ instr.len = len;
+ instr.callback = 0;
+
+ puts("erasing spinor flash...\n");
+ ret = mtd_derase(mtd, &instr);
+ if (ret)
+ return -EIO;
+
+ len = CONFIG_ENV_SIZE;
+ puts("writing spinor flash...\n");
+ ret = mtd_dwrite(mtd, CONFIG_ENV_OFFSET, len,
+ (size_t *)&len, (u_char *)env_new);
+ if (ret)
+ return -EIO;
+
+ puts("done\n");
+ return ret;
+}
+
+static int env_spinor_load(void)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
+ struct spi_nor *nor;
+ struct mtd_info *mtd;
+ loff_t offset, len;
+ int ret;
+
+ nor = env_init_spinor();
+ if (!nor)
+ return -EIO;
+
+ offset = CONFIG_ENV_OFFSET;
+ len = CONFIG_ENV_SIZE;
+
+ mtd = spi_nor_get_mtd_info(nor);
+ if (!mtd)
+ return -EIO;
+
+ ret = mtd_dread(mtd, offset, len, (size_t *)&len, (uchar *)buf);
+ if (ret)
+ return -EIO;
+
+ ret = env_import(buf, 1);
+ if (ret)
+ gd->env_valid = ENV_VALID;
+
+ return ret;
+}
+
+U_BOOT_ENV_LOCATION(spinor) = {
+ .location = ENVL_SPI_NOR,
+ ENV_NAME("SPI-NOR Flash")
+ .load = env_spinor_load,
+ .save = env_save_ptr(env_spinor_save),
+};
diff --git a/include/environment.h b/include/environment.h
index d29f82c..8e8be26 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -198,6 +198,7 @@ enum env_location {
ENVL_ONENAND,
ENVL_REMOTE,
ENVL_SPI_FLASH,
+ ENVL_SPI_NOR,
ENVL_UBI,
ENVL_NOWHERE,

--
2.7.4