summaryrefslogtreecommitdiffstats
path: root/arch/sandbox/board
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2020-10-14 12:46:52 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2020-10-14 12:46:52 +0200
commitbee1da7fcc005edab18fde60fd2ce956d12c5e18 (patch)
tree77d02747d657192acb10500f979b83e20d0447a3 /arch/sandbox/board
parentc29ce8d93f9403c3ce6ccc5e82fb7a7be41d6659 (diff)
parent765ecaf52b834278a2449fcb097754a3aae9aa96 (diff)
downloadbarebox-bee1da7fcc005edab18fde60fd2ce956d12c5e18.tar.gz
barebox-bee1da7fcc005edab18fde60fd2ce956d12c5e18.tar.xz
Merge branch 'for-next/sandbox' into master
Diffstat (limited to 'arch/sandbox/board')
-rw-r--r--arch/sandbox/board/Makefile3
-rw-r--r--arch/sandbox/board/devices.c3
-rw-r--r--arch/sandbox/board/dtb.c28
-rw-r--r--arch/sandbox/board/env/init/state12
-rw-r--r--arch/sandbox/board/hostfile.c94
-rw-r--r--arch/sandbox/board/power.c82
-rw-r--r--arch/sandbox/board/poweroff.c42
-rw-r--r--arch/sandbox/board/watchdog.c84
8 files changed, 261 insertions, 87 deletions
diff --git a/arch/sandbox/board/Makefile b/arch/sandbox/board/Makefile
index 26f6cb1922..c504c967de 100644
--- a/arch/sandbox/board/Makefile
+++ b/arch/sandbox/board/Makefile
@@ -4,7 +4,8 @@ obj-y += hostfile.o
obj-y += console.o
obj-y += devices.o
obj-y += dtb.o
-obj-y += poweroff.o
+obj-y += power.o
obj-y += dev-random.o
+obj-y += watchdog.o
extra-y += barebox.lds
diff --git a/arch/sandbox/board/devices.c b/arch/sandbox/board/devices.c
index 1fd1913ae6..26152a8b90 100644
--- a/arch/sandbox/board/devices.c
+++ b/arch/sandbox/board/devices.c
@@ -26,9 +26,6 @@ static int sandbox_device_init(void)
{
struct device_d *dev, *tmp;
- barebox_set_model("barebox sandbox");
- barebox_set_hostname("barebox");
-
list_for_each_entry_safe(dev, tmp, &sandbox_device_list, list) {
/* reset the list_head before registering for real */
dev->list.prev = NULL;
diff --git a/arch/sandbox/board/dtb.c b/arch/sandbox/board/dtb.c
index d11bde0249..4a8cbfb26f 100644
--- a/arch/sandbox/board/dtb.c
+++ b/arch/sandbox/board/dtb.c
@@ -32,32 +32,14 @@ int barebox_register_dtb(const void *new_dtb)
return 0;
}
+extern char __dtb_sandbox_start[];
+
static int of_sandbox_init(void)
{
- struct device_node *root;
- int ret;
-
- if (dtb) {
- root = of_unflatten_dtb(dtb);
- } else {
- root = of_new_node(NULL, NULL);
-
- ret = of_property_write_u32(root, "#address-cells", 2);
- if (ret)
- return ret;
-
- ret = of_property_write_u32(root, "#size-cells", 2);
- if (ret)
- return ret;
- }
-
- if (IS_ERR(root))
- return PTR_ERR(root);
+ if (!dtb)
+ dtb = __dtb_sandbox_start;
- of_set_root_node(root);
- of_fix_tree(root);
- if (IS_ENABLED(CONFIG_OFDEVICE))
- of_probe();
+ barebox_register_fdt(dtb);
return 0;
}
diff --git a/arch/sandbox/board/env/init/state b/arch/sandbox/board/env/init/state
new file mode 100644
index 0000000000..0b8e40409f
--- /dev/null
+++ b/arch/sandbox/board/env/init/state
@@ -0,0 +1,12 @@
+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 on first boot ***"
+echo "*** barebox will repair them on next shutdown ***"
+echo "*****************************************************************"
+echo -e -n $NC
diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c
index 63530bd25e..e3e38b7119 100644
--- a/arch/sandbox/board/hostfile.c
+++ b/arch/sandbox/board/hostfile.c
@@ -124,9 +124,6 @@ static int hf_probe(struct device_d *dev)
if (err)
return err;
- if (!priv->fd)
- priv->fd = linux_open(priv->filename, true);
-
if (priv->fd < 0)
return priv->fd;
@@ -194,37 +191,98 @@ static int of_hostfile_fixup(struct device_node *root, void *ctx)
{
struct hf_info *hf = ctx;
struct device_node *node;
- uint32_t reg[] = {
- hf->base >> 32,
- hf->base,
- hf->size >> 32,
- hf->size
- };
+ bool name_only = false;
int ret;
- node = of_new_node(root, hf->devname);
+ node = of_get_child_by_name(root, hf->devname);
+ if (node)
+ name_only = true;
+ else
+ node = of_new_node(root, hf->devname);
- ret = of_property_write_string(node, "compatible", hostfile_dt_ids->compatible);
+ ret = of_property_write_string(node, "barebox,filename", hf->filename);
if (ret)
return ret;
- ret = of_property_write_u32_array(node, "reg", reg, ARRAY_SIZE(reg));
+ if (name_only)
+ return 0;
+
+ ret = of_property_write_string(node, "compatible", hostfile_dt_ids->compatible);
if (ret)
return ret;
- ret = of_property_write_u32(node, "barebox,fd", hf->fd);
+ ret = of_property_write_bool(node, "barebox,blockdev", hf->is_blockdev);
if (ret)
return ret;
- ret = of_property_write_string(node, "barebox,filename", hf->filename);
-
- if (hf->is_blockdev)
- ret = of_property_write_bool(node, "barebox,blockdev", true);
+ ret = of_property_write_bool(node, "barebox,cdev", hf->is_cdev);
+ if (ret)
+ return ret;
- return ret;
+ return of_property_write_bool(node, "barebox,read-only", hf->is_readonly);
}
int barebox_register_filedev(struct hf_info *hf)
{
return of_register_fixup(of_hostfile_fixup, hf);
}
+
+static int of_hostfile_map_fixup(struct device_node *root, void *ctx)
+{
+ struct device_node *node;
+ int ret;
+
+ 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;
+
+ hf.is_blockdev = of_property_read_bool(node, "barebox,blockdev");
+ hf.is_cdev = of_property_read_bool(node, "barebox,cdev");
+ hf.is_readonly = of_property_read_bool(node, "barebox,read-only");
+
+ of_property_read_u64_array(node, "reg", reg, ARRAY_SIZE(reg));
+
+ hf.base = reg[0];
+ hf.size = reg[1];
+
+ ret = linux_open_hostfile(&hf);
+ if (ret)
+ goto out;
+
+ reg[0] = hf.base;
+ reg[1] = hf.size;
+
+ ret = of_property_write_u64_array(node, "reg", reg, ARRAY_SIZE(reg));
+ if (ret)
+ goto out;
+
+ ret = of_property_write_bool(node, "barebox,blockdev", hf.is_blockdev);
+ 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)
+ pr_err("error fixing up %s: %pe\n", hf.devname, ERR_PTR(ret));
+ }
+
+ return 0;
+}
+
+static int barebox_fixup_filedevs(void)
+{
+ return of_register_fixup(of_hostfile_map_fixup, NULL);
+}
+pure_initcall(barebox_fixup_filedevs);
diff --git a/arch/sandbox/board/power.c b/arch/sandbox/board/power.c
new file mode 100644
index 0000000000..3cc9447958
--- /dev/null
+++ b/arch/sandbox/board/power.c
@@ -0,0 +1,82 @@
+#include <common.h>
+#include <driver.h>
+#include <poweroff.h>
+#include <restart.h>
+#include <mach/linux.h>
+#include <reset_source.h>
+#include <mfd/syscon.h>
+
+struct sandbox_power {
+ struct restart_handler rst_hang, rst_reexec;
+ struct regmap *src;
+ u32 src_offset;
+};
+
+static void sandbox_poweroff(struct poweroff_handler *poweroff)
+{
+ linux_exit();
+}
+
+static void sandbox_rst_hang(struct restart_handler *rst)
+{
+ linux_hang();
+}
+
+static void sandbox_rst_reexec(struct restart_handler *rst)
+{
+ struct sandbox_power *power = container_of(rst, struct sandbox_power, rst_reexec);
+ regmap_update_bits(power->src, power->src_offset, 0xff, RESET_RST);
+ linux_reexec();
+}
+
+static int sandbox_power_probe(struct device_d *dev)
+{
+ struct sandbox_power *power = xzalloc(sizeof(*power));
+ unsigned int rst;
+ int ret;
+
+ poweroff_handler_register_fn(sandbox_poweroff);
+
+ power->rst_hang = (struct restart_handler) {
+ .name = "hang",
+ .restart = sandbox_rst_hang
+ };
+
+ power->rst_reexec = (struct restart_handler) {
+ .name = "reexec", .priority = 200,
+ .restart = sandbox_rst_reexec,
+ };
+
+ restart_handler_register(&power->rst_hang);
+
+ 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))
+ return 0;
+
+ ret = of_property_read_u32_index(dev->device_node, "barebox,reset-source", 1,
+ &power->src_offset);
+ if (ret)
+ return 0;
+
+ ret = regmap_read(power->src, power->src_offset, &rst);
+ if (ret == 0 && rst == 0)
+ rst = RESET_POR;
+
+ reset_source_set_prinst(rst, RESET_SOURCE_DEFAULT_PRIORITY, 0);
+ return 0;
+}
+
+static __maybe_unused struct of_device_id sandbox_power_dt_ids[] = {
+ { .compatible = "barebox,sandbox-power" },
+ { /* sentinel */ }
+};
+
+static struct driver_d sandbox_power_drv = {
+ .name = "sandbox-power",
+ .of_compatible = sandbox_power_dt_ids,
+ .probe = sandbox_power_probe,
+};
+coredevice_platform_driver(sandbox_power_drv);
diff --git a/arch/sandbox/board/poweroff.c b/arch/sandbox/board/poweroff.c
deleted file mode 100644
index 8ce739af72..0000000000
--- a/arch/sandbox/board/poweroff.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <common.h>
-#include <init.h>
-#include <poweroff.h>
-#include <restart.h>
-#include <mach/linux.h>
-
-static void sandbox_poweroff(struct poweroff_handler *poweroff)
-{
- linux_exit();
-}
-
-static void sandbox_rst_hang(struct restart_handler *rst)
-{
- linux_hang();
-}
-
-static struct restart_handler rst_hang = {
- .name = "hang",
- .restart = sandbox_rst_hang
-};
-
-static void sandbox_rst_reexec(struct restart_handler *rst)
-{
- linux_reexec();
-}
-
-static struct restart_handler rst_reexec = {
- .name = "reexec", .priority = 200,
- .restart = sandbox_rst_reexec,
-};
-
-static int poweroff_register_feature(void)
-{
- poweroff_handler_register_fn(sandbox_poweroff);
- restart_handler_register(&rst_hang);
-
- if (IS_ENABLED(CONFIG_SANDBOX_REEXEC))
- restart_handler_register(&rst_reexec);
-
- return 0;
-}
-coredevice_initcall(poweroff_register_feature);
diff --git a/arch/sandbox/board/watchdog.c b/arch/sandbox/board/watchdog.c
new file mode 100644
index 0000000000..336451282f
--- /dev/null
+++ b/arch/sandbox/board/watchdog.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <errno.h>
+#include <driver.h>
+#include <mach/linux.h>
+#include <of.h>
+#include <watchdog.h>
+#include <mfd/syscon.h>
+#include <reset_source.h>
+
+struct sandbox_watchdog {
+ struct watchdog wdd;
+ bool cant_disable :1;
+};
+
+static inline struct sandbox_watchdog *to_sandbox_watchdog(struct watchdog *wdd)
+{
+ return container_of(wdd, struct sandbox_watchdog, wdd);
+}
+
+static int sandbox_watchdog_set_timeout(struct watchdog *wdd, unsigned int timeout)
+{
+ struct sandbox_watchdog *wd = to_sandbox_watchdog(wdd);
+
+ if (!timeout && wd->cant_disable)
+ return -ENOSYS;
+
+ if (timeout > wdd->timeout_max)
+ return -EINVAL;
+
+ return linux_watchdog_set_timeout(timeout);
+}
+
+static int sandbox_watchdog_probe(struct device_d *dev)
+{
+ struct device_node *np = dev->device_node;
+ struct sandbox_watchdog *wd;
+ struct watchdog *wdd;
+ struct regmap *src;
+ u32 src_offset;
+ int ret;
+
+ wd = xzalloc(sizeof(*wd));
+
+ wdd = &wd->wdd;
+ wdd->hwdev = dev;
+ wdd->set_timeout = sandbox_watchdog_set_timeout;
+ wdd->timeout_max = 1000;
+
+ wd->cant_disable = of_property_read_bool(np, "barebox,cant-disable");
+
+ ret = watchdog_register(wdd);
+ if (ret) {
+ dev_err(dev, "Failed to register watchdog device\n");
+ return ret;
+ }
+
+ src = syscon_regmap_lookup_by_phandle(np, "barebox,reset-source");
+ if (IS_ERR(src))
+ return 0;
+
+ ret = of_property_read_u32_index(np, "barebox,reset-source", 1, &src_offset);
+ if (ret)
+ return 0;
+
+ regmap_update_bits(src, src_offset, 0xff, RESET_WDG);
+
+ dev_info(dev, "probed\n");
+ return 0;
+}
+
+
+static __maybe_unused struct of_device_id sandbox_watchdog_dt_ids[] = {
+ { .compatible = "barebox,sandbox-watchdog" },
+ { /* sentinel */ }
+};
+
+static struct driver_d sandbox_watchdog_drv = {
+ .name = "sandbox-watchdog",
+ .of_compatible = sandbox_watchdog_dt_ids,
+ .probe = sandbox_watchdog_probe,
+};
+device_platform_driver(sandbox_watchdog_drv);