diff options
Diffstat (limited to 'arch/sandbox/board')
-rw-r--r-- | arch/sandbox/board/.gitignore | 2 | ||||
-rw-r--r-- | arch/sandbox/board/Makefile | 8 | ||||
-rw-r--r-- | arch/sandbox/board/barebox.lds.S | 4 | ||||
-rw-r--r-- | arch/sandbox/board/board.c | 25 | ||||
-rw-r--r-- | arch/sandbox/board/clock.c | 4 | ||||
-rw-r--r-- | arch/sandbox/board/console.c | 7 | ||||
-rw-r--r-- | arch/sandbox/board/dev-random.c | 2 | ||||
-rw-r--r-- | arch/sandbox/board/devices.c | 11 | ||||
-rw-r--r-- | arch/sandbox/board/dtb.c | 33 | ||||
-rw-r--r-- | arch/sandbox/board/env/nv/autoboot | 1 | ||||
-rw-r--r-- | arch/sandbox/board/hostfile.c | 246 | ||||
-rw-r--r-- | arch/sandbox/board/led.c | 68 | ||||
-rw-r--r-- | arch/sandbox/board/power.c | 99 | ||||
-rw-r--r-- | arch/sandbox/board/poweroff.c | 17 | ||||
-rw-r--r-- | arch/sandbox/board/stickypage.S | 29 | ||||
-rw-r--r-- | arch/sandbox/board/watchdog.c | 77 |
16 files changed, 512 insertions, 121 deletions
diff --git a/arch/sandbox/board/.gitignore b/arch/sandbox/board/.gitignore index d1165788c9..03987a7009 100644 --- a/arch/sandbox/board/.gitignore +++ b/arch/sandbox/board/.gitignore @@ -1 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + barebox.lds diff --git a/arch/sandbox/board/Makefile b/arch/sandbox/board/Makefile index 26f6cb1922..b4bab02163 100644 --- a/arch/sandbox/board/Makefile +++ b/arch/sandbox/board/Makefile @@ -1,10 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only + obj-y += board.o obj-y += clock.o 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 +obj-$(CONFIG_LED) += led.o extra-y += barebox.lds + +obj-y += stickypage.o diff --git a/arch/sandbox/board/barebox.lds.S b/arch/sandbox/board/barebox.lds.S index 7a5a8eb1e7..ab2801f3d2 100644 --- a/arch/sandbox/board/barebox.lds.S +++ b/arch/sandbox/board/barebox.lds.S @@ -1,4 +1,6 @@ -#include <asm-generic/barebox.lds.h> +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <asm/barebox.lds.h> SECTIONS { diff --git a/arch/sandbox/board/board.c b/arch/sandbox/board/board.c index ad2bc910c3..c8d1c99897 100644 --- a/arch/sandbox/board/board.c +++ b/arch/sandbox/board/board.c @@ -3,9 +3,6 @@ * * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix * - * See file CREDITS for list of people who contributed to this - * project. - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. @@ -23,6 +20,7 @@ #include <mach/linux.h> #include <init.h> #include <errno.h> +#include <deep-probe.h> #include <fb.h> struct fb_videomode mode = { @@ -31,23 +29,23 @@ struct fb_videomode mode = { .yres = 480, }; -static struct device_d tap_device = { +static struct device tap_device = { .id = DEVICE_ID_DYNAMIC, .name = "tap", }; -static struct device_d sdl_device = { +static struct device sdl_device = { .id = DEVICE_ID_DYNAMIC, .name = "sdlfb", .platform_data = &mode, }; -static struct device_d devrandom_device = { +static struct device devrandom_device = { .id = DEVICE_ID_DYNAMIC, .name = "devrandom", }; -static int devices_init(void) +static int devices_init(struct device *dev) { platform_device_register(&tap_device); @@ -64,4 +62,15 @@ static int devices_init(void) return 0; } -device_initcall(devices_init); +static struct of_device_id sandbox_dt_ids[] = { + { .compatible = "barebox,sandbox" }, + { /* sentinel */ } +}; +BAREBOX_DEEP_PROBE_ENABLE(sandbox_dt_ids); + +static struct driver sandbox_board_drv = { + .name = "sandbox-board", + .of_compatible = sandbox_dt_ids, + .probe = devices_init, +}; +device_platform_driver(sandbox_board_drv); diff --git a/arch/sandbox/board/clock.c b/arch/sandbox/board/clock.c index bdea89f002..1787fb5786 100644 --- a/arch/sandbox/board/clock.c +++ b/arch/sandbox/board/clock.c @@ -3,9 +3,6 @@ * * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix * - * See file CREDITS for list of people who contributed to this - * project. - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. @@ -31,6 +28,7 @@ static struct clocksource cs = { .read = linux_clocksource_read, .mask = CLOCKSOURCE_MASK(32), .shift = 10, + .priority = 80, }; static int clocksource_init (void) diff --git a/arch/sandbox/board/console.c b/arch/sandbox/board/console.c index 4b251e9087..274ef67aef 100644 --- a/arch/sandbox/board/console.c +++ b/arch/sandbox/board/console.c @@ -3,9 +3,6 @@ * * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix * - * See file CREDITS for list of people who contributed to this - * project. - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. @@ -24,10 +21,10 @@ int barebox_register_console(int stdinfd, int stdoutfd) { - struct device_d *dev; + struct device *dev; struct linux_console_data *data; - dev = xzalloc(sizeof(struct device_d) + sizeof(struct linux_console_data)); + dev = xzalloc(sizeof(struct device) + sizeof(struct linux_console_data)); data = (struct linux_console_data *)(dev + 1); diff --git a/arch/sandbox/board/dev-random.c b/arch/sandbox/board/dev-random.c index 60295e9fce..b62e8cc0d7 100644 --- a/arch/sandbox/board/dev-random.c +++ b/arch/sandbox/board/dev-random.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-only + #include <common.h> #include <mach/linux.h> diff --git a/arch/sandbox/board/devices.c b/arch/sandbox/board/devices.c index 72e62552a3..ecd24e9207 100644 --- a/arch/sandbox/board/devices.c +++ b/arch/sandbox/board/devices.c @@ -6,13 +6,15 @@ #include <common.h> #include <driver.h> -#include <mach/linux.h> #include <init.h> #include <mach/linux.h> +#include <asm/io.h> + +unsigned char __pci_iobase[IO_SPACE_LIMIT]; static LIST_HEAD(sandbox_device_list); -int sandbox_add_device(struct device_d *dev) +int sandbox_add_device(struct device *dev) { list_add(&dev->list, &sandbox_device_list); @@ -21,10 +23,7 @@ int sandbox_add_device(struct device_d *dev) static int sandbox_device_init(void) { - struct device_d *dev, *tmp; - - barebox_set_model("barebox sandbox"); - barebox_set_hostname("barebox"); + struct device *dev, *tmp; list_for_each_entry_safe(dev, tmp, &sandbox_device_list, list) { /* reset the list_head before registering for real */ diff --git a/arch/sandbox/board/dtb.c b/arch/sandbox/board/dtb.c index af4a64a9c7..98d2e774b8 100644 --- a/arch/sandbox/board/dtb.c +++ b/arch/sandbox/board/dtb.c @@ -2,9 +2,6 @@ * Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix * Copyright (c) 2015 Marc Kleine-Budde <mkl@pengutronix.de>, Pengutronix * - * See file CREDITS for list of people who contributed to this - * project. - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. @@ -35,33 +32,13 @@ 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; + if (!dtb) + dtb = __dtb_sandbox_start; - ret = of_property_write_u32(root, "#size-cells", 1); - if (ret) - return ret; - } - - if (IS_ERR(root)) - return PTR_ERR(root); - - of_set_root_node(root); - of_fix_tree(root); - if (IS_ENABLED(CONFIG_OFDEVICE)) - of_probe(); - - return 0; + return barebox_register_fdt(dtb); } core_initcall(of_sandbox_init); diff --git a/arch/sandbox/board/env/nv/autoboot b/arch/sandbox/board/env/nv/autoboot new file mode 100644 index 0000000000..f7d13fd046 --- /dev/null +++ b/arch/sandbox/board/env/nv/autoboot @@ -0,0 +1 @@ +abort diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c index e5a7580d07..7afad95b6d 100644 --- a/arch/sandbox/board/hostfile.c +++ b/arch/sandbox/board/hostfile.c @@ -3,9 +3,6 @@ * * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix * - * See file CREDITS for list of people who contributed to this - * project. - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. @@ -19,25 +16,29 @@ #include <common.h> #include <driver.h> +#include <block.h> +#include <disks.h> #include <malloc.h> #include <mach/linux.h> #include <init.h> #include <errno.h> #include <linux/err.h> #include <mach/hostfile.h> +#include <featctrl.h> #include <xfuncs.h> -#include <linux/err.h> - struct hf_priv { - struct cdev cdev; + union { + struct block_device blk; + struct cdev cdev; + }; const char *filename; int fd; + struct feature_controller feat; }; -static ssize_t hf_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags) +static ssize_t hf_read(struct hf_priv *priv, void *buf, size_t count, loff_t offset, ulong flags) { - struct hf_priv *priv= cdev->priv; int fd = priv->fd; if (linux_lseek(fd, offset) != offset) @@ -46,9 +47,8 @@ static ssize_t hf_read(struct cdev *cdev, void *buf, size_t count, loff_t offset return linux_read(fd, buf, count); } -static ssize_t hf_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags) +static ssize_t hf_write(struct hf_priv *priv, const void *buf, size_t count, loff_t offset, ulong flags) { - struct hf_priv *priv = cdev->priv; int fd = priv->fd; if (linux_lseek(fd, offset) != offset) @@ -57,59 +57,135 @@ static ssize_t hf_write(struct cdev *cdev, const void *buf, size_t count, loff_t return linux_write(fd, buf, count); } -static void hf_info(struct device_d *dev) +static ssize_t hf_cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags) +{ + return hf_read(cdev->priv, buf, count, offset, flags); +} + +static ssize_t hf_cdev_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags) +{ + return hf_write(cdev->priv, buf, count, offset, flags); +} + +static struct cdev_operations hf_cdev_ops = { + .read = hf_cdev_read, + .write = hf_cdev_write, +}; + +static int hf_blk_read(struct block_device *blk, void *buf, sector_t block, blkcnt_t num_blocks) +{ + ssize_t ret = hf_read(container_of(blk, struct hf_priv, blk), buf, + num_blocks << SECTOR_SHIFT, block << SECTOR_SHIFT, 0); + return ret > 0 ? 0 : ret; +} + +static int hf_blk_write(struct block_device *blk, const void *buf, sector_t block, blkcnt_t num_blocks) +{ + ssize_t ret = hf_write(container_of(blk, struct hf_priv, blk), buf, + num_blocks << SECTOR_SHIFT, block << SECTOR_SHIFT, 0); + return ret > 0 ? 0 : ret; +} + +static struct block_device_ops hf_blk_ops = { + .read = hf_blk_read, + .write = hf_blk_write, +}; + +static void hf_info(struct device *dev) { struct hf_priv *priv = dev->priv; printf("file: %s\n", priv->filename); } -static struct cdev_operations hf_fops = { - .read = hf_read, - .write = hf_write, -}; +static int hostfile_feat_check(struct feature_controller *feat, int idx) +{ + struct hf_priv *priv = container_of(feat, struct hf_priv, feat); -static int hf_probe(struct device_d *dev) + return priv->fd >= 0 ? FEATCTRL_OKAY : FEATCTRL_GATED; +} + +static int hf_probe(struct device *dev) { + struct device_node *np = dev->of_node; struct hf_priv *priv = xzalloc(sizeof(*priv)); - struct resource *res; + struct cdev *cdev; + bool is_featctrl = false, is_blockdev; + u64 reg[2]; int err; - res = dev_get_resource(dev, IORESOURCE_MEM, 0); - if (IS_ERR(res)) - return PTR_ERR(res); + if (!np) + return -ENODEV; + + dev->priv = priv; + priv->fd = -1; - priv->cdev.size = resource_size(res); + if (IS_ENABLED(CONFIG_FEATURE_CONTROLLER) && + of_property_read_bool(np, "barebox,feature-controller")) { + priv->feat.dev = dev; + priv->feat.check = hostfile_feat_check; - if (!dev->device_node) - return -ENODEV; + err = feature_controller_register(&priv->feat); + if (err) + return err; - of_property_read_u32(dev->device_node, "barebox,fd", &priv->fd); + is_featctrl = true; + } - err = of_property_read_string(dev->device_node, "barebox,filename", - &priv->filename); + + err = of_property_read_u64_array(np, "reg", reg, ARRAY_SIZE(reg)); if (err) return err; - if (!priv->fd) - priv->fd = linux_open(priv->filename, true); + of_property_read_u32(np, "barebox,fd", &priv->fd); + + err = of_property_read_string(np, "barebox,filename", + &priv->filename); + if (err) + return err; - priv->cdev.name = dev->device_node->name; - priv->cdev.dev = dev; - priv->cdev.ops = &hf_fops; - priv->cdev.priv = priv; + if (priv->fd < 0) + return is_featctrl ? 0 : priv->fd; dev->info = hf_info; - dev->priv = priv; - err = devfs_create(&priv->cdev); - if (err) - return err; + is_blockdev = of_property_read_bool(np, "barebox,blockdev"); - of_parse_partitions(&priv->cdev, dev->device_node); - of_partitions_register_fixup(&priv->cdev); + cdev = is_blockdev ? &priv->blk.cdev : &priv->cdev; - return 0; + cdev_set_of_node(cdev, np); + + if (is_blockdev) { + cdev->name = np->name; + priv->blk.dev = dev; + priv->blk.ops = &hf_blk_ops; + priv->blk.blockbits = SECTOR_SHIFT; + priv->blk.num_blocks = reg[1] / SECTOR_SIZE; + priv->blk.type = BLK_TYPE_VIRTUAL; + + err = blockdevice_register(&priv->blk); + if (err) + return err; + + dev_info(dev, "registered as block device\n"); + } else { + cdev->name = np->name; + cdev->dev = dev; + cdev->ops = &hf_cdev_ops; + cdev->size = reg[1]; + cdev->priv = priv; + + err = devfs_create(cdev); + if (err) + return err; + + dev_info(dev, "registered as character device\n"); + } + + of_parse_partitions(cdev, np); + of_partitions_register_fixup(cdev); + + return of_platform_populate(np, NULL, dev); } static __maybe_unused struct of_device_id hostfile_dt_ids[] = { @@ -119,45 +195,111 @@ static __maybe_unused struct of_device_id hostfile_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, hostfile_dt_ids); -static struct driver_d hf_drv = { +static struct driver hf_drv = { .name = "hostfile", .of_compatible = DRV_OF_COMPAT(hostfile_dt_ids), .probe = hf_probe, }; -coredevice_platform_driver(hf_drv); +device_platform_driver(hf_drv); 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 - }; + 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); + 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, "barebox,stickypage") { + char *filename; + + filename = linux_get_stickypage_path(); + if (!filename) { + pr_err("error allocating stickypage\n"); + continue; + } + + of_property_write_string(node, "barebox,filename", filename); + of_property_write_string(node, "compatible", "barebox,hostfile"); + } + + for_each_compatible_node_from(node, root, NULL, "barebox,hostfile") { + struct hf_info hf = {}; + uint64_t reg[2] = {}; + + hf.devname = node->name; + + ret = of_property_read_string(node, "barebox,filename", &hf.filename); + if (ret) { + pr_err("skipping nameless hostfile %s\n", hf.devname); + continue; + } + + 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) + continue; + + reg[0] = hf.base; + reg[1] = hf.size; + + of_property_write_u64_array(node, "reg", reg, ARRAY_SIZE(reg)); + of_property_write_bool(node, "barebox,blockdev", hf.is_blockdev); + of_property_write_u32(node, "barebox,fd", hf.fd); + } + + 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/led.c b/arch/sandbox/board/led.c new file mode 100644 index 0000000000..ced7e82f99 --- /dev/null +++ b/arch/sandbox/board/led.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <common.h> +#include <init.h> +#include <led.h> +#include <mach/linux.h> +#include <of.h> + +static struct sandbox_led { + struct led led; + bool active; +} sandbox_led; + +static inline void terminal_puts(const char *s) +{ + linux_write(1, s, strlen(s)); +} + +static void sandbox_led_set(struct led *led, unsigned int brightness) +{ + terminal_puts("\x1b]2;barebox "); + while (brightness--) + terminal_puts("."); + terminal_puts("\a"); + + sandbox_led.active = true; +} + +static int sandbox_led_of_probe(struct device *dev) +{ + struct device_node *np = dev->of_node; + int ret; + + if (sandbox_led.led.set) + return -EBUSY; + + sandbox_led.led.name = xstrdup(np->name); + sandbox_led.led.max_value = 5; + sandbox_led.led.set = sandbox_led_set; + + ret = led_register(&sandbox_led.led); + if (ret) + return ret; + + led_of_parse_trigger(&sandbox_led.led, np); + + return 0; +} + +static void sandbox_led_of_remove(struct device *dev) +{ + if (sandbox_led.active) + sandbox_led_set(NULL, 0); +} + +static struct of_device_id sandbox_led_of_ids[] = { + { .compatible = "barebox,sandbox-led", }, + { } +}; +MODULE_DEVICE_TABLE(of, sandbox_led_of_ids); + +static struct driver sandbox_led_of_driver = { + .name = "sandbox-led", + .probe = sandbox_led_of_probe, + .remove = sandbox_led_of_remove, + .of_compatible = sandbox_led_of_ids, +}; +device_platform_driver(sandbox_led_of_driver); diff --git a/arch/sandbox/board/power.c b/arch/sandbox/board/power.c new file mode 100644 index 0000000000..8300c589c7 --- /dev/null +++ b/arch/sandbox/board/power.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <common.h> +#include <driver.h> +#include <poweroff.h> +#include <restart.h> +#include <mach/linux.h> +#include <asm/reset_source.h> +#include <linux/nvmem-consumer.h> + +struct sandbox_power { + struct restart_handler rst_hang, rst_reexec; + struct poweroff_handler poweroff; + struct nvmem_cell *reset_source_cell; +}; + +static void sandbox_poweroff(struct poweroff_handler *poweroff) +{ + struct sandbox_power *power = container_of(poweroff, struct sandbox_power, poweroff); + + sandbox_save_reset_source(power->reset_source_cell, RESET_POR); + + 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); + + sandbox_save_reset_source(power->reset_source_cell, RESET_RST); + + linux_reexec(); +} + +static int sandbox_power_probe(struct device *dev) +{ + struct sandbox_power *power = xzalloc(sizeof(*power)); + size_t len; + u8 *rst; + + power->poweroff = (struct poweroff_handler) { + .name = "exit", + .poweroff = sandbox_poweroff + }; + + poweroff_handler_register(&power->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->reset_source_cell = of_nvmem_cell_get(dev->of_node, + "reset-source"); + if (IS_ERR(power->reset_source_cell)) { + if (PTR_ERR(power->reset_source_cell) != -EPROBE_DEFER) + dev_warn(dev, "No reset source info available: %pe\n", + power->reset_source_cell); + power->reset_source_cell = NULL; + return 0; + } + + rst = nvmem_cell_read(power->reset_source_cell, &len); + if (!IS_ERR(rst)) { + reset_source_set_prinst(*rst, RESET_SOURCE_DEFAULT_PRIORITY, 0); + + free(rst); + } + + return 0; +} + +static __maybe_unused struct of_device_id sandbox_power_dt_ids[] = { + { .compatible = "barebox,sandbox-power" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sandbox_power_dt_ids); + +static struct driver 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 6b5a6dff15..0000000000 --- a/arch/sandbox/board/poweroff.c +++ /dev/null @@ -1,17 +0,0 @@ -#include <common.h> -#include <init.h> -#include <poweroff.h> -#include <mach/linux.h> - -static void sandbox_poweroff(struct poweroff_handler *poweroff) -{ - linux_exit(); -} - -static int poweroff_register_feature(void) -{ - poweroff_handler_register_fn(sandbox_poweroff); - - return 0; -} -coredevice_initcall(poweroff_register_feature); diff --git a/arch/sandbox/board/stickypage.S b/arch/sandbox/board/stickypage.S new file mode 100644 index 0000000000..1d3861c373 --- /dev/null +++ b/arch/sandbox/board/stickypage.S @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +.section .note.GNU-stack,"",%progbits +.section .rodata.stickypage,"a" + +.globl stickypage; +stickypage: + +/* nvmem */ .org 0x300 +.byte 0x01 + +/* env */ .org 0x400 +.byte 0x79, 0xba, 0x8f, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +.byte 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x69, 0x9c, 0x7f, 0x00, 0x00, 0x00, 0x00 + +/* state */ .org 0xC00 +.byte 0xf3, 0xfd, 0x54, 0x23, 0x18, 0x00, 0x00, 0x00, 0xa6, 0x86, 0x3b, 0xaa, 0x00, 0x00, 0x08, 0x00 +.byte 0x19, 0x70, 0x3d, 0xbb, 0x64, 0x89, 0x3b, 0x31, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 +.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +.byte 0xf3, 0xfd, 0x54, 0x23, 0x18, 0x00, 0x00, 0x00, 0xa6, 0x86, 0x3b, 0xaa, 0x00, 0x00, 0x08, 0x00 +.byte 0x19, 0x70, 0x3d, 0xbb, 0x64, 0x89, 0x3b, 0x31, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 +.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +.byte 0xf3, 0xfd, 0x54, 0x23, 0x18, 0x00, 0x00, 0x00, 0xa6, 0x86, 0x3b, 0xaa, 0x00, 0x00, 0x08, 0x00 +.byte 0x19, 0x70, 0x3d, 0xbb, 0x64, 0x89, 0x3b, 0x31, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 + +.fill 4096-(.-stickypage), 1, 0 +.size stickypage, 4096 diff --git a/arch/sandbox/board/watchdog.c b/arch/sandbox/board/watchdog.c new file mode 100644 index 0000000000..074c96a8a9 --- /dev/null +++ b/arch/sandbox/board/watchdog.c @@ -0,0 +1,77 @@ +// 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 <linux/nvmem-consumer.h> +#include <asm/reset_source.h> + +struct sandbox_watchdog { + struct watchdog wdd; + bool cant_disable :1; + struct nvmem_cell *reset_source_cell; +}; + +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; + + sandbox_save_reset_source(wd->reset_source_cell, RESET_WDG); + + linux_watchdog_set_timeout(timeout); + return 0; +} + +static int sandbox_watchdog_probe(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct sandbox_watchdog *wd; + struct watchdog *wdd; + + wd = xzalloc(sizeof(*wd)); + + wdd = &wd->wdd; + wdd->hwdev = dev; + wdd->set_timeout = sandbox_watchdog_set_timeout; + wdd->timeout_max = 1000; + + wd->reset_source_cell = of_nvmem_cell_get(np, "reset-source"); + if (IS_ERR(wd->reset_source_cell)) { + if (PTR_ERR(wd->reset_source_cell) != -EPROBE_DEFER) + dev_warn(dev, "No reset source info available: %pe\n", + wd->reset_source_cell); + wd->reset_source_cell = NULL; + } + + wd->cant_disable = of_property_read_bool(np, "barebox,cant-disable"); + + return watchdog_register(wdd); +} + + +static __maybe_unused struct of_device_id sandbox_watchdog_dt_ids[] = { + { .compatible = "barebox,sandbox-watchdog" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sandbox_watchdog_dt_ids); + +static struct driver sandbox_watchdog_drv = { + .name = "sandbox-watchdog", + .of_compatible = sandbox_watchdog_dt_ids, + .probe = sandbox_watchdog_probe, +}; +device_platform_driver(sandbox_watchdog_drv); |