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 .gitignore | 1 + Makefile | 2 +- arch/sandbox/Makefile | 8 ++ arch/sandbox/board/env/init/state | 13 --- arch/sandbox/board/hostfile.c | 21 +++-- arch/sandbox/board/power.c | 33 +++---- arch/sandbox/board/stickypage.bin | Bin 0 -> 4097 bytes arch/sandbox/board/watchdog.c | 20 ++--- arch/sandbox/configs/sandbox_defconfig | 2 +- arch/sandbox/dts/sandbox.dts | 36 ++++++-- .../sandbox/mach-sandbox/include/mach/linux.h | 1 + arch/sandbox/os/common.c | 83 ++++++++---------- commands/Kconfig | 7 ++ commands/Makefile | 1 + commands/nvmem.c | 24 +++++ drivers/nvmem/Kconfig | 6 ++ drivers/nvmem/Makefile | 4 +- drivers/nvmem/bsec.c | 1 - drivers/nvmem/core.c | 25 ++++-- drivers/nvmem/partition.c | 40 +++++++++ drivers/nvmem/rmem.c | 67 ++++++++++++++ drivers/of/base.c | 21 ++++- drivers/of/of_net.c | 78 +++++++++++++--- drivers/of/partition.c | 7 ++ drivers/power/reset/Kconfig | 10 +++ drivers/power/reset/Makefile | 1 + drivers/power/reset/nvmem-reboot-mode.c | 83 ++++++++++++++++++ fs/devfs-core.c | 2 +- include/driver.h | 3 + include/linux/nvmem-consumer.h | 2 + include/linux/nvmem-provider.h | 8 ++ include/of_net.h | 21 ++++- net/eth.c | 24 +++++ 33 files changed, 521 insertions(+), 134 deletions(-) delete mode 100644 arch/sandbox/board/env/init/state create mode 100644 arch/sandbox/board/stickypage.bin create mode 100644 commands/nvmem.c create mode 100644 drivers/nvmem/partition.c create mode 100644 drivers/nvmem/rmem.c create mode 100644 drivers/power/reset/nvmem-reboot-mode.c -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
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
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
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
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
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
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
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
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
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
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
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
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
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
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