* [PATCH 01/13] nvmem: bsec: remove unused, left-over, struct member
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 02/13] nvmem: treat devices without nvmem_bus::write as read only Ahmad Fatoum
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
With the move to the nvmem_regmap_register, the config member in the
bsec driver became unused. Drop it.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/nvmem/bsec.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/nvmem/bsec.c b/drivers/nvmem/bsec.c
index 509a5fa872f7..d9b38c8414fb 100644
--- a/drivers/nvmem/bsec.c
+++ b/drivers/nvmem/bsec.c
@@ -23,7 +23,6 @@
struct bsec_priv {
u32 svc_id;
struct regmap_config map_config;
- struct nvmem_config config;
};
struct stm32_bsec_data {
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 02/13] nvmem: treat devices without nvmem_bus::write as read only
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 01/13] nvmem: bsec: remove unused, left-over, struct member Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 03/13] nvmem: add support for new read-only memory (rmem) binding Ahmad Fatoum
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
nvmem_bus::write is dereferenced unconditionally when doing write
operations. Align behavior with Linux, which allows drivers to omit
the reg_write callback when the device is known to be read-only.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/nvmem/core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index cfeecf70cd5d..3c14e390de39 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -209,8 +209,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
nvmem->dev.device_node = np;
nvmem->priv = config->priv;
- nvmem->read_only = of_property_read_bool(np, "read-only") |
- config->read_only;
+ if (config->read_only || !config->bus->write || of_property_read_bool(np, "read-only"))
+ nvmem->read_only = true;
dev_set_name(&nvmem->dev, config->name);
nvmem->dev.id = DEVICE_ID_DYNAMIC;
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 03/13] nvmem: add support for new read-only memory (rmem) binding
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 01/13] nvmem: bsec: remove unused, left-over, struct member Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 02/13] nvmem: treat devices without nvmem_bus::write as read only Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 04/13] nvmem: add support for nvmem-cells binding Ahmad Fatoum
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Only upstream user of this binding is the raspberry pi 4 DT, where it's
used to pass along bootloader-provided info to Linux. We have instances
in barebox, where a previous stage bootloader passes along a memory
region with info for barebox to interpret. This could in future be
modelled as nvmem-rmem nodes. The binding is also quite handy for
debugging.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/nvmem/Kconfig | 6 ++++
drivers/nvmem/Makefile | 2 ++
drivers/nvmem/rmem.c | 67 ++++++++++++++++++++++++++++++++++++++++++
drivers/of/base.c | 21 ++++++++++---
fs/devfs-core.c | 2 +-
include/driver.h | 3 ++
6 files changed, 96 insertions(+), 5 deletions(-)
create mode 100644 drivers/nvmem/rmem.c
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index e4a72b1431a9..0d7c0b7b9e3d 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -9,6 +9,12 @@ menuconfig NVMEM
if NVMEM
+config NVMEM_RMEM
+ bool "Reserved Memory Based Driver Support"
+ help
+ This driver maps reserved memory into an nvmem device. It might be
+ useful to expose information left by firmware in memory.
+
config NVMEM_SNVS_LPGPR
tristate "Freescale SNVS LPGPR support"
select MFD_SYSCON
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 617e3725a726..6330f3d6e681 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -5,6 +5,8 @@
obj-$(CONFIG_NVMEM) += nvmem_core.o
nvmem_core-y := core.o regmap.o
+obj-$(CONFIG_NVMEM_RMEM) += rmem.o
+
# Devices
obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o
nvmem_snvs_lpgpr-y := snvs_lpgpr.o
diff --git a/drivers/nvmem/rmem.c b/drivers/nvmem/rmem.c
new file mode 100644
index 000000000000..e103cec4482a
--- /dev/null
+++ b/drivers/nvmem/rmem.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+ */
+
+#include <io.h>
+#include <driver.h>
+#include <linux/nvmem-provider.h>
+#include <init.h>
+
+struct rmem {
+ struct device_d *dev;
+ const struct resource *mem;
+};
+
+static int rmem_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct rmem *rmem = context;
+ return mem_copy(rmem->dev, val, (void *)rmem->mem->start + offset,
+ bytes, offset, 0);
+}
+
+static struct nvmem_bus rmem_nvmem_bus = {
+ .read = rmem_read,
+};
+
+static int rmem_probe(struct device_d *dev)
+{
+ struct nvmem_config config = { };
+ struct resource *mem;
+ struct rmem *priv;
+
+ mem = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(mem))
+ return PTR_ERR(mem);
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->mem = mem;
+
+ config.dev = priv->dev = dev;
+ config.priv = priv;
+ config.name = "rmem";
+ config.size = resource_size(mem);
+ config.bus = &rmem_nvmem_bus;
+
+ return PTR_ERR_OR_ZERO(nvmem_register(&config));
+}
+
+static const struct of_device_id rmem_match[] = {
+ { .compatible = "nvmem-rmem", },
+ { /* sentinel */ },
+};
+
+static struct driver_d rmem_driver = {
+ .name = "rmem",
+ .of_compatible = rmem_match,
+ .probe = rmem_probe,
+};
+device_platform_driver(rmem_driver);
+
+MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>");
+MODULE_DESCRIPTION("Reserved Memory Based nvmem Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 193bae7fa017..015629e1e967 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2331,9 +2331,14 @@ static void of_platform_device_create_root(struct device_node *np)
free(dev);
}
+static const struct of_device_id reserved_mem_matches[] = {
+ { .compatible = "nvmem-rmem" },
+ {}
+};
+
int of_probe(void)
{
- struct device_node *firmware;
+ struct device_node *node;
int ret;
if(!root_node)
@@ -2347,9 +2352,17 @@ int of_probe(void)
ret = of_probe_memory();
- firmware = of_find_node_by_path("/firmware");
- if (firmware)
- of_platform_populate(firmware, NULL, NULL);
+ /*
+ * Handle certain compatibles explicitly, since we don't want to create
+ * platform_devices for every node in /reserved-memory with a
+ * "compatible",
+ */
+ for_each_matching_node(node, reserved_mem_matches)
+ of_platform_device_create(node, NULL);
+
+ node = of_find_node_by_path("/firmware");
+ if (node)
+ of_platform_populate(node, NULL, NULL);
of_platform_device_create_root(root_node);
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index f804f969745c..30ad0e050835 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -529,7 +529,7 @@ void cdev_remove_loop(struct cdev *cdev)
free(cdev);
}
-static ssize_t mem_copy(struct device_d *dev, void *dst, const void *src,
+ssize_t mem_copy(struct device_d *dev, void *dst, const void *src,
resource_size_t count, resource_size_t offset,
unsigned long flags)
{
diff --git a/include/driver.h b/include/driver.h
index d84fe35d5063..c7f5903fcea0 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -347,6 +347,9 @@ struct cdev;
/* These are used by drivers which work with direct memory accesses */
ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags);
ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags);
+ssize_t mem_copy(struct device_d *dev, void *dst, const void *src,
+ resource_size_t count, resource_size_t offset,
+ unsigned long flags);
int generic_memmap_ro(struct cdev *dev, void **map, int flags);
int generic_memmap_rw(struct cdev *dev, void **map, int flags);
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 04/13] nvmem: add support for nvmem-cells binding
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (2 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 03/13] nvmem: add support for new read-only memory (rmem) binding Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 05/13] sandbox: use nvmem on top of stickypage for reset reason Ahmad Fatoum
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Recently, nvmem cell and MTD partition bindings were made to coexist:
Partitions can now be compatible = "nvmem-cells"; which registers a
NVMEM provider and interprets its child nodes as cells. Teach barebox
about this. This allows fetching NVMEM cells from MTD partitions and
hostfiles.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/nvmem/Makefile | 2 +-
drivers/nvmem/core.c | 12 +++++-----
drivers/nvmem/partition.c | 40 ++++++++++++++++++++++++++++++++++
drivers/of/partition.c | 7 ++++++
include/linux/nvmem-provider.h | 8 +++++++
5 files changed, 63 insertions(+), 6 deletions(-)
create mode 100644 drivers/nvmem/partition.c
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 6330f3d6e681..53c02dc7850c 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -3,7 +3,7 @@
#
obj-$(CONFIG_NVMEM) += nvmem_core.o
-nvmem_core-y := core.o regmap.o
+nvmem_core-y := core.o regmap.o partition.o
obj-$(CONFIG_NVMEM_RMEM) += rmem.o
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 3c14e390de39..c060e627db4f 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -205,7 +205,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
nvmem->size = config->size;
nvmem->dev.parent = config->dev;
nvmem->bus = config->bus;
- np = config->dev->device_node;
+ np = config->cdev ? config->cdev->device_node : config->dev->device_node;
nvmem->dev.device_node = np;
nvmem->priv = config->priv;
@@ -223,10 +223,12 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
return ERR_PTR(rval);
}
- rval = nvmem_register_cdev(nvmem, config->name);
- if (rval) {
- kfree(nvmem);
- return ERR_PTR(rval);
+ if (!config->cdev) {
+ rval = nvmem_register_cdev(nvmem, config->name);
+ if (rval) {
+ kfree(nvmem);
+ return ERR_PTR(rval);
+ }
}
list_add_tail(&nvmem->node, &nvmem_devs);
diff --git a/drivers/nvmem/partition.c b/drivers/nvmem/partition.c
new file mode 100644
index 000000000000..3f0bdc58de40
--- /dev/null
+++ b/drivers/nvmem/partition.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <common.h>
+#include <driver.h>
+#include <malloc.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <init.h>
+#include <io.h>
+#include <linux/nvmem-provider.h>
+
+static int nvmem_cdev_write(void *ctx, unsigned offset, const void *val, size_t bytes)
+{
+ return cdev_write(ctx, val, bytes, offset, 0);
+}
+
+static int nvmem_cdev_read(void *ctx, unsigned offset, void *buf, size_t bytes)
+{
+ return cdev_read(ctx, buf, bytes, offset, 0);
+}
+
+static struct nvmem_bus nvmem_cdev_bus = {
+ .read = nvmem_cdev_read,
+ .write = nvmem_cdev_write,
+};
+
+struct nvmem_device *nvmem_partition_register(struct cdev *cdev)
+{
+ struct nvmem_config config = {};
+
+ config.name = cdev->name;
+ config.dev = cdev->dev;
+ config.cdev = cdev;
+ config.priv = cdev;
+ config.stride = 1;
+ config.word_size = 1;
+ config.size = cdev->size;
+ config.bus = &nvmem_cdev_bus;
+
+ return nvmem_register(&config);
+}
diff --git a/drivers/of/partition.c b/drivers/of/partition.c
index b71716218b44..b6d0523fd960 100644
--- a/drivers/of/partition.c
+++ b/drivers/of/partition.c
@@ -20,6 +20,7 @@
#include <linux/mtd/mtd.h>
#include <linux/err.h>
#include <nand.h>
+#include <linux/nvmem-provider.h>
#include <init.h>
#include <globalvar.h>
@@ -83,6 +84,12 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node)
if (new)
new->device_node = node;;
+ if (IS_ENABLED(CONFIG_NVMEM) && of_device_is_compatible(node, "nvmem-cells")) {
+ struct nvmem_device *nvmem = nvmem_partition_register(new);
+ if (IS_ERR(nvmem))
+ dev_warn(cdev->dev, "nvmem registeration failed: %pe\n", nvmem);
+ }
+
free(filename);
return new;
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 2d738983736e..a293f60c1ef3 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -26,6 +26,7 @@ struct nvmem_config {
struct device_d *dev;
const char *name;
bool read_only;
+ struct cdev *cdev;
int stride;
int word_size;
int size;
@@ -34,11 +35,13 @@ struct nvmem_config {
};
struct regmap;
+struct cdev;
#if IS_ENABLED(CONFIG_NVMEM)
struct nvmem_device *nvmem_register(const struct nvmem_config *cfg);
struct nvmem_device *nvmem_regmap_register(struct regmap *regmap, const char *name);
+struct nvmem_device *nvmem_partition_register(struct cdev *cdev);
#else
@@ -52,5 +55,10 @@ static inline struct nvmem_device *nvmem_regmap_register(struct regmap *regmap,
return ERR_PTR(-ENOSYS);
}
+static inline struct nvmem_device *nvmem_partition_register(struct cdev *cdev)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
#endif /* CONFIG_NVMEM */
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 05/13] sandbox: use nvmem on top of stickypage for reset reason
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (3 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 04/13] nvmem: add support for nvmem-cells binding Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 06/13] power: reset: port Linux generic NVMEM reboot mode driver Ahmad Fatoum
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Watchdog and system reset driver use a byte in the sticky page to
persist reset reason over reexec. So far, this was a byte outside
partitioned space. With the new nvmem-cells binding, a partition can be
dedicated to holding nvmem cells. Use that instead.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/sandbox/board/power.c | 35 ++++++++++++++++++++---------------
arch/sandbox/board/watchdog.c | 20 ++++++++++----------
arch/sandbox/dts/sandbox.dts | 18 +++++++++++++++---
3 files changed, 45 insertions(+), 28 deletions(-)
diff --git a/arch/sandbox/board/power.c b/arch/sandbox/board/power.c
index 3cc944795895..57801c8c3dc4 100644
--- a/arch/sandbox/board/power.c
+++ b/arch/sandbox/board/power.c
@@ -4,11 +4,11 @@
#include <restart.h>
#include <mach/linux.h>
#include <reset_source.h>
-#include <mfd/syscon.h>
+#include <linux/nvmem-consumer.h>
struct sandbox_power {
struct restart_handler rst_hang, rst_reexec;
- struct regmap *src;
+ struct nvmem_cell *reset_source_cell;
u32 src_offset;
};
@@ -24,16 +24,20 @@ static void sandbox_rst_hang(struct restart_handler *rst)
static void sandbox_rst_reexec(struct restart_handler *rst)
{
+ u8 reason = RESET_RST;
struct sandbox_power *power = container_of(rst, struct sandbox_power, rst_reexec);
- regmap_update_bits(power->src, power->src_offset, 0xff, RESET_RST);
+
+ if (!IS_ERR(power->reset_source_cell))
+ WARN_ON(nvmem_cell_write(power->reset_source_cell, &reason, 1) <= 0);
+
linux_reexec();
}
static int sandbox_power_probe(struct device_d *dev)
{
struct sandbox_power *power = xzalloc(sizeof(*power));
- unsigned int rst;
- int ret;
+ size_t len = 1;
+ u8 *rst;
poweroff_handler_register_fn(sandbox_poweroff);
@@ -52,20 +56,21 @@ static int sandbox_power_probe(struct device_d *dev)
if (IS_ENABLED(CONFIG_SANDBOX_REEXEC))
restart_handler_register(&power->rst_reexec);
- power->src = syscon_regmap_lookup_by_phandle(dev->device_node, "barebox,reset-source");
- if (IS_ERR(power->src))
+ power->reset_source_cell = of_nvmem_cell_get(dev->device_node, "reset-source");
+ if (IS_ERR(power->reset_source_cell)) {
+ dev_warn(dev, "No reset source info available: %pe\n", power->reset_source_cell);
return 0;
+ }
- ret = of_property_read_u32_index(dev->device_node, "barebox,reset-source", 1,
- &power->src_offset);
- if (ret)
- return 0;
+ rst = nvmem_cell_read(power->reset_source_cell, &len);
+ if (!IS_ERR(rst)) {
+ if (*rst == 0)
+ *rst = RESET_POR;
+ reset_source_set_prinst(*rst, RESET_SOURCE_DEFAULT_PRIORITY, 0);
- ret = regmap_read(power->src, power->src_offset, &rst);
- if (ret == 0 && rst == 0)
- rst = RESET_POR;
+ free(rst);
+ }
- reset_source_set_prinst(rst, RESET_SOURCE_DEFAULT_PRIORITY, 0);
return 0;
}
diff --git a/arch/sandbox/board/watchdog.c b/arch/sandbox/board/watchdog.c
index e1cff7a0bf0b..ff26a2019fac 100644
--- a/arch/sandbox/board/watchdog.c
+++ b/arch/sandbox/board/watchdog.c
@@ -6,7 +6,7 @@
#include <mach/linux.h>
#include <of.h>
#include <watchdog.h>
-#include <mfd/syscon.h>
+#include <linux/nvmem-consumer.h>
#include <reset_source.h>
struct sandbox_watchdog {
@@ -36,10 +36,9 @@ static int sandbox_watchdog_set_timeout(struct watchdog *wdd, unsigned int timeo
static int sandbox_watchdog_probe(struct device_d *dev)
{
struct device_node *np = dev->device_node;
+ struct nvmem_cell *reset_source_cell;
struct sandbox_watchdog *wd;
struct watchdog *wdd;
- struct regmap *src;
- u32 src_offset;
int ret;
wd = xzalloc(sizeof(*wd));
@@ -57,16 +56,17 @@ static int sandbox_watchdog_probe(struct device_d *dev)
return ret;
}
- src = syscon_regmap_lookup_by_phandle(np, "barebox,reset-source");
- if (IS_ERR(src))
- return 0;
+ reset_source_cell = of_nvmem_cell_get(dev->device_node, "reset-source");
+ if (IS_ERR(reset_source_cell)) {
+ dev_warn(dev, "No reset source info available: %pe\n", reset_source_cell);
+ goto out;
+ }
- ret = of_property_read_u32_index(np, "barebox,reset-source", 1, &src_offset);
- if (ret)
- return 0;
+ nvmem_cell_write(reset_source_cell, &(u8) { RESET_WDG }, 1);
- regmap_update_bits(src, src_offset, 0xff, RESET_WDG);
+ nvmem_cell_put(reset_source_cell);
+out:
dev_info(dev, "probed\n");
return 0;
}
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index e99986bb9062..7f8f1964e408 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -71,7 +71,17 @@
#address-cells = <1>;
#size-cells = <1>;
- /* 0x00+4 reserved for syscon use */
+ part_nvmem: nvmem@300 {
+ compatible = "nvmem-cells";
+ reg = <0x300 0x100>;
+ label = "nvmem";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ reset_source: reset-source@0 {
+ reg = <0x0 0x1>;
+ };
+ };
part_env: env@400 {
reg = <0x400 0x800>;
@@ -87,12 +97,14 @@
power {
compatible = "barebox,sandbox-power";
- barebox,reset-source = <&stickypage 0>;
+ nvmem-cell-names = "reset-source";
+ nvmem-cells = <&reset_source>;
};
watchdog {
compatible = "barebox,sandbox-watchdog";
- barebox,reset-source = <&stickypage 0>;
+ nvmem-cell-names = "reset-source";
+ nvmem-cells = <&reset_source>;
};
sound {
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 06/13] power: reset: port Linux generic NVMEM reboot mode driver
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (4 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 05/13] sandbox: use nvmem on top of stickypage for reset reason Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 07/13] sandbox: use nvmem-reboot-mode instead of syscon-reboot-mode Ahmad Fatoum
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Not all systems can realize their reboot mode protocol via the syscon
driver:
- There might be no registers available for use that survive a warm
reset
- There might be no warm resets and every reset resets is a cold one
For these systems, the reboot mode can instead be stored in NVMEM.
Port over the Linux nvmem-reboot-mode driver to make this possible.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/power/reset/Kconfig | 10 +++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/nvmem-reboot-mode.c | 83 +++++++++++++++++++++++++
3 files changed, 94 insertions(+)
create mode 100644 drivers/power/reset/nvmem-reboot-mode.c
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index dec1482ccd0c..e4151d8bc608 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -13,6 +13,16 @@ config SYSCON_REBOOT_MODE
Say y here will enable reboot mode driver. This will
get reboot mode arguments and store it in SYSCON mapped
register, then the bootloader can read it to take different
+
+config NVMEM_REBOOT_MODE
+ bool "Generic NVMEM reboot mode driver"
+ depends on OFDEVICE
+ depends on NVMEM
+ select REBOOT_MODE
+ help
+ Say y here will enable reboot mode driver. This will
+ get reboot mode arguments and store it in a NVMEM cell,
+ then the bootloader can read it and take different
action according to the mode.
config POWER_RESET_SYSCON
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 33d29d2d9546..10d6f2a41e22 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o
obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
+obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o
obj-$(CONFIG_POWER_RESET_SYSCON_POWEROFF) += syscon-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c
new file mode 100644
index 000000000000..b82b37d642e7
--- /dev/null
+++ b/drivers/power/reset/nvmem-reboot-mode.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Vaisala Oyj. All rights reserved.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <of.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/reboot-mode.h>
+
+struct nvmem_reboot_mode {
+ struct reboot_mode_driver reboot;
+ struct nvmem_cell *cell;
+};
+
+static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot,
+ const u32 *_magic)
+{
+ struct nvmem_reboot_mode *nvmem_rbm;
+ u32 magic = *_magic;
+ int ret;
+
+ nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot);
+
+ ret = nvmem_cell_write(nvmem_rbm->cell, &magic, sizeof(magic));
+ if (ret < 0)
+ dev_err(reboot->dev, "update reboot mode bits failed: %pe\n", ERR_PTR(ret));
+ else if (ret != 4)
+ ret = -EIO;
+ else
+ ret = 0;
+
+ return ret;
+}
+
+static int nvmem_reboot_mode_probe(struct device_d *dev)
+{
+ struct nvmem_reboot_mode *nvmem_rbm;
+ struct nvmem_cell *cell;
+ void *magicbuf;
+ size_t len;
+ int ret;
+
+ cell = nvmem_cell_get(dev, "reboot-mode");
+ if (IS_ERR(cell)) {
+ ret = PTR_ERR(cell);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to get the nvmem cell reboot-mode: %pe\n", cell);
+ return ret;
+ }
+
+ nvmem_rbm = xzalloc(sizeof(*nvmem_rbm));
+
+ nvmem_rbm->cell = cell;
+ nvmem_rbm->reboot.dev = dev;
+ nvmem_rbm->reboot.write = nvmem_reboot_mode_write;
+ nvmem_rbm->reboot.priority = 200;
+
+ magicbuf = nvmem_cell_read(nvmem_rbm->cell, &len);
+ if (IS_ERR(magicbuf) || len != 4) {
+ dev_err(dev, "error reading reboot mode: %pe\n", magicbuf);
+ return PTR_ERR(magicbuf);
+ }
+
+ ret = reboot_mode_register(&nvmem_rbm->reboot, magicbuf, 1);
+ if (ret)
+ dev_err(dev, "can't register reboot mode\n");
+
+ return ret;
+}
+
+static const struct of_device_id nvmem_reboot_mode_of_match[] = {
+ { .compatible = "nvmem-reboot-mode" },
+ { /* sentinel */ }
+};
+
+static struct driver_d nvmem_reboot_mode_driver = {
+ .probe = nvmem_reboot_mode_probe,
+ .name = "nvmem-reboot-mode",
+ .of_compatible = nvmem_reboot_mode_of_match,
+};
+coredevice_platform_driver(nvmem_reboot_mode_driver);
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 07/13] sandbox: use nvmem-reboot-mode instead of syscon-reboot-mode
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (5 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 06/13] power: reset: port Linux generic NVMEM reboot mode driver Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 08/13] sandbox: dts: fix unit-address for state partition Ahmad Fatoum
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We have some syscon-reboot-mode users in tree, but no nvmem-reboot-mode
yet. Use the new nvmem-cells binding to remedy this. Added benefit is
that we no longer access unpartitioned space; The reboot mode is now
clearly described in the device tree.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/sandbox/configs/sandbox_defconfig | 2 +-
arch/sandbox/dts/sandbox.dts | 15 ++++++++++-----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/arch/sandbox/configs/sandbox_defconfig b/arch/sandbox/configs/sandbox_defconfig
index d9d96d948155..881762444b21 100644
--- a/arch/sandbox/configs/sandbox_defconfig
+++ b/arch/sandbox/configs/sandbox_defconfig
@@ -4,7 +4,6 @@ CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
CONFIG_CONSOLE_ALLOW_COLOR=y
-CONFIG_PARTITION=y
CONFIG_PARTITION_DISK_EFI=y
CONFIG_DEFAULT_COMPRESSION_GZIP=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
@@ -126,6 +125,7 @@ CONFIG_WATCHDOG_POLLER=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_SYSCON_REBOOT_MODE=y
+CONFIG_NVMEM_REBOOT_MODE=y
CONFIG_FS_CRAMFS=y
CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 7f8f1964e408..fa9348d71f62 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -59,11 +59,12 @@
barebox,cdev; /* no caching allowed */
bmode: reboot-mode {
- compatible = "syscon-reboot-mode";
- offset = <0>;
- mask = <0xffffff00>;
- mode-normal = <0x00000000>;
- mode-loader = <0xbbbbbb00>;
+ compatible = "nvmem-reboot-mode";
+ nvmem-cells = <&reboot_mode>;
+ nvmem-cell-names = "reboot-mode";
+
+ mode-normal = <0x000000>;
+ mode-loader = <0xbbbbbb>;
};
partitions {
@@ -81,6 +82,10 @@
reset_source: reset-source@0 {
reg = <0x0 0x1>;
};
+
+ reboot_mode: reboot-mode@1 {
+ reg = <0x1 0x4>;
+ };
};
part_env: env@400 {
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 08/13] sandbox: dts: fix unit-address for state partition
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (6 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 07/13] sandbox: use nvmem-reboot-mode instead of syscon-reboot-mode Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 09/13] nvmem: add command to list nvmem devices Ahmad Fatoum
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/sandbox/dts/sandbox.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index fa9348d71f62..595a1e8eae73 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -93,7 +93,7 @@
label = "env";
};
- part_state: state@800 {
+ part_state: state@c00 {
reg = <0xC00 0x400>;
label = "state";
};
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 09/13] nvmem: add command to list nvmem devices
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (7 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 08/13] sandbox: dts: fix unit-address for state partition Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 10/13] sandbox: hostfile: move initcall to earlier postcore level Ahmad Fatoum
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
When doing development around nvmem devices, it can be useful to list
which ones exist. Add a command to facilitate this. It can be extended
in future as the need arises (e.g.export cells into the environment?).
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
commands/Kconfig | 7 +++++++
commands/Makefile | 1 +
commands/nvmem.c | 24 ++++++++++++++++++++++++
drivers/nvmem/core.c | 9 +++++++++
include/linux/nvmem-consumer.h | 2 ++
5 files changed, 43 insertions(+)
create mode 100644 commands/nvmem.c
diff --git a/commands/Kconfig b/commands/Kconfig
index 5ae3cb3dd145..7bb36d6e417e 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -206,6 +206,13 @@ config CMD_REGULATOR
the regulator command lists the currently registered regulators and
their current state.
+config CMD_NVMEM
+ bool
+ depends on NVMEM
+ prompt "nvmem command"
+ help
+ the nvmem command lists the currently registered nvmem devices.
+
config CMD_LSPCI
bool
depends on PCI
diff --git a/commands/Makefile b/commands/Makefile
index 4b45d266fd56..ba5ea19eb202 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_CMD_SAVEENV) += saveenv.o
obj-$(CONFIG_CMD_LOADENV) += loadenv.o
obj-$(CONFIG_CMD_NAND) += nand.o
obj-$(CONFIG_CMD_NANDTEST) += nandtest.o
+obj-$(CONFIG_CMD_NVMEM) += nvmem.o
obj-$(CONFIG_CMD_MEMTEST) += memtest.o
obj-$(CONFIG_CMD_MEMTESTER) += memtester/
obj-$(CONFIG_CMD_TRUE) += true.o
diff --git a/commands/nvmem.c b/commands/nvmem.c
new file mode 100644
index 000000000000..a0e3d092e3cf
--- /dev/null
+++ b/commands/nvmem.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: © 2021 Ahmad Fatoum, Pengutronix
+
+#include <common.h>
+#include <command.h>
+#include <linux/nvmem-consumer.h>
+
+static int do_nvmem(int argc, char *argv[])
+{
+ nvmem_devices_print();
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(nvmem)
+BAREBOX_CMD_HELP_TEXT("Usage: nvmem")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(nvmem)
+ .cmd = do_nvmem,
+ BAREBOX_CMD_DESC("list nvmem devices")
+ BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_HELP(cmd_nvmem_help)
+BAREBOX_CMD_END
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index c060e627db4f..ae9c965c25e2 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -49,6 +49,15 @@ struct nvmem_cell {
static LIST_HEAD(nvmem_cells);
static LIST_HEAD(nvmem_devs);
+void nvmem_devices_print(void)
+{
+ struct nvmem_device *dev;
+
+ list_for_each_entry(dev, &nvmem_devs, node) {
+ printf("%s\n", dev_name(&dev->dev));
+ }
+}
+
static ssize_t nvmem_cdev_read(struct cdev *cdev, void *buf, size_t count,
loff_t offset, unsigned long flags)
{
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 5f44cf00cdff..b979f23372a6 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -49,6 +49,8 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
int nvmem_device_cell_write(struct nvmem_device *nvmem,
struct nvmem_cell_info *info, void *buf);
+void nvmem_devices_print(void);
+
#else
static inline struct nvmem_cell *nvmem_cell_get(struct device_d *dev,
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 10/13] sandbox: hostfile: move initcall to earlier postcore level
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (8 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 09/13] nvmem: add command to list nvmem devices Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 11/13] of: of_net: sync of_get_mac_address with Linux for NVMEM support Ahmad Fatoum
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Follow-up changes will have the hostfile provide nvmem cells to other
drivers, which run at coredevice_ and device_ initcall levels.
These drivers can't defer probe though, because access to the NVMEM
cell is optional. Move the hostfile initcall earlier to allow for this.
Once deep probe support is merged and enabled for sanbox, it should
be possible to revert this commit and see no nvmem cell related
warnings.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/sandbox/board/hostfile.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c
index 4fdf2b317d57..0346590889ed 100644
--- a/arch/sandbox/board/hostfile.c
+++ b/arch/sandbox/board/hostfile.c
@@ -182,7 +182,7 @@ static struct driver_d hf_drv = {
.of_compatible = DRV_OF_COMPAT(hostfile_dt_ids),
.probe = hf_probe,
};
-device_platform_driver(hf_drv);
+postcore_platform_driver(hf_drv);
static int of_hostfile_fixup(struct device_node *root, void *ctx)
{
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 11/13] of: of_net: sync of_get_mac_address with Linux for NVMEM support
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (9 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 10/13] sandbox: hostfile: move initcall to earlier postcore level Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 12/13] net: consult device tree for ethernet address in NVMEM as fall-back Ahmad Fatoum
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We don't use of_get_mac_address anywhere, but it can come in handy as a
last resort before barebox generates a random MAC address. With the
existing implementation, that MAC address is written literally into the
DT, so it's mainly useful when barebox is booted with an external device
tree. The kernel implementation adds support for parsing the MAC address
out of a revered mac-address nvmem cell, which is much more prevalent.
Sync the implementation with Linux v5.13 in preparation for using it.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/of/of_net.c | 78 +++++++++++++++++++++++++++++++++++++--------
include/of_net.h | 21 +++++++++++-
2 files changed, 84 insertions(+), 15 deletions(-)
diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c
index cee45971950b..67015160e230 100644
--- a/drivers/of/of_net.c
+++ b/drivers/of/of_net.c
@@ -9,6 +9,7 @@
#include <net.h>
#include <of_net.h>
#include <linux/phy.h>
+#include <linux/nvmem-consumer.h>
/**
* It maps 'enum phy_interface_t' found in include/linux/phy.h
@@ -67,12 +68,55 @@ int of_get_phy_mode(struct device_node *np)
}
EXPORT_SYMBOL_GPL(of_get_phy_mode);
+static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr)
+{
+ struct property *pp = of_find_property(np, name, NULL);
+
+ if (pp && pp->length == ETH_ALEN && is_valid_ether_addr(pp->value)) {
+ memcpy(addr, pp->value, ETH_ALEN);
+ return 0;
+ }
+ return -ENODEV;
+}
+
+int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
+{
+ struct nvmem_cell *cell;
+ const void *mac;
+ size_t len;
+
+ if (!IS_ENABLED(CONFIG_NVMEM))
+ return -ENODEV;
+
+ cell = of_nvmem_cell_get(np, "mac-address");
+ if (IS_ERR(cell))
+ return PTR_ERR(cell);
+
+ mac = nvmem_cell_read(cell, &len);
+ nvmem_cell_put(cell);
+
+ if (IS_ERR(mac))
+ return PTR_ERR(mac);
+
+ if (len != ETH_ALEN || !is_valid_ether_addr(mac)) {
+ kfree(mac);
+ return -EINVAL;
+ }
+
+ memcpy(addr, mac, ETH_ALEN);
+ kfree(mac);
+
+ return 0;
+}
+
/**
* Search the device tree for the best MAC address to use. 'mac-address' is
* checked first, because that is supposed to contain to "most recent" MAC
* address. If that isn't set, then 'local-mac-address' is checked next,
- * because that is the default address. If that isn't set, then the obsolete
- * 'address' is checked, just in case we're using an old device tree.
+ * because that is the default address. If that isn't set, then the obsolete
+ * 'address' is checked, just in case we're using an old device tree. If any
+ * of the above isn't set, then try to get MAC address from nvmem cell named
+ * 'mac-address'.
*
* Note that the 'address' property is supposed to contain a virtual address of
* the register set, but some DTS files have redefined that property to be the
@@ -85,18 +129,24 @@ EXPORT_SYMBOL_GPL(of_get_phy_mode);
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
* but is all zeros.
*/
-const void *of_get_mac_address(struct device_node *np)
+int of_get_mac_address(struct device_node *np, u8 *addr)
{
- const void *p;
- int len, i;
- const char *str[] = { "mac-address", "local-mac-address", "address" };
-
- for (i = 0; i < ARRAY_SIZE(str); i++) {
- p = of_get_property(np, str[i], &len);
- if (p && (len == 6) && is_valid_ether_addr(p))
- return p;
- }
+ int ret;
+
+ if (!np)
+ return -ENODEV;
+
+ ret = of_get_mac_addr(np, "mac-address", addr);
+ if (!ret)
+ return 0;
+
+ ret = of_get_mac_addr(np, "local-mac-address", addr);
+ if (!ret)
+ return 0;
+
+ ret = of_get_mac_addr(np, "address", addr);
+ if (!ret)
+ return 0;
- return NULL;
+ return of_get_mac_addr_nvmem(np, addr);
}
-EXPORT_SYMBOL(of_get_mac_address);
diff --git a/include/of_net.h b/include/of_net.h
index f37af58303a5..36f1058cbae8 100644
--- a/include/of_net.h
+++ b/include/of_net.h
@@ -6,8 +6,27 @@
#ifndef __LINUX_OF_NET_H
#define __LINUX_OF_NET_H
+#include <linux/types.h>
#include <of.h>
+
+#ifdef CONFIG_OFDEVICE
+int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr);
+int of_get_mac_address(struct device_node *np, u8 *addr);
int of_get_phy_mode(struct device_node *np);
-const void *of_get_mac_address(struct device_node *np);
+#else
+static inline int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
+{
+ return -ENOSYS;
+}
+static inline int of_get_mac_address(struct device_node *np, u8 *addr)
+{
+ return -ENOSYS;
+}
+
+static inline int of_get_phy_mode(struct device_node *np)
+{
+ return -ENOSYS;
+}
+#endif
#endif /* __LINUX_OF_NET_H */
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 12/13] net: consult device tree for ethernet address in NVMEM as fall-back
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (10 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 11/13] of: of_net: sync of_get_mac_address with Linux for NVMEM support Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-19 3:45 ` [PATCH 13/13] sandbox: ship sample environment Ahmad Fatoum
2021-06-21 6:05 ` [PATCH 00/13] nvmem: misc enhancements Sascha Hauer
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
While barebox fixes up the mac-address into the device tree, it doesn't
care much for extracting a mac address _from_ the device tree, whether
it be from local-mac-address property or from a mac-address nvmem cell.
Fix the latter by calling of_get_mac_addr_nvmem for each Ethernet adapter.
We do this in a very late initcall, because we don't want to enforce a
probe a probe order between nvmem providers and network devices. We
can't do it at randomization time, because we need to fixup Ethernet mac
addresses, even when barebox itself doesn't ifup the netdev.
of_get_mac_addr_nvmem could be replaced by of_get_mac_address to also
parse local-mac-address and brethern, but justifying this change is left
as a future exercise.
Cc: Michael Grzeschik <m.grzeschik@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
net/eth.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/net/eth.c b/net/eth.c
index 84f99d3aa822..762c5dfb8aa8 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -11,6 +11,7 @@
#include <net.h>
#include <dma.h>
#include <of.h>
+#include <of_net.h>
#include <linux/phy.h>
#include <errno.h>
#include <malloc.h>
@@ -504,3 +505,26 @@ void led_trigger_network(enum led_trigger trigger)
led_trigger(trigger, TRIGGER_FLASH);
led_trigger(LED_TRIGGER_NET_TXRX, TRIGGER_FLASH);
}
+
+static int of_populate_ethaddr(void)
+{
+ char str[sizeof("xx:xx:xx:xx:xx:xx")];
+ struct eth_device *edev;
+ int ret;
+
+ list_for_each_entry(edev, &netdev_list, list) {
+ if (!edev->parent || is_valid_ether_addr(edev->ethaddr))
+ continue;
+
+ ret = of_get_mac_addr_nvmem(edev->parent->device_node, edev->ethaddr);
+ if (ret)
+ continue;
+
+ ethaddr_to_string(edev->ethaddr, str);
+ dev_info(&edev->dev, "Got preset MAC address from device tree: %s\n", str);
+ eth_set_ethaddr(edev, edev->ethaddr);
+ }
+
+ return 0;
+}
+postenvironment_initcall(of_populate_ethaddr);
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 13/13] sandbox: ship sample environment
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (11 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 12/13] net: consult device tree for ethernet address in NVMEM as fall-back Ahmad Fatoum
@ 2021-06-19 3:45 ` Ahmad Fatoum
2021-06-21 6:05 ` [PATCH 00/13] nvmem: misc enhancements Sascha Hauer
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2021-06-19 3:45 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The idea of the stickypage was to have a 4K memory region persistent
over resets. This region was implemented as mmap of a temporary hostfile,
which was created on first barebox start and maintained over resets.
Usability was a bit lacking however:
- The temporary files weren't deleted
- state always showed warnings and errors on first boot. The banner
telling users to ignore this wasn't best user experience
- In the same vein, the power driver had logic to handle a fresh
(zeroed) stickypage and interpret that as POR boot
We can avoid all that, by just shipping a default stickypage and
referencing that from DT. Do that.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
.gitignore | 1 +
Makefile | 2 +-
arch/sandbox/Makefile | 8 ++
arch/sandbox/board/env/init/state | 13 ---
arch/sandbox/board/hostfile.c | 19 ++--
arch/sandbox/board/power.c | 2 -
arch/sandbox/board/stickypage.bin | Bin 0 -> 4097 bytes
arch/sandbox/dts/sandbox.dts | 1 +
.../sandbox/mach-sandbox/include/mach/linux.h | 1 +
arch/sandbox/os/common.c | 83 ++++++++----------
10 files changed, 59 insertions(+), 71 deletions(-)
delete mode 100644 arch/sandbox/board/env/init/state
create mode 100644 arch/sandbox/board/stickypage.bin
diff --git a/.gitignore b/.gitignore
index d7a37b3c9b39..529bcfc2128e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ Module.symvers
/TAGS
/barebox*
/System.map
+/stickypage.bin
#
# git files that we don't want to ignore even it they are dot-files
diff --git a/Makefile b/Makefile
index f3a1bcc04cdd..6715a44d1e9e 100644
--- a/Makefile
+++ b/Makefile
@@ -1123,7 +1123,7 @@ endif # CONFIG_MODULES
# Directories & files removed with 'make clean'
CLEAN_DIRS += $(MODVERDIR)
-CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \
+CLEAN_FILES += barebox System.map stickypage.bin include/generated/barebox_default_env.h \
.tmp_version .tmp_barebox* barebox.bin barebox.map \
.tmp_kallsyms* barebox.ldr compile_commands.json \
scripts/bareboxenv-target barebox-flash-image \
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index 5fc7e227be67..5e35d598a232 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -75,3 +75,11 @@ common-y += $(BOARD) arch/sandbox/os/ arch/sandbox/lib/
common-$(CONFIG_OFTREE) += arch/sandbox/dts/
CLEAN_FILES += $(BOARD)/barebox.lds
+
+quiet_cmd_install = INSTALL $@
+ cmd_install = install $< $@
+
+stickypage.bin: arch/sandbox/board/stickypage.bin
+ $(call cmd,install)
+
+all: stickypage.bin
diff --git a/arch/sandbox/board/env/init/state b/arch/sandbox/board/env/init/state
deleted file mode 100644
index b8a2b42a53ea..000000000000
--- a/arch/sandbox/board/env/init/state
+++ /dev/null
@@ -1,13 +0,0 @@
-if [ "x$state.dirty" != "x1" -o $global.system.reset != "POR" ]; then
- exit
-fi
-
-source /env/data/ansi-colors
-
-echo -e $CYAN
-echo "*******************************************************"
-echo "*** Inconsistent barebox state buckets detected ***"
-echo "*** This is normal for a first boot ***"
-echo "*** barebox will repair them on next poweroff/reset ***"
-echo "*******************************************************"
-echo -e -n $NC
diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c
index 0346590889ed..f11062197934 100644
--- a/arch/sandbox/board/hostfile.c
+++ b/arch/sandbox/board/hostfile.c
@@ -232,12 +232,21 @@ static int of_hostfile_map_fixup(struct device_node *root, void *ctx)
for_each_compatible_node_from(node, root, NULL, hostfile_dt_ids->compatible) {
struct hf_info hf = {};
uint64_t reg[2] = {};
- bool no_filename;
hf.devname = node->name;
ret = of_property_read_string(node, "barebox,filename", &hf.filename);
- no_filename = ret;
+ if (ret) {
+ pr_err("skipping nameless hostfile %s\n", hf.devname);
+ continue;
+ }
+
+ if (memcmp(hf.filename, "$build/", 7) == 0) {
+ char *fullpath = xasprintf("%s/%s", linux_get_builddir(),
+ hf.filename + sizeof "$build/" - 1);
+
+ hf.filename = fullpath;
+ }
hf.is_blockdev = of_property_read_bool(node, "barebox,blockdev");
hf.is_cdev = of_property_read_bool(node, "barebox,cdev");
@@ -263,12 +272,6 @@ static int of_hostfile_map_fixup(struct device_node *root, void *ctx)
if (ret)
goto out;
- if (no_filename) {
- ret = of_property_write_string(node, "barebox,filename", hf.filename);
- if (ret)
- goto out;
- }
-
ret = of_property_write_u32(node, "barebox,fd", hf.fd);
out:
if (ret)
diff --git a/arch/sandbox/board/power.c b/arch/sandbox/board/power.c
index 57801c8c3dc4..3112c80348e7 100644
--- a/arch/sandbox/board/power.c
+++ b/arch/sandbox/board/power.c
@@ -64,8 +64,6 @@ static int sandbox_power_probe(struct device_d *dev)
rst = nvmem_cell_read(power->reset_source_cell, &len);
if (!IS_ERR(rst)) {
- if (*rst == 0)
- *rst = RESET_POR;
reset_source_set_prinst(*rst, RESET_SOURCE_DEFAULT_PRIORITY, 0);
free(rst);
diff --git a/arch/sandbox/board/stickypage.bin b/arch/sandbox/board/stickypage.bin
new file mode 100644
index 0000000000000000000000000000000000000000..e507ca656e6488ff5cebbdda8169f1ab153abb19
GIT binary patch
literal 4097
zcmZQz7zLvtFmgkHapZa(?DNW9{guc;01FSE%sKVQ;-l=*5Eu=C(GVC7fzc2c4T0ek
z0-yheC`$mnv#iZ}6$1kYgJgm2?vzezLr^<_nFwzVw0<I-II3hc1V%#uM+k5M0H)F!
AIsgCw
literal 0
HcmV?d00001
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 595a1e8eae73..5b2cab219e2a 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -55,6 +55,7 @@
stickypage: stickypage {
compatible = "barebox,hostfile", "syscon", "simple-mfd";
+ barebox,filename = "$build/stickypage.bin";
reg = <0 0 0 4096>;
barebox,cdev; /* no caching allowed */
diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h
index 831e170d90ef..453813952e55 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -13,6 +13,7 @@ int linux_register_device(const char *name, void *start, void *end);
int tap_alloc(const char *dev);
uint64_t linux_get_time(void);
int linux_open(const char *filename, int readwrite);
+const char *linux_get_builddir(void);
int linux_open_hostfile(struct hf_info *hf);
int linux_read(int fd, void *buf, size_t count);
int linux_read_nonblock(int fd, void *buf, size_t count);
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c
index 4eb6d37fffc1..e36e3972bc0d 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -127,9 +127,23 @@ void __attribute__((noreturn)) linux_exit(void)
exit(0);
}
-static size_t saved_argv_len;
static char **saved_argv;
+static int selfpath(char *buf, size_t len)
+{
+ int ret;
+
+ /* we must follow the symlink, so we can exec an updated executable */
+ ret = readlink("/proc/self/exe", buf, len - 1);
+ if (ret < 0)
+ return ret;
+
+ if (0 < ret && ret < len - 1)
+ buf[ret] = '\0';
+
+ return ret;
+}
+
void linux_reexec(void)
{
char buf[4097];
@@ -138,9 +152,8 @@ void linux_reexec(void)
cookmode();
/* we must follow the symlink, so we can exec an updated executable */
- ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
- if (0 < ret && ret < sizeof(buf) - 1) {
- buf[ret] = '\0';
+ ret = selfpath(buf, sizeof(buf));
+ if (ret > 0) {
execv(buf, saved_argv);
if (!strcmp(&buf[ret - DELETED_OFFSET], " (deleted)")) {
printf("barebox image on disk changed. Loading new.\n");
@@ -317,6 +330,21 @@ static int add_image(const char *_str, char *devname_template, int *devname_numb
return ret;
}
+const char *linux_get_builddir(void)
+{
+ static char path[4097];
+ int ret;
+
+ if (!path[0]) {
+ ret = selfpath(path, sizeof(path));
+ if (ret < 0)
+ return NULL;
+ dirname(path);
+ }
+
+ return path;
+}
+
int linux_open_hostfile(struct hf_info *hf)
{
char *buf = NULL;
@@ -327,45 +355,10 @@ int linux_open_hostfile(struct hf_info *hf)
hf->filename ? "" : "initially un", hf->filename ?: "",
hf->is_readonly ? "(ro)" : "");
- if (hf->filename) {
- fd = hf->fd = open(hf->filename, (hf->is_readonly ? O_RDONLY : O_RDWR) | O_CLOEXEC);
- } else {
- char *filename;
- int ret;
-
- ret = asprintf(&buf, "--image=%s=/tmp/barebox-hostfileXXXXXX", hf->devname);
- if (ret < 0) {
- perror("asprintf");
- goto err_out;
- }
-
- filename = buf + strlen("--image==") + strlen(hf->devname);
-
- fd = hf->fd = mkstemp(filename);
- if (fd >= 0) {
- ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
- if (ret < 0) {
- perror("fcntl");
- goto err_out;
- }
-
- ret = ftruncate(fd, hf->size);
- if (ret < 0) {
- perror("ftruncate");
- goto err_out;
- }
-
- hf->filename = filename;
-
- saved_argv = realloc(saved_argv,
- ++saved_argv_len * sizeof(*saved_argv));
- if (!saved_argv)
- exit(1);
- saved_argv[saved_argv_len - 2] = buf;
- saved_argv[saved_argv_len - 1] = NULL;
- }
- }
+ if (!hf->filename)
+ return -ENOENT;
+ fd = hf->fd = open(hf->filename, (hf->is_readonly ? O_RDONLY : O_RDWR) | O_CLOEXEC);
if (fd < 0) {
perror("open");
goto err_out;
@@ -517,11 +510,7 @@ int main(int argc, char *argv[])
}
}
- saved_argv_len = argc + 1;
- saved_argv = calloc(saved_argv_len, sizeof(*saved_argv));
- if (!saved_argv)
- exit(1);
- memcpy(saved_argv, argv, saved_argv_len * sizeof(*saved_argv));
+ saved_argv = argv;
ram = malloc(malloc_size);
if (!ram) {
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 00/13] nvmem: misc enhancements
2021-06-19 3:45 [PATCH 00/13] nvmem: misc enhancements Ahmad Fatoum
` (12 preceding siblings ...)
2021-06-19 3:45 ` [PATCH 13/13] sandbox: ship sample environment Ahmad Fatoum
@ 2021-06-21 6:05 ` Sascha Hauer
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2021-06-21 6:05 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: barebox
On Sat, Jun 19, 2021 at 05:45:03AM +0200, Ahmad Fatoum wrote:
> Series implements some of the new NVMEM bindings:
>
> - New providers:
> - nvmem-cells (for MTD partitions)
> - nvmem-rmem (memory regions passed by previous boot stages)
>
> - New consumers:
> - Network devices: Unlike Linux, we do that for all drivers
> in generic code. This is done postenvironment, so network drivers,
> board code and other (OTP) drivers are not overridden.
> - nvmem-reboot-mode: To go along with syscon-reboot-mode
> - nvmem command: This one only prints registered devices for now
>
> And changes sandbox to make use of it.
>
> Ahmad Fatoum (13):
> nvmem: bsec: remove unused, left-over, struct member
> nvmem: treat devices without nvmem_bus::write as read only
> nvmem: add support for new read-only memory (rmem) binding
> nvmem: add support for nvmem-cells binding
> sandbox: use nvmem on top of stickypage for reset reason
> power: reset: port Linux generic NVMEM reboot mode driver
> sandbox: use nvmem-reboot-mode instead of syscon-reboot-mode
> sandbox: dts: fix unit-address for state partition
> nvmem: add command to list nvmem devices
> sandbox: hostfile: move initcall to earlier postcore level
> of: of_net: sync of_get_mac_address with Linux for NVMEM support
> net: consult device tree for ethernet address in NVMEM as fall-back
> sandbox: ship sample environment
Applied, thanks
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread