From 49292bd74f73a260927b7f3f42548e4ee4407237 Mon Sep 17 00:00:00 2001 From: Robert Schwebel Date: Tue, 26 Jul 2016 22:16:06 +0200 Subject: platform-beaglebone: rename to platform-v7a In the meantime, in addition to beaglebone, this platform supports the other ARMv7 based boards (rpi2, vexpress), so rename it. Signed-off-by: Robert Schwebel --- ...dd-framework-for-redundant-boot-scenarios.patch | 1467 ++++++++++++++++++++ ...dd-kernel-option-containing-the-system-th.patch | 43 + ...ootstate-separate-names-from-boot-targets.patch | 63 + ...-set-kernel-option-to-name-of-boot-target.patch | 119 ++ ...lebone-add-state-entrie-for-mmc0-and-mmc1.patch | 35 + ...i2-add-basic-boot-spec-devicetree-support.patch | 462 ++++++ ...6.05.0-customers-pengutronix-multi_v7-201.patch | 22 + .../platform-v7a/patches/barebox-2016.05.0/series | 22 + 8 files changed, 2233 insertions(+) create mode 100644 configs/platform-v7a/patches/barebox-2016.05.0/0001-bootstate-add-framework-for-redundant-boot-scenarios.patch create mode 100644 configs/platform-v7a/patches/barebox-2016.05.0/0002-bootstate-Add-kernel-option-containing-the-system-th.patch create mode 100644 configs/platform-v7a/patches/barebox-2016.05.0/0003-bootstate-separate-names-from-boot-targets.patch create mode 100644 configs/platform-v7a/patches/barebox-2016.05.0/0004-bootstate-set-kernel-option-to-name-of-boot-target.patch create mode 100644 configs/platform-v7a/patches/barebox-2016.05.0/0101-beaglebone-add-state-entrie-for-mmc0-and-mmc1.patch create mode 100644 configs/platform-v7a/patches/barebox-2016.05.0/0201-rpi2-add-basic-boot-spec-devicetree-support.patch create mode 100644 configs/platform-v7a/patches/barebox-2016.05.0/0301-Release-2016.05.0-customers-pengutronix-multi_v7-201.patch create mode 100644 configs/platform-v7a/patches/barebox-2016.05.0/series (limited to 'configs/platform-v7a/patches') diff --git a/configs/platform-v7a/patches/barebox-2016.05.0/0001-bootstate-add-framework-for-redundant-boot-scenarios.patch b/configs/platform-v7a/patches/barebox-2016.05.0/0001-bootstate-add-framework-for-redundant-boot-scenarios.patch new file mode 100644 index 0000000..08b17de --- /dev/null +++ b/configs/platform-v7a/patches/barebox-2016.05.0/0001-bootstate-add-framework-for-redundant-boot-scenarios.patch @@ -0,0 +1,1467 @@ +From: Marc Kleine-Budde +Date: Fri, 20 Feb 2015 09:19:14 +0100 +Subject: [PATCH] bootstate: add framework for redundant boot scenarios + +There are several use cases where a redundant Linux system is needed. The +barebox,bootstate framework provides the building blocks to model different +use cases without the need to start from the scratch over and over again. + +Signed-off-by: Marc Kleine-Budde +--- + .../bindings/barebox/barebox,bootstate.rst | 236 +++++++ + arch/sandbox/dts/sandbox.dts | 83 +++ + commands/Kconfig | 5 + + commands/Makefile | 1 + + commands/bootchooser.c | 101 +++ + common/Kconfig | 8 + + common/Makefile | 1 + + common/bootstate.c | 781 +++++++++++++++++++++ + drivers/misc/Kconfig | 5 + + drivers/misc/Makefile | 1 + + drivers/misc/bootstate.c | 79 +++ + include/bootstate.h | 39 + + 12 files changed, 1340 insertions(+) + create mode 100644 Documentation/devicetree/bindings/barebox/barebox,bootstate.rst + create mode 100644 commands/bootchooser.c + create mode 100644 common/bootstate.c + create mode 100644 drivers/misc/bootstate.c + create mode 100644 include/bootstate.h + +diff --git a/Documentation/devicetree/bindings/barebox/barebox,bootstate.rst b/Documentation/devicetree/bindings/barebox/barebox,bootstate.rst +new file mode 100644 +index 000000000000..0f7131536798 +--- /dev/null ++++ b/Documentation/devicetree/bindings/barebox/barebox,bootstate.rst +@@ -0,0 +1,236 @@ ++barebox bootstate ++================= ++ ++Overview ++-------- ++ ++There are several use cases where a redundant Linux system is needed. ++The ``barebox,bootstate`` framework provides the building blocks to ++model different use cases without the need to start from the scratch ++over and over again. ++ ++The ``barebox,bootstate`` works on abstract boot targets, each with a ++set of properties and implements an algorithm which selects the ++highest priority target to boot. ++ ++A set of boot targets can be described in a devicetree node. This ++node could be part of the regular devicetree blob or it could be an ++extra devicetree for the bootstate. ++ ++A bootstate node contains a description of a set of boot targets along ++with a place where to store the mutable state. Currently implemented ++backends are :ref:`barebox,state` and ``nv`` (:ref:`command_nv`) ++variables. ++ ++Required properties: ++ ++* ``compatible``: should be ``barebox,bootstate``; ++* ``backend-type``: should be ``state`` or ``nv``. ++ ++Optional properties: ++ ++* ``backend``: phandle to the :ref:`barebox,state` backend ++ ++ ++boot target nodes - immutable description ++----------------------------------------- ++ ++These are subnodes of a bootstate node, each describing a boot ++target. The node name may end with ``@
``, but the suffix is ++stripped from the target name. ++ ++Optional properties: ++ ++* ``default_attempts``: If the boot attempts counter is reset, this ++ value is used. ++ ++Example:: ++ ++ bootstate: bootstate { ++ compatible = "barebox,bootstate"; ++ backend-type = "state"; ++ backend = <&state>; ++ ++ system0 { ++ default_attempts = <3>; ++ }; ++ ++ system1 { ++ default_attempts = <3>; ++ }; ++ }; ++ ++In this example a bootstate, using a :ref:`barebox,state` backend with ++two boot target nodes ``system0`` and ``system1`` is defined. When the ++boot attempts counter is reset, the default value of ``3`` is used for ++both targets. ++ ++ ++boot target nodes - mutable state ++--------------------------------- ++ ++The above example uses a :ref:`barebox,state` backend, which requires ++some additional configuration to hold the mutable ++state. :ref:`barebox,state` has to be explicidly configured, while ++``nv`` (:ref:`command_nv`) variables are created on the fly. ++ ++The state of each boot target consists of the following ``uint32`` ++varibles: ++ ++* ``remaining_attempts``: holds the number of remaining boot attempts. ++ This variable is changed by the bootstate algorithm during boot. ++* ``priority``: defines the priority of the boot target. Higher number ++ indicate a higher priority, If two boot targets have the same ++ priority the one defined first in the device tree has precedence. ++ The ``priority`` can optionally be changed by the algorithm to 0, if ++ the boot target is decremented to ``0`` remaining boot attempts. A ++ ``priority`` of ``0`` means the boot target is **deactivated** and ++ will not be considered a valid target during further boots. If the ++ remaining attempts counter is reset, a target with priority 0 is ++ **not** changed. ++* ``ok``: this is an opaque value, it's not accessed by the bootstate ++ algorithm. It can be used be the Linux system to track the first ++ boot after an update. ++ ++The bootstate can also hold a default watchdog timeout (in seconds), ++which can be activated by the bootstate algorithm. ++ ++Example:: ++ ++ state: state { ++ magic = <0x4d433230>; ++ compatible = "barebox,state"; ++ backend-type = "raw"; ++ backend = <&backend_state>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootstate { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ system0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ remaining_attempts { ++ reg = <0x0 0x4>; ++ type = "uint32"; ++ }; ++ priority { ++ reg = <0x4 0x4>; ++ type = "uint32"; ++ }; ++ ok { ++ reg = <0x8 0x4>; ++ type = "uint32"; ++ }; ++ }; ++ ++ system1 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ remaining_attempts { ++ reg = <0x10 0x4>; ++ type = "uint32"; ++ }; ++ priority { ++ reg = <0x14 0x4>; ++ type = "uint32"; ++ }; ++ ok { ++ reg = <0x18 0x4>; ++ type = "uint32"; ++ }; ++ }; ++ ++ watchdog_timeout { ++ reg = <0x20 0x4>; ++ type = "uint32"; ++ default = <60>; ++ }; ++ }; ++ }; ++ ++This example defines two boot targets (``system0`` and ``system1``) and ++a watchdog timeout of ``60`` seconds. ++ ++ ++Backends ++-------- ++ ++Currently two backends exist. The :ref:`barebox,state` backend is a ++bit more complicated to setup, as all boot target have to be described ++in the referenced :ref:`barebox,state` in the device tree. On the ++upside, the advantages of the (possible redundant storage, etc...) of ++the :ref:`barebox,state` is gained for free. ++ ++The :ref:`command_nv` backend is a lot simpler, no special setup is ++needed, it should run on every board, which already implements a ++read/writeable barebox environment. ++ ++ ++Algorithm ++--------- ++ ++The low level algorithm is implemented by the ++``bootstate_get_target()`` function. Its job is to iterate over all ++boot sources and return the name (as a string) of the choosen boot ++target. ++ ++The algorithm iterates over all boot targets defined under the ++associated device tree node and picks the one with the highest ++``priority`` (higher number have a higher priority) where the ++``remaining_attempts`` is greater than zero. A pointer to the name of ++the boot target is returned, the string should be freed via ``free()``. ++ ++The behaviour can be modified with the flags paramter. The following ++flags are currently supported: ++ ++* ``BOOTCHOOSER_FLAG_ATTEMPTS_KEEP``: the ``remaining_attempts`` ++ counter of the choosen boot target is not changed. ++* ``BOOTCHOOSER_FLAG_ATTEMPTS_DEC``: the ``remaining_attempts`` ++ counter of the choosen boot target is decremented by one. ++* ``BOOTCHOOSER_FLAG_ATTEMPTS_RESET``: the ``remaining_attempts`` ++ counter of all *active* boot targets (those with ``priority > 0``) ++ are reset to their default values as defined in the immutable ++ description by ``default_attempts``. ++* ``BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS``: if used together ++ with ``BOOTCHOOSER_FLAG_ATTEMPTS_DEC`` and the ++ ``remaining_attempts`` counter of the choosen boot target is ++ decremented to ``0``, the boot target is deactivated for further ++ boot attempts (although *this* boot is attemped as usual). This is ++ done by setting the ``priority`` to ``0``. ++* ``BOOTCHOOSER_FLAG_VERBOSE``: increases the verbosity of the output ++ ++ ++Frontend ++-------- ++ ++The shell command ``bootchooser`` (:ref:`command_bootchooser`) can be ++used to choose and start a boot target by a shell one-liner. The ++command picks the boot target with the highest priority and calls the ++``boot`` (:ref:`command_boot`) command with the selected boot target ++as its first and only parameter. ++ ++The ``bootchooser`` command implements command line paramter versions ++of the above described flags: ++ ++* ``-k``: keep boot attempts ++* ``-d``: decrement boot attempts ++* ``-r``: reset boot attempts ++* ``-z``: deactivate on zero remaining attempts ++* ``-v``: verbose output ++ ++Next to the standard parameters, these additional options are ++implemented: ++ ++* ``-D``: dryrun - do not boot (all other functionality is active) - a ++ specified watchdog timeout will be activated. ++* ``-R``: retry - if booting fails, then chose next target, but ++ decrement its attempts. Note: if the current target has still the ++ highest priority and remaining attemts, it will be selected again. ++* ``-w ``: activate watchdog - if no parameter is ++ given, the timeout from the device tree is used. A given parameter ++ overwrites the device tree default. +diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts +index 2595aa13fa62..e2bc8f76c2e3 100644 +--- a/arch/sandbox/dts/sandbox.dts ++++ b/arch/sandbox/dts/sandbox.dts +@@ -3,5 +3,88 @@ + #include "skeleton.dtsi" + + / { ++ aliases { ++ state = &state; ++ }; + ++ state: state { ++ magic = <0x4d433230>; ++ compatible = "barebox,state"; ++ backend-type = "dtb"; ++ backend = "/fd0"; ++ ++ bootstate { ++ system0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ remaining_attempts { ++ reg = <0x0 0x4>; ++ type = "uint32"; ++ }; ++ priority { ++ reg = <0x4 0x4>; ++ type = "uint32"; ++ }; ++ ok { ++ reg = <0x8 0x4>; ++ type = "uint32"; ++ }; ++ }; ++ ++ system1 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ remaining_attempts { ++ reg = <0x10 0x4>; ++ type = "uint32"; ++ }; ++ priority { ++ reg = <0x14 0x4>; ++ type = "uint32"; ++ }; ++ ok { ++ reg = <0x18 0x4>; ++ type = "uint32"; ++ }; ++ }; ++ ++ factory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ remaining_attempts { ++ reg = <0x20 0x4>; ++ type = "uint32"; ++ }; ++ priority { ++ reg = <0x24 0x4>; ++ type = "uint32"; ++ }; ++ ok { ++ reg = <0x28 0x4>; ++ type = "uint32"; ++ }; ++ }; ++ }; ++ }; ++ ++ bootstate: bootstate { ++ compatible = "barebox,bootstate"; ++ backend-type = "state"; // or "nv", or "efivar" ++ backend = <&state>; ++ ++ system0 { ++ default_attempts = <3>; ++ }; ++ ++ system1 { ++ default_attempts = <3>; ++ }; ++ ++ factory { ++ default_attempts = <3>; ++ }; ++ }; + }; +diff --git a/commands/Kconfig b/commands/Kconfig +index 875c5f4f01ed..603e887b15ec 100644 +--- a/commands/Kconfig ++++ b/commands/Kconfig +@@ -2189,6 +2189,11 @@ config CMD_SPD_DECODE + help + decode spd eeprom + ++config CMD_BOOTCHOOSER ++ tristate ++ depends on BOOTSTATE ++ prompt "bootchooser" ++ + # end Miscellaneous commands + endmenu + +diff --git a/commands/Makefile b/commands/Makefile +index f1b482f04934..bb3b40809af5 100644 +--- a/commands/Makefile ++++ b/commands/Makefile +@@ -117,3 +117,4 @@ obj-$(CONFIG_CMD_DHRYSTONE) += dhrystone.o + obj-$(CONFIG_CMD_SPD_DECODE) += spd_decode.o + obj-$(CONFIG_CMD_MMC_EXTCSD) += mmc_extcsd.o + obj-$(CONFIG_CMD_NAND_BITFLIP) += nand-bitflip.o ++obj-$(CONFIG_CMD_BOOTCHOOSER) += bootchooser.o +diff --git a/commands/bootchooser.c b/commands/bootchooser.c +new file mode 100644 +index 000000000000..06ca5e41d527 +--- /dev/null ++++ b/commands/bootchooser.c +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (C) 2012 Jan Luebbe ++ * Copyright (C) 2015 Marc Kleine-Budde ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int do_bootchooser(int argc, char *argv[]) ++{ ++ unsigned flags = 0, timeout = 0; ++ char *name = NULL; ++ int opt, ret; ++ ++ while ((opt = getopt(argc, argv, "kdrzvDRw::")) > 0) { ++ switch (opt) { ++ case 'k': ++ flags |= BOOTCHOOSER_FLAG_ATTEMPTS_KEEP; ++ break; ++ case 'd': ++ flags |= BOOTCHOOSER_FLAG_ATTEMPTS_DEC; ++ break; ++ case 'r': ++ flags |= BOOTCHOOSER_FLAG_ATTEMPTS_RESET; ++ break; ++ case 'z': ++ flags |= BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS; ++ break; ++ case 'v': ++ flags |= BOOTCHOOSER_FLAG_VERBOSE; ++ break; ++ case 'D': ++ flags |= BOOTCHOOSER_FLAG_DRYRUN; ++ break; ++ case 'R': ++ flags |= BOOTCHOOSER_FLAG_RETRY_WITH_DEC; ++ break; ++ case 'w': ++ if (optarg) ++ timeout = simple_strtoul(optarg, NULL, 0); ++ else ++ flags |= BOOTCHOOSER_FLAG_WATCHDOG_TIMEOUT_FROM_STATE; ++ flags |= BOOTCHOOSER_FLAG_WATCHDOG_ENABLE; ++ break; ++ default: ++ return COMMAND_ERROR_USAGE; ++ } ++ } ++ ++ if (optind < argc) ++ name = argv[optind]; ++ ++ if (!(flags & (BOOTCHOOSER_FLAG_ATTEMPTS_KEEP | ++ BOOTCHOOSER_FLAG_ATTEMPTS_DEC | ++ BOOTCHOOSER_FLAG_ATTEMPTS_RESET))) { ++ bootstate_info(); ++ return 0; ++ } ++ ++ if ((flags & BOOTCHOOSER_FLAG_ATTEMPTS_KEEP) && ++ (flags & (BOOTCHOOSER_FLAG_ATTEMPTS_DEC | BOOTCHOOSER_FLAG_ATTEMPTS_RESET))) ++ return COMMAND_ERROR_USAGE; ++ ++ ret = bootstate_bootchooser(name, flags, timeout); ++ ++ return ret ? COMMAND_ERROR : COMMAND_SUCCESS; ++} ++ ++BAREBOX_CMD_HELP_START(bootchooser) ++BAREBOX_CMD_HELP_TEXT("Options:") ++BAREBOX_CMD_HELP_OPT ("-k","keep - boot, don't modify attempts counter") ++BAREBOX_CMD_HELP_OPT ("-d","decrement - boot, but decrement attempts counter by one") ++BAREBOX_CMD_HELP_OPT ("-r","reset - boot, but reset _all_ attempts counters to default") ++BAREBOX_CMD_HELP_OPT ("-z","deactivate chosen target on zero remaining boot attempts") ++BAREBOX_CMD_HELP_OPT ("-v","verbose output") ++BAREBOX_CMD_HELP_OPT ("-D","dryrun - do not boot, but handle watchdog and reset") ++BAREBOX_CMD_HELP_OPT ("-R","retry - boot, retry next boot target and decrement attempts") ++BAREBOX_CMD_HELP_OPT ("-w","activate watchdog, use timeout specified in .watchdog_timeout") ++BAREBOX_CMD_HELP_END ++ ++BAREBOX_CMD_START(bootchooser) ++ .cmd = do_bootchooser, ++ BAREBOX_CMD_DESC("automatically select a boot target and boot") ++ BAREBOX_CMD_OPTS("[-kdrzvDR] -w [BOOTSTATE]") ++ BAREBOX_CMD_GROUP(CMD_GRP_MISC) ++ BAREBOX_CMD_HELP(cmd_bootchooser_help) ++BAREBOX_CMD_END +diff --git a/common/Kconfig b/common/Kconfig +index 7c09e8c117f1..f17769661ee6 100644 +--- a/common/Kconfig ++++ b/common/Kconfig +@@ -792,6 +792,14 @@ config STATE_CRYPTO + See Documentation/devicetree/bindings/barebox/barebox,state.rst + for more information. + ++config BOOTSTATE ++ bool "bootstate infrastructure" ++ depends on OF_BAREBOX_DRIVERS ++ select ENVIRONMENT_VARIABLES ++ select OFTREE ++ select PARAMETER ++ select BOOTSTATE_DRV ++ + config RESET_SOURCE + bool "detect Reset cause" + depends on GLOBALVAR +diff --git a/common/Makefile b/common/Makefile +index d99ca7b7ac74..5505449874ad 100644 +--- a/common/Makefile ++++ b/common/Makefile +@@ -46,6 +46,7 @@ obj-$(CONFIG_SHELL_HUSH) += hush.o + obj-$(CONFIG_SHELL_SIMPLE) += parser.o + obj-$(CONFIG_STATE) += state.o + obj-$(CONFIG_RATP) += ratp.o ++obj-$(CONFIG_BOOTSTATE) += bootstate.o + obj-$(CONFIG_UIMAGE) += image.o uimage.o + obj-$(CONFIG_FITIMAGE) += image-fit.o + obj-$(CONFIG_MENUTREE) += menutree.o +diff --git a/common/bootstate.c b/common/bootstate.c +new file mode 100644 +index 000000000000..3dc18813064d +--- /dev/null ++++ b/common/bootstate.c +@@ -0,0 +1,781 @@ ++/* ++ * Copyright (C) 2012 Jan Luebbe ++ * Copyright (C) 2015 Marc Kleine-Budde ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* list of all registered bootstate instances */ ++static LIST_HEAD(bootstate_list); ++ ++struct state_backend; ++ ++struct bootstate { ++ struct device_d dev; ++ const char *name; ++ struct list_head list; ++ struct list_head targets; ++ struct list_head targets_unsorted; ++ struct bootstate_backend *backend; ++ bool dirty; ++}; ++ ++struct bootstate_backend { ++ int (*load)(struct bootstate_backend *backend, struct bootstate *bootstate); ++ int (*save)(struct bootstate_backend *backend, struct bootstate *bootstate); ++ const char *name; ++ const char *path; ++}; ++ ++struct bootstate_target { ++ struct list_head list; ++ struct list_head list_unsorted; ++ ++ /* state */ ++ unsigned int priority; ++ unsigned int remaining_attempts; ++ bool ok; ++ ++ /* spec */ ++ const char *name; ++ unsigned int default_attempts; ++}; ++ ++static void pr_target(struct bootstate *bootstate, struct bootstate_target *target) ++{ ++ printf("%s: target: name=%s prio=%u, ok=%d, rem=%u, def=%u\n", ++ bootstate->name, target->name, target->priority, target->ok, ++ target->remaining_attempts, target->default_attempts); ++} ++ ++static struct bootstate *bootstate_new(const char *name) ++{ ++ struct bootstate *bootstate; ++ int ret; ++ ++ bootstate = xzalloc(sizeof(*bootstate)); ++ safe_strncpy(bootstate->dev.name, name, MAX_DRIVER_NAME); ++ bootstate->name = bootstate->dev.name; ++ bootstate->dev.id = DEVICE_ID_DYNAMIC; ++ INIT_LIST_HEAD(&bootstate->targets); ++ INIT_LIST_HEAD(&bootstate->targets_unsorted); ++ ++ ret = register_device(&bootstate->dev); ++ if (ret) { ++ free(bootstate); ++ return ERR_PTR(ret); ++ } ++ ++ list_add_tail(&bootstate->list, &bootstate_list); ++ ++ return bootstate; ++} ++ ++void bootstate_release(struct bootstate *bootstate) ++{ ++ list_del(&bootstate->list); ++ unregister_device(&bootstate->dev); ++ free(bootstate); ++} ++ ++static int bootstate_target_compare(struct list_head *a, struct list_head *b) ++{ ++ struct bootstate_target *bootstate_a = list_entry(a, struct bootstate_target, list); ++ struct bootstate_target *bootstate_b = list_entry(b, struct bootstate_target, list); ++ ++ /* order descending */ ++ return bootstate_a->priority >= bootstate_b->priority ? -1 : 1; ++} ++ ++static void bootstate_target_add(struct bootstate *bootstate, struct bootstate_target *target) ++{ ++ list_del(&target->list); ++ list_add_sort(&target->list, &bootstate->targets, bootstate_target_compare); ++} ++ ++static int bootstate_variable_read_u32(const struct bootstate *bootstate, ++ const char *name, uint32_t *out_val) ++{ ++ char *var; ++ int ret; ++ ++ var = asprintf("%s.%s.%s", bootstate->backend->path, bootstate->name, name); ++ ret = getenv_uint(var, out_val); ++ free(var); ++ ++ return ret; ++} ++ ++static int bootstate_backend_variable_read_target_u32(const struct bootstate_backend *backend, ++ const struct bootstate *bootstate, ++ const struct bootstate_target *target, ++ const char *name, uint32_t *out_val) ++{ ++ char *var; ++ int ret; ++ ++ var = asprintf("%s.%s.%s.%s", backend->path, bootstate->name, ++ target->name, name); ++ ret = getenv_uint(var, out_val); ++ free(var); ++ ++ return ret; ++} ++ ++static int bootstate_backend_variable_write_target_u32(const struct bootstate_backend *backend, ++ const struct bootstate *bootstate, ++ const struct bootstate_target *target, ++ const char *name, uint32_t in_val) ++{ ++ char *var; ++ char *val; ++ int ret; ++ ++ var = asprintf("%s.%s.%s.%s", backend->path, bootstate->name, ++ target->name, name); ++ val = asprintf("%d", in_val); ++ ret = setenv(var, val); ++ free(val); ++ free(var); ++ ++ return ret; ++} ++ ++static int bootstate_variable_nv_init_u32(const struct bootstate_backend *backend, ++ const struct bootstate *bootstate, ++ const struct bootstate_target *target, ++ const char *name) ++{ ++ char *var; ++ int ret; ++ ++ var = asprintf("%s.%s.%s", bootstate->name, target->name, name); ++ ret = nvvar_add(var, "0"); ++ free(var); ++ ++ return ret; ++} ++ ++static struct bootstate_target *bootstate_target_find(const struct bootstate *bootstate, ++ const char *name) ++{ ++ struct bootstate_target *target; ++ ++ list_for_each_entry(target, &bootstate->targets, list) { ++ if (!strcmp(target->name, name)) ++ return target; ++ } ++ ++ return ERR_PTR(-ENOENT); ++} ++ ++static int bootstate_target_from_node(struct bootstate *bootstate, const struct device_node *node, bool create) ++{ ++ struct bootstate_target *target; ++ char *name, *indexs; ++ int ret; ++ ++ name = xstrdup(node->name); ++ indexs = strchr(name, '@'); ++ if (indexs) ++ *indexs++ = 0; ++ ++ if (create) { ++ /* create*/ ++ target = xzalloc(sizeof(*target)); ++ ++ target->name = xstrdup(name); ++ list_add_tail(&target->list, &bootstate->targets); ++ list_add_tail(&target->list_unsorted, ++ &bootstate->targets_unsorted); ++ } else { ++ target = bootstate_target_find(bootstate, name); ++ if (IS_ERR(target)) { ++ int ret = PTR_ERR(target); ++ pr_err("no such boot target: %s: %s\n", ++ name, strerror(-ret)); ++ return ret; ++ } ++ } ++ ++ /* init */ ++ ret = of_property_read_u32(node, "default_attempts", ++ &target->default_attempts); ++ if (ret) ++ return ret; ++ ++ free(name); ++ ++ return 0; ++} ++ ++static int bootstate_from_node(struct bootstate *bootstate, ++ const struct device_node *node, bool create) ++{ ++ struct device_node *child; ++ int ret; ++ ++ for_each_child_of_node(node, child) { ++ ret = bootstate_target_from_node(bootstate, child, create); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bootstate_backend_load_one(const struct bootstate_backend *backend, ++ const struct bootstate *bootstate, ++ struct bootstate_target *target) ++{ ++ uint32_t tmp; ++ int ret; ++ ++ ret = bootstate_backend_variable_read_target_u32(backend, bootstate, target, ++ "remaining_attempts", ++ &target->remaining_attempts); ++ if (ret) ++ return ret; ++ ++ ret = bootstate_backend_variable_read_target_u32(backend, bootstate, target, ++ "priority", &target->priority); ++ if (ret) ++ return ret; ++ ++ ret = bootstate_backend_variable_read_target_u32(backend, bootstate, target, ++ "ok", &tmp); ++ if (ret) ++ return ret; ++ ++ target->ok = !!tmp; ++ ++ return ret; ++} ++ ++static int bootstate_backend_load(struct bootstate_backend *backend, ++ struct bootstate *bootstate) ++{ ++ struct bootstate_target *target; ++ int ret; ++ ++ list_for_each_entry(target, &bootstate->targets_unsorted, list_unsorted) { ++ ret = bootstate_backend_load_one(backend, bootstate, target); ++ if (ret) ++ return ret; ++ bootstate_target_add(bootstate, target); ++ } ++ ++ return 0; ++} ++ ++static int bootstate_backend_save_one(const struct bootstate_backend *backend, ++ const struct bootstate *bootstate, ++ struct bootstate_target *target) ++{ ++ int ret; ++ ++ ret = bootstate_backend_variable_write_target_u32(backend, bootstate, target, ++ "remaining_attempts", ++ target->remaining_attempts); ++ if (ret) ++ return ret; ++ ++ ret = bootstate_backend_variable_write_target_u32(backend, bootstate, target, ++ "priority", target->priority); ++ if (ret) ++ return ret; ++ ++ ret = bootstate_backend_variable_write_target_u32(backend, bootstate, target, ++ "ok", target->ok); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int bootstate_backend_save(const struct bootstate_backend *backend, ++ const struct bootstate *bootstate) ++{ ++ struct bootstate_target *target; ++ int ret; ++ ++ list_for_each_entry(target, &bootstate->targets, list) { ++ ret = bootstate_backend_save_one(backend, bootstate, target); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bootstate_backend_nv_init_one(const struct bootstate_backend *backend, ++ const struct bootstate *bootstate, ++ struct bootstate_target *target) ++{ ++ int ret; ++ ++ ret = bootstate_variable_nv_init_u32(backend, bootstate, target, ++ "remaining_attempts"); ++ if (ret) ++ return ret; ++ ++ ret = bootstate_variable_nv_init_u32(backend, bootstate, target, ++ "priority"); ++ if (ret) ++ return ret; ++ ++ ret = bootstate_variable_nv_init_u32(backend, bootstate, target, ++ "ok"); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int bootstate_backend_nv_init(struct bootstate_backend *backend, ++ struct bootstate *bootstate) ++{ ++ struct bootstate_target *target; ++ int ret; ++ ++ list_for_each_entry(target, &bootstate->targets_unsorted, list_unsorted) { ++ ret = bootstate_backend_nv_init_one(backend, bootstate, target); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bootstate_backend_nv_save(struct bootstate_backend *backend, ++ struct bootstate *bootstate) ++{ ++ int ret; ++ ++ ret = bootstate_backend_save(backend, bootstate); ++ if (ret) ++ return ret; ++ ++ return envfs_save(NULL, NULL, 0); ++} ++ ++static int bootstate_backend_nv_load(struct bootstate_backend *backend, ++ struct bootstate *bootstate) ++{ ++ return bootstate_backend_load(backend, bootstate); ++} ++ ++struct bootstate_backend_nv { ++ struct bootstate_backend backend; ++}; ++ ++int bootstate_backend_nv(struct bootstate *bootstate) ++{ ++ struct bootstate_backend_nv *backend_nv; ++ struct bootstate_backend *backend; ++ ++ if (bootstate->backend) ++ return -EBUSY; ++ ++ backend_nv = xzalloc(sizeof(*backend_nv)); ++ backend = &backend_nv->backend; ++ ++ backend->load = bootstate_backend_nv_load; ++ backend->save = bootstate_backend_nv_save; ++ backend->name = "nv"; ++ backend->path = "nv"; ++ ++ bootstate->backend = backend; ++ ++ return bootstate_backend_nv_init(backend, bootstate); ++} ++ ++struct bootstate_backend_state { ++ struct bootstate_backend backend; ++ struct state *state; ++}; ++ ++static int bootstate_backend_state_save(struct bootstate_backend *backend, ++ struct bootstate *bootstate) ++{ ++ struct bootstate_backend_state *backend_state = ++ container_of(backend, struct bootstate_backend_state, backend); ++ int ret; ++ ++ ret = bootstate_backend_save(backend, bootstate); ++ if (ret) ++ return ret; ++ ++ return state_save(backend_state->state); ++} ++ ++static int bootstate_backend_state_load(struct bootstate_backend *backend, ++ struct bootstate *bootstate) ++{ ++ return bootstate_backend_load(backend, bootstate); ++} ++ ++int bootstate_backend_state(struct bootstate *bootstate, const struct device_node *node) ++{ ++ struct bootstate_backend_state *backend_state; ++ struct bootstate_backend *backend; ++ const struct device_node *state_node; ++ struct state *state; ++ ++ if (bootstate->backend) ++ return -EBUSY; ++ ++ state_node = of_parse_phandle(node, "backend", 0); ++ if (!state_node) ++ return -EINVAL; ++ ++ state = state_by_node(state_node); ++ if (!state) ++ return -EPROBE_DEFER; ++ ++ backend_state = xzalloc(sizeof(*backend_state)); ++ backend_state->state = state; ++ ++ backend = &backend_state->backend; ++ backend->load = bootstate_backend_state_load; ++ backend->save = bootstate_backend_state_save; ++ backend->name = "state"; ++ ++ bootstate->backend = backend; ++ ++ return state_get_name(backend_state->state, &backend->path); ++} ++ ++/* ++ * bootstate_new_from_node - create a new bootstate instance from a device_node ++ * ++ * @name The name of the new bootstate instance ++ * @node The device_node describing the new bootstate instance ++ */ ++struct bootstate *bootstate_new_from_node(const char *name, const struct device_node *node) ++{ ++ struct bootstate *bootstate; ++ int ret; ++ ++ pr_debug("%s: node=%s, name=%s\n", __func__, node->full_name, name); ++ ++ bootstate = bootstate_new(name); ++ if (!bootstate) ++ return ERR_PTR(-EINVAL); ++ ++ ret = bootstate_from_node(bootstate, node, true); ++ if (ret) { ++ bootstate_release(bootstate); ++ return ERR_PTR(ret); ++ } ++ ++ return bootstate; ++} ++ ++/* ++ * bootstate_by_name - find a bootstate instance by name ++ * ++ * @name The name of the state instance ++ */ ++struct bootstate *bootstate_by_name(const char *name) ++{ ++ struct bootstate *bs; ++ ++ list_for_each_entry(bs, &bootstate_list, list) { ++ if (!strcmp(name, bs->name)) ++ return bs; ++ } ++ ++ return NULL; ++} ++ ++/* ++ * bootstate_load - load a bootstate from the backing store ++ * ++ * @bootstate The state instance to load ++ */ ++static int bootstate_load(struct bootstate *bootstate) ++{ ++ int ret; ++ ++ if (!bootstate->backend) ++ return -ENOSYS; ++ ++ ret = bootstate->backend->load(bootstate->backend, bootstate); ++ if (ret) ++ bootstate->dirty = 1; ++ else ++ bootstate->dirty = 0; ++ ++ return ret; ++} ++ ++/* ++ * bootstate_save - save a bootstate to the backing store ++ * ++ * @bootstate The bootstate instance to save ++ */ ++static int bootstate_save(struct bootstate *bootstate) ++{ ++ int ret; ++ ++ if (!bootstate->dirty) ++ return 0; ++ ++ if (!bootstate->backend) ++ return -ENOSYS; ++ ++ ret = bootstate->backend->save(bootstate->backend, bootstate); ++ if (ret) ++ return ret; ++ ++ bootstate->dirty = 0; ++ ++ return 0; ++} ++ ++void bootstate_info(void) ++{ ++ struct bootstate *bootstate; ++ ++ printf("registered bootstate instances:\n"); ++ ++ list_for_each_entry(bootstate, &bootstate_list, list) { ++ printf("%-20s ", bootstate->name); ++ printf("(backend: %s, path: %s)\n", ++ bootstate->backend->name, bootstate->backend->path); ++ } ++} ++ ++#define __BF(arg) [__BOOTCHOOSER_FLAG_##arg##_SHIFT] = __stringify(arg) ++ ++static const char * const bootstate_flags_str[] = { ++ __BF(ATTEMPTS_KEEP), ++ __BF(ATTEMPTS_DEC), ++ __BF(ATTEMPTS_RESET), ++ __BF(DEACTIVATE_ON_ZERO_ATTEMPTS), ++ __BF(VERBOSE), ++ __BF(DRYRUN), ++ __BF(RETRY_WITH_DEC), ++ __BF(WATCHDOG_ENABLE), ++ __BF(WATCHDOG_TIMEOUT_FROM_STATE), ++}; ++ ++#undef __BF ++ ++#define pr(verbose, format, args...) \ ++ ({ \ ++ (verbose) ? pr_info((format), ##args) : 0; \ ++ }) ++ ++void _pr_flags(struct bootstate *bootstate, unsigned flags) ++{ ++ int i; ++ ++ pr_info("%s: flags=0x%08x\n", bootstate->name, flags); ++ ++ for (i = 0; i < ARRAY_SIZE(bootstate_flags_str); i++) { ++ if (flags & (1 << i)) ++ pr_info("%s: -> %s\n", bootstate->name, ++ bootstate_flags_str[i]); ++ } ++} ++ ++#define pr_flags(verbose, bootstate, flags) \ ++ ({ \ ++ (verbose) ? _pr_flags(bootstate, flags) : 0; \ ++ }) ++ ++/* ++ * bootstate_get_target - create a new state instance from a device_node ++ * ++ * @bootstate the bootstate instance to work in ++ * @flags supported flags: ++ * BOOTCHOOSER_FLAG_VERBOSE ++ * BOOTCHOOSER_FLAG_ATTEMPTS_KEEP ++ * BOOTCHOOSER_FLAG_ATTEMPTS_DEC ++ * BOOTCHOOSER_FLAG_ATTEMPTS_RESET ++ * BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS ++ * @target_out a string to the choosen boot target is returned via ++ * this paramater ++ */ ++int bootstate_get_target(struct bootstate *bootstate, unsigned flags, char **target_out) ++{ ++ struct bootstate_target *target; ++ int ret; ++ bool found = false; ++ bool v = flags & BOOTCHOOSER_FLAG_VERBOSE; ++ ++ pr_flags(v, bootstate, flags); ++ ++ ret = bootstate_load(bootstate); ++ if (ret) ++ return ret; ++ ++ if (flags & BOOTCHOOSER_FLAG_ATTEMPTS_RESET) { ++ list_for_each_entry(target, &bootstate->targets, list) { ++ if (target->priority == 0) ++ continue; ++ ++ target->remaining_attempts = target->default_attempts; ++ bootstate->dirty = true; ++ ++ pr(v, "%s: target: name=%s setting rem to %d due to %s\n", ++ bootstate->name, target->name, target->default_attempts, ++ bootstate_flags_str[__BOOTCHOOSER_FLAG_ATTEMPTS_RESET_SHIFT]); ++ } ++ pr(v, "%s: --------\n", bootstate->name); ++ } ++ ++ list_for_each_entry(target, &bootstate->targets, list) { ++ pr_target(bootstate, target); ++ ++ if (found) ++ continue; ++ ++ if (target->priority == 0) { ++ pr(v, "%s: name=%s prio=%d - trying next\n", ++ bootstate->name, target->name, target->priority); ++ continue; ++ } ++ ++ if (target->remaining_attempts == 0) { ++ pr(v, "%s: name=%s remaining attempts == 0 - trying next\n", ++ bootstate->name, target->name); ++ continue; ++ } ++ ++ if (flags & BOOTCHOOSER_FLAG_ATTEMPTS_DEC) { ++ bootstate->dirty = true; ++ target->remaining_attempts--; ++ ++ pr(v, "%s: name=%s decrementing remaining_attempts to %d due to %s\n", ++ bootstate->name, target->name, ++ target->remaining_attempts, ++ bootstate_flags_str[__BOOTCHOOSER_FLAG_ATTEMPTS_DEC_SHIFT]); ++ ++ if ((target->remaining_attempts == 0) && ++ (flags & BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS)) { ++ target->priority = 0; ++ ++ pr(v, "%s: name=%s deactivating target (setting priority = 0) due to %s\n", ++ bootstate->name, target->name, ++ bootstate_flags_str[__BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS_SHIFT]); ++ } ++ } ++ ++ found = true; ++ *target_out = strdup(target->name); ++ pr_debug("%s: selected target '%s'\n", __func__, target->name); ++ if (!v) ++ goto out; ++ ++ pr(v, "%s: --- other bootsources ---\n", bootstate->name); ++ } ++ ++ out: ++ bootstate_save(bootstate); ++ ++ if (!found) ++ return -ENOENT; ++ ++ return 0; ++} ++ ++int bootstate_bootchooser(char *name, unsigned flags, unsigned timeout) ++{ ++ struct bootstate *bootstate; ++ bool v = flags & BOOTCHOOSER_FLAG_VERBOSE; ++ char *target; ++ int ret; ++ ++ if (!name) ++ name = "bootstate"; ++ ++ bootstate = bootstate_by_name(name); ++ if (!bootstate) { ++ pr_err("Bootstate '%s' not found.\n", name); ++ return -ENODEV; ++ } ++ ++ if (flags & BOOTCHOOSER_FLAG_WATCHDOG_ENABLE) { ++ if (flags & BOOTCHOOSER_FLAG_WATCHDOG_TIMEOUT_FROM_STATE) { ++ ret = bootstate_variable_read_u32(bootstate, "watchdog_timeout", ++ &timeout); ++ if (ret) ++ return ret; ++ } ++ ++ if (timeout != 0) { ++ pr(v, "%s: starting watchdog with timeout=%ds\n", ++ __func__, timeout); ++ ++ ret = watchdog_set_timeout(timeout); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ while (true) { ++ char *cmd; ++ ++ ret = bootstate_get_target(bootstate, flags, &target); ++ if (ret) ++ return ret; ++ ++ cmd = asprintf("boot %s", target); ++ free(target); ++ pr_info("%srunning: %s...\n", ++ flags & BOOTCHOOSER_FLAG_DRYRUN ? "not " : "", cmd); ++ if (!(flags & BOOTCHOOSER_FLAG_DRYRUN)) ++ ret = run_command(cmd); ++ free(cmd); ++ ++ if (flags & BOOTCHOOSER_FLAG_RETRY_WITH_DEC) { ++ flags |= BOOTCHOOSER_FLAG_ATTEMPTS_DEC; ++ flags &= ~(BOOTCHOOSER_FLAG_ATTEMPTS_RESET | ++ BOOTCHOOSER_FLAG_ATTEMPTS_KEEP); ++ continue; ++ } ++ ++ return ret; ++ } ++ ++ return -ENOENT; ++} +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 7a5b14697efd..2459051e1db1 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -19,4 +19,9 @@ config STATE_DRV + tristate "state driver" + depends on STATE + ++config BOOTSTATE_DRV ++ tristate "bootstate driver" ++ depends on BOOTSTATE ++ depends on STATE ++ + endmenu +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index 487e4b8ba2e5..603e14ebb5de 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -5,3 +5,4 @@ + obj-$(CONFIG_JTAG) += jtag.o + obj-$(CONFIG_SRAM) += sram.o + obj-$(CONFIG_STATE_DRV) += state.o ++obj-$(CONFIG_BOOTSTATE_DRV) += bootstate.o +diff --git a/drivers/misc/bootstate.c b/drivers/misc/bootstate.c +new file mode 100644 +index 000000000000..3ec9b8fda86b +--- /dev/null ++++ b/drivers/misc/bootstate.c +@@ -0,0 +1,79 @@ ++/* ++ * Copyright (C) 2013 Sascha Hauer ++ * Copyright (C) 2015 Marc Kleine-Budde ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++static int bootstate_probe(struct device_d *dev) ++{ ++ struct device_node *np = dev->device_node; ++ struct bootstate *bootstate; ++ const char *alias; ++ const char *backend_type = NULL; ++ int ret; ++ ++ if (!np) ++ return -EINVAL; ++ ++ alias = of_alias_get(np); ++ if (!alias) ++ alias = "bootstate"; ++ ++ bootstate = bootstate_new_from_node(alias, np); ++ if (IS_ERR(bootstate)) ++ return PTR_ERR(bootstate); ++ ++ of_property_read_string(np, "backend-type", &backend_type); ++ if (!strcmp(backend_type, "state")) { ++ ret = bootstate_backend_state(bootstate, np); ++ } else if (!strcmp(backend_type, "nv")) { ++ ret = bootstate_backend_nv(bootstate); ++ } else { ++ dev_warn(dev, "invalid backend type: %s\n", backend_type); ++ ret = -ENODEV; ++ goto out_release; ++ } ++ ++ if (ret) ++ goto out_release; ++ ++ return 0; ++ ++ out_release: ++ bootstate_release(bootstate); ++ return ret; ++} ++ ++static __maybe_unused struct of_device_id bootstate_ids[] = { ++ { ++ .compatible = "barebox,bootstate", ++ }, { ++ /* sentinel */ ++ } ++}; ++ ++static struct driver_d bootstate_driver = { ++ .name = "bootstate", ++ .probe = bootstate_probe, ++ .of_compatible = DRV_OF_COMPAT(bootstate_ids), ++}; ++device_platform_driver(bootstate_driver); +diff --git a/include/bootstate.h b/include/bootstate.h +new file mode 100644 +index 000000000000..22631c902f60 +--- /dev/null ++++ b/include/bootstate.h +@@ -0,0 +1,39 @@ ++#ifndef __BOOTSTATE_H ++#define __BOOTSTATE_H ++ ++#include ++ ++struct bootstate *bootstate_new_from_node(const char *name, const struct device_node *node); ++struct bootstate *bootstate_find_by_name(const char *name); ++struct bootstate *bootstate_by_name(const char *name); ++void bootstate_release(struct bootstate *bootstate); ++void bootstate_info(void); ++int bootstate_backend_nv(struct bootstate *bootstate); ++int bootstate_backend_state(struct bootstate *bootstate, const struct device_node *node); ++ ++enum { ++ __BOOTCHOOSER_FLAG_ATTEMPTS_KEEP_SHIFT, ++ __BOOTCHOOSER_FLAG_ATTEMPTS_DEC_SHIFT, ++ __BOOTCHOOSER_FLAG_ATTEMPTS_RESET_SHIFT, ++ __BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS_SHIFT, ++ __BOOTCHOOSER_FLAG_VERBOSE_SHIFT, ++ __BOOTCHOOSER_FLAG_DRYRUN_SHIFT, ++ __BOOTCHOOSER_FLAG_RETRY_WITH_DEC_SHIFT, ++ __BOOTCHOOSER_FLAG_WATCHDOG_ENABLE_SHIFT, ++ __BOOTCHOOSER_FLAG_WATCHDOG_TIMEOUT_FROM_STATE_SHIFT, ++}; ++ ++#define BOOTCHOOSER_FLAG_ATTEMPTS_KEEP (1 << __BOOTCHOOSER_FLAG_ATTEMPTS_KEEP_SHIFT) ++#define BOOTCHOOSER_FLAG_ATTEMPTS_DEC (1 << __BOOTCHOOSER_FLAG_ATTEMPTS_DEC_SHIFT) ++#define BOOTCHOOSER_FLAG_ATTEMPTS_RESET (1 << __BOOTCHOOSER_FLAG_ATTEMPTS_RESET_SHIFT) ++#define BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS (1 << __BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS_SHIFT) ++#define BOOTCHOOSER_FLAG_VERBOSE (1 << __BOOTCHOOSER_FLAG_VERBOSE_SHIFT) ++#define BOOTCHOOSER_FLAG_DRYRUN (1 << __BOOTCHOOSER_FLAG_DRYRUN_SHIFT) ++#define BOOTCHOOSER_FLAG_RETRY_WITH_DEC (1 << __BOOTCHOOSER_FLAG_RETRY_WITH_DEC_SHIFT) ++#define BOOTCHOOSER_FLAG_WATCHDOG_ENABLE (1 << __BOOTCHOOSER_FLAG_WATCHDOG_ENABLE_SHIFT) ++#define BOOTCHOOSER_FLAG_WATCHDOG_TIMEOUT_FROM_STATE (1 << __BOOTCHOOSER_FLAG_WATCHDOG_TIMEOUT_FROM_STATE_SHIFT) ++ ++int bootstate_get_target(struct bootstate *bootstate, unsigned flags, char **target_out); ++int bootstate_bootchooser(char *name, unsigned flags, unsigned watchdog_timeout_s); ++ ++#endif /* __BOOTSTATE_H */ diff --git a/configs/platform-v7a/patches/barebox-2016.05.0/0002-bootstate-Add-kernel-option-containing-the-system-th.patch b/configs/platform-v7a/patches/barebox-2016.05.0/0002-bootstate-Add-kernel-option-containing-the-system-th.patch new file mode 100644 index 0000000..719cd50 --- /dev/null +++ b/configs/platform-v7a/patches/barebox-2016.05.0/0002-bootstate-Add-kernel-option-containing-the-system-th.patch @@ -0,0 +1,43 @@ +From: Sascha Hauer +Date: Mon, 20 Jul 2015 20:44:00 +0200 +Subject: [PATCH] bootstate: Add kernel option containing the system that is + started + +This is useful to allow the userspace to determine which system +is actually started without dissecting the root= option. + +Signed-off-by: Sascha Hauer +--- + common/bootstate.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/common/bootstate.c b/common/bootstate.c +index 3dc18813064d..b0cb0183068a 100644 +--- a/common/bootstate.c ++++ b/common/bootstate.c +@@ -753,12 +753,16 @@ int bootstate_bootchooser(char *name, unsigned flags, unsigned timeout) + } + + while (true) { +- char *cmd; ++ char *cmd, *system; + + ret = bootstate_get_target(bootstate, flags, &target); + if (ret) + return ret; + ++ system = asprintf("bootstate.active=%s", target); ++ globalvar_add_simple("linux.bootargs.bootchooser", system); ++ free(system); ++ + cmd = asprintf("boot %s", target); + free(target); + pr_info("%srunning: %s...\n", +@@ -766,6 +770,7 @@ int bootstate_bootchooser(char *name, unsigned flags, unsigned timeout) + if (!(flags & BOOTCHOOSER_FLAG_DRYRUN)) + ret = run_command(cmd); + free(cmd); ++ globalvar_set_match("linux.bootargs.bootchooser", NULL); + + if (flags & BOOTCHOOSER_FLAG_RETRY_WITH_DEC) { + flags |= BOOTCHOOSER_FLAG_ATTEMPTS_DEC; diff --git a/configs/platform-v7a/patches/barebox-2016.05.0/0003-bootstate-separate-names-from-boot-targets.patch b/configs/platform-v7a/patches/barebox-2016.05.0/0003-bootstate-separate-names-from-boot-targets.patch new file mode 100644 index 0000000..77f4949 --- /dev/null +++ b/configs/platform-v7a/patches/barebox-2016.05.0/0003-bootstate-separate-names-from-boot-targets.patch @@ -0,0 +1,63 @@ +From: Sascha Hauer +Date: Thu, 23 Jul 2015 16:42:18 +0200 +Subject: [PATCH] bootstate: separate names from boot targets + +The name of a boot target and the device or script to boot may be two +different things. Allow a 'boot' property in the boot targets. + +Signed-off-by: Sascha Hauer +--- + common/bootstate.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/common/bootstate.c b/common/bootstate.c +index b0cb0183068a..fde278262fa3 100644 +--- a/common/bootstate.c ++++ b/common/bootstate.c +@@ -75,6 +75,7 @@ struct bootstate_target { + /* spec */ + const char *name; + unsigned int default_attempts; ++ const char *boot; + }; + + static void pr_target(struct bootstate *bootstate, struct bootstate_target *target) +@@ -205,7 +206,7 @@ static struct bootstate_target *bootstate_target_find(const struct bootstate *bo + return ERR_PTR(-ENOENT); + } + +-static int bootstate_target_from_node(struct bootstate *bootstate, const struct device_node *node, bool create) ++static int bootstate_target_from_node(struct bootstate *bootstate, struct device_node *node, bool create) + { + struct bootstate_target *target; + char *name, *indexs; +@@ -217,10 +218,18 @@ static int bootstate_target_from_node(struct bootstate *bootstate, const struct + *indexs++ = 0; + + if (create) { ++ const char *boot; ++ + /* create*/ + target = xzalloc(sizeof(*target)); + + target->name = xstrdup(name); ++ ++ if (!of_property_read_string(node, "boot", &boot)) ++ target->boot = xstrdup(boot); ++ else ++ target->boot = xstrdup(name); ++ + list_add_tail(&target->list, &bootstate->targets); + list_add_tail(&target->list_unsorted, + &bootstate->targets_unsorted); +@@ -701,8 +710,9 @@ int bootstate_get_target(struct bootstate *bootstate, unsigned flags, char **tar + } + + found = true; +- *target_out = strdup(target->name); +- pr_debug("%s: selected target '%s'\n", __func__, target->name); ++ *target_out = strdup(target->boot); ++ pr_debug("%s: selected target '%s', boot '%s'\n", ++ __func__, target->name, target->boot); + if (!v) + goto out; diff --git a/configs/platform-v7a/patches/barebox-2016.05.0/0004-bootstate-set-kernel-option-to-name-of-boot-target.patch b/configs/platform-v7a/patches/barebox-2016.05.0/0004-bootstate-set-kernel-option-to-name-of-boot-target.patch new file mode 100644 index 0000000..1db763c --- /dev/null +++ b/configs/platform-v7a/patches/barebox-2016.05.0/0004-bootstate-set-kernel-option-to-name-of-boot-target.patch @@ -0,0 +1,119 @@ +From: Sascha Hauer +Date: Mon, 27 Jul 2015 13:39:45 +0200 +Subject: [PATCH] bootstate: set kernel option to name of boot target + +Signed-off-by: Sascha Hauer +--- + common/bootstate.c | 60 ++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 36 insertions(+), 24 deletions(-) + +diff --git a/common/bootstate.c b/common/bootstate.c +index fde278262fa3..2dcc47cfa257 100644 +--- a/common/bootstate.c ++++ b/common/bootstate.c +@@ -631,20 +631,8 @@ void _pr_flags(struct bootstate *bootstate, unsigned flags) + (verbose) ? _pr_flags(bootstate, flags) : 0; \ + }) + +-/* +- * bootstate_get_target - create a new state instance from a device_node +- * +- * @bootstate the bootstate instance to work in +- * @flags supported flags: +- * BOOTCHOOSER_FLAG_VERBOSE +- * BOOTCHOOSER_FLAG_ATTEMPTS_KEEP +- * BOOTCHOOSER_FLAG_ATTEMPTS_DEC +- * BOOTCHOOSER_FLAG_ATTEMPTS_RESET +- * BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS +- * @target_out a string to the choosen boot target is returned via +- * this paramater +- */ +-int bootstate_get_target(struct bootstate *bootstate, unsigned flags, char **target_out) ++static struct bootstate_target *bootstate_target_get(struct bootstate *bootstate, ++ unsigned flags) + { + struct bootstate_target *target; + int ret; +@@ -655,7 +643,7 @@ int bootstate_get_target(struct bootstate *bootstate, unsigned flags, char **tar + + ret = bootstate_load(bootstate); + if (ret) +- return ret; ++ return ERR_PTR(ret); + + if (flags & BOOTCHOOSER_FLAG_ATTEMPTS_RESET) { + list_for_each_entry(target, &bootstate->targets, list) { +@@ -710,7 +698,6 @@ int bootstate_get_target(struct bootstate *bootstate, unsigned flags, char **tar + } + + found = true; +- *target_out = strdup(target->boot); + pr_debug("%s: selected target '%s', boot '%s'\n", + __func__, target->name, target->boot); + if (!v) +@@ -723,7 +710,33 @@ int bootstate_get_target(struct bootstate *bootstate, unsigned flags, char **tar + bootstate_save(bootstate); + + if (!found) +- return -ENOENT; ++ return ERR_PTR(-ENOENT); ++ ++ return target; ++} ++ ++/* ++ * bootstate_get_target - create a new state instance from a device_node ++ * ++ * @bootstate the bootstate instance to work in ++ * @flags supported flags: ++ * BOOTCHOOSER_FLAG_VERBOSE ++ * BOOTCHOOSER_FLAG_ATTEMPTS_KEEP ++ * BOOTCHOOSER_FLAG_ATTEMPTS_DEC ++ * BOOTCHOOSER_FLAG_ATTEMPTS_RESET ++ * BOOTCHOOSER_FLAG_DEACTIVATE_ON_ZERO_ATTEMPTS ++ * @target_out a string to the choosen boot target is returned via ++ * this paramater ++ */ ++int bootstate_get_target(struct bootstate *bootstate, unsigned flags, char **target_out) ++{ ++ struct bootstate_target *target; ++ ++ target = bootstate_target_get(bootstate, flags); ++ if (IS_ERR(target)) ++ return PTR_ERR(target); ++ ++ *target_out = strdup(target->boot); + + return 0; + } +@@ -732,7 +745,7 @@ int bootstate_bootchooser(char *name, unsigned flags, unsigned timeout) + { + struct bootstate *bootstate; + bool v = flags & BOOTCHOOSER_FLAG_VERBOSE; +- char *target; ++ struct bootstate_target *target; + int ret; + + if (!name) +@@ -765,16 +778,15 @@ int bootstate_bootchooser(char *name, unsigned flags, unsigned timeout) + while (true) { + char *cmd, *system; + +- ret = bootstate_get_target(bootstate, flags, &target); +- if (ret) +- return ret; ++ target = bootstate_target_get(bootstate, flags); ++ if (IS_ERR(target)) ++ return PTR_ERR(target); + +- system = asprintf("bootstate.active=%s", target); ++ system = asprintf("bootstate.active=%s", target->name); + globalvar_add_simple("linux.bootargs.bootchooser", system); + free(system); + +- cmd = asprintf("boot %s", target); +- free(target); ++ cmd = asprintf("boot %s", target->boot); + pr_info("%srunning: %s...\n", + flags & BOOTCHOOSER_FLAG_DRYRUN ? "not " : "", cmd); + if (!(flags & BOOTCHOOSER_FLAG_DRYRUN)) diff --git a/configs/platform-v7a/patches/barebox-2016.05.0/0101-beaglebone-add-state-entrie-for-mmc0-and-mmc1.patch b/configs/platform-v7a/patches/barebox-2016.05.0/0101-beaglebone-add-state-entrie-for-mmc0-and-mmc1.patch new file mode 100644 index 0000000..9761b58 --- /dev/null +++ b/configs/platform-v7a/patches/barebox-2016.05.0/0101-beaglebone-add-state-entrie-for-mmc0-and-mmc1.patch @@ -0,0 +1,35 @@ +From: Michael Grzeschik +Date: Fri, 10 Jun 2016 14:02:30 +0200 +Subject: [PATCH] beaglebone: add state entrie for mmc0 and mmc1 + +Signed-off-by: Michael Grzeschik +--- + arch/arm/dts/am335x-bone-common.dtsi | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm/dts/am335x-bone-common.dtsi b/arch/arm/dts/am335x-bone-common.dtsi +index ef97d906616c..d14c6ded6a55 100644 +--- a/arch/arm/dts/am335x-bone-common.dtsi ++++ b/arch/arm/dts/am335x-bone-common.dtsi +@@ -11,6 +11,21 @@ + linux,stdout-path = &uart0; + }; + ++ bootstate: bootstate { ++ compatible = "barebox,bootstate"; ++ backend-type = "nv"; ++ ++ system0 { ++ default_attempts = <3>; ++ boot = "mmc0"; ++ }; ++ ++ system1 { ++ default_attempts = <3>; ++ boot = "mmc1"; ++ }; ++ }; ++ + cpus { + cpu@0 { + cpu0-supply = <&dcdc2_reg>; diff --git a/configs/platform-v7a/patches/barebox-2016.05.0/0201-rpi2-add-basic-boot-spec-devicetree-support.patch b/configs/platform-v7a/patches/barebox-2016.05.0/0201-rpi2-add-basic-boot-spec-devicetree-support.patch new file mode 100644 index 0000000..40d67be --- /dev/null +++ b/configs/platform-v7a/patches/barebox-2016.05.0/0201-rpi2-add-basic-boot-spec-devicetree-support.patch @@ -0,0 +1,462 @@ +From: Alexander Aring +Date: Thu, 9 Jun 2016 11:26:03 +0200 +Subject: [PATCH] rpi2: add basic boot-spec devicetree support + +Signed-off-by: Alexander Aring +--- + arch/arm/dts/Makefile | 1 + + arch/arm/dts/bcm2835-rpi.dtsi | 60 +++++++++++ + arch/arm/dts/bcm2836-rpi-2-b.dts | 35 +++++++ + arch/arm/dts/bcm2836.dtsi | 78 ++++++++++++++ + arch/arm/dts/bcm283x.dtsi | 212 +++++++++++++++++++++++++++++++++++++++ + arch/arm/mach-bcm283x/core.c | 4 +- + 6 files changed, 389 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/dts/bcm2835-rpi.dtsi + create mode 100644 arch/arm/dts/bcm2836-rpi-2-b.dts + create mode 100644 arch/arm/dts/bcm2836.dtsi + create mode 100644 arch/arm/dts/bcm283x.dtsi + +diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile +index b83c1109ef39..960d8aac3933 100644 +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -9,6 +9,7 @@ obj- += dummy.o + + pbl-dtb-$(CONFIG_MACH_AFI_GF) += am335x-afi-gf.dtb.o + pbl-dtb-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o ++pbl-dtb-$(CONFIG_MACH_RPI2) += bcm2836-rpi-2-b.dtb.o + pbl-dtb-$(CONFIG_MACH_CM_FX6) += imx6dl-cm-fx6.dtb.o imx6q-cm-fx6.dtb.o imx6q-utilite.dtb.o + pbl-dtb-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o + pbl-dtb-$(CONFIG_MACH_DUCKBILL) += imx28-duckbill.dtb.o +diff --git a/arch/arm/dts/bcm2835-rpi.dtsi b/arch/arm/dts/bcm2835-rpi.dtsi +new file mode 100644 +index 000000000000..3afb9fefe2d1 +--- /dev/null ++++ b/arch/arm/dts/bcm2835-rpi.dtsi +@@ -0,0 +1,60 @@ ++/ { ++ memory { ++ reg = <0 0x10000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ act { ++ label = "ACT"; ++ default-state = "keep"; ++ linux,default-trigger = "heartbeat"; ++ }; ++ }; ++ ++ soc { ++ firmware: firmware { ++ compatible = "raspberrypi,bcm2835-firmware"; ++ mboxes = <&mailbox>; ++ }; ++ }; ++}; ++ ++&gpio { ++ pinctrl-names = "default"; ++ ++ gpioout: gpioout { ++ brcm,pins = <6>; ++ brcm,function = ; ++ }; ++ ++ alt0: alt0 { ++ brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>; ++ brcm,function = ; ++ }; ++ ++ alt3: alt3 { ++ brcm,pins = <48 49 50 51 52 53>; ++ brcm,function = ; ++ }; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ clock-frequency = <100000>; ++}; ++ ++&i2c2 { ++ status = "okay"; ++}; ++ ++&sdhci { ++ status = "okay"; ++ bus-width = <4>; ++}; +diff --git a/arch/arm/dts/bcm2836-rpi-2-b.dts b/arch/arm/dts/bcm2836-rpi-2-b.dts +new file mode 100644 +index 000000000000..ff946661bd13 +--- /dev/null ++++ b/arch/arm/dts/bcm2836-rpi-2-b.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++#include "bcm2836.dtsi" ++#include "bcm2835-rpi.dtsi" ++ ++/ { ++ compatible = "raspberrypi,2-model-b", "brcm,bcm2836"; ++ model = "Raspberry Pi 2 Model B"; ++ ++ memory { ++ reg = <0 0x40000000>; ++ }; ++ ++ leds { ++ act { ++ gpios = <&gpio 47 0>; ++ }; ++ ++ pwr { ++ label = "PWR"; ++ gpios = <&gpio 35 0>; ++ default-state = "keep"; ++ linux,default-trigger = "default-on"; ++ }; ++ }; ++}; ++ ++&gpio { ++ pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; ++ ++ /* I2S interface */ ++ i2s_alt0: i2s_alt0 { ++ brcm,pins = <18 19 20 21>; ++ brcm,function = ; ++ }; ++}; +diff --git a/arch/arm/dts/bcm2836.dtsi b/arch/arm/dts/bcm2836.dtsi +new file mode 100644 +index 000000000000..9d0651d8f373 +--- /dev/null ++++ b/arch/arm/dts/bcm2836.dtsi +@@ -0,0 +1,78 @@ ++#include "bcm283x.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2836"; ++ ++ soc { ++ ranges = <0x7e000000 0x3f000000 0x1000000>, ++ <0x40000000 0x40000000 0x00001000>; ++ dma-ranges = <0xc0000000 0x00000000 0x3f000000>; ++ ++ local_intc: local_intc { ++ compatible = "brcm,bcm2836-l1-intc"; ++ reg = <0x40000000 0x100>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&local_intc>; ++ }; ++ ++ arm-pmu { ++ compatible = "arm,cortex-a7-pmu"; ++ interrupt-parent = <&local_intc>; ++ interrupts = <9>; ++ }; ++ }; ++ ++ timer { ++ compatible = "arm,armv7-timer"; ++ interrupt-parent = <&local_intc>; ++ interrupts = <0>, // PHYS_SECURE_PPI ++ <1>, // PHYS_NONSECURE_PPI ++ <3>, // VIRT_PPI ++ <2>; // HYP_PPI ++ always-on; ++ }; ++ ++ cpus: cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ v7_cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf00>; ++ clock-frequency = <800000000>; ++ }; ++ ++ v7_cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf01>; ++ clock-frequency = <800000000>; ++ }; ++ ++ v7_cpu2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf02>; ++ clock-frequency = <800000000>; ++ }; ++ ++ v7_cpu3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0xf03>; ++ clock-frequency = <800000000>; ++ }; ++ }; ++}; ++ ++/* Make the BCM2835-style global interrupt controller be a child of the ++ * CPU-local interrupt controller. ++ */ ++&intc { ++ compatible = "brcm,bcm2836-armctrl-ic"; ++ reg = <0x7e00b200 0x200>; ++ interrupt-parent = <&local_intc>; ++ interrupts = <8>; ++}; +diff --git a/arch/arm/dts/bcm283x.dtsi b/arch/arm/dts/bcm283x.dtsi +new file mode 100644 +index 000000000000..971e741e5467 +--- /dev/null ++++ b/arch/arm/dts/bcm283x.dtsi +@@ -0,0 +1,212 @@ ++#include ++#include ++#include "skeleton.dtsi" ++ ++/* This include file covers the common peripherals and configuration between ++ * bcm2835 and bcm2836 implementations, leaving the CPU configuration to ++ * bcm2835.dtsi and bcm2836.dtsi. ++ */ ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ model = "BCM2835"; ++ interrupt-parent = <&intc>; ++ ++ chosen { ++ bootargs = "earlyprintk console=ttyAMA0"; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ timer@7e003000 { ++ compatible = "brcm,bcm2835-system-timer"; ++ reg = <0x7e003000 0x1000>; ++ interrupts = <1 0>, <1 1>, <1 2>, <1 3>; ++ /* This could be a reference to BCM2835_CLOCK_TIMER, ++ * but we don't have the driver using the common clock ++ * support yet. ++ */ ++ clock-frequency = <1000000>; ++ }; ++ ++ dma: dma@7e007000 { ++ compatible = "brcm,bcm2835-dma"; ++ reg = <0x7e007000 0xf00>; ++ interrupts = <1 16>, ++ <1 17>, ++ <1 18>, ++ <1 19>, ++ <1 20>, ++ <1 21>, ++ <1 22>, ++ <1 23>, ++ <1 24>, ++ <1 25>, ++ <1 26>, ++ <1 27>, ++ <1 28>; ++ ++ #dma-cells = <1>; ++ brcm,dma-channel-mask = <0x7f35>; ++ }; ++ ++ intc: interrupt-controller@7e00b200 { ++ compatible = "brcm,bcm2835-armctrl-ic"; ++ reg = <0x7e00b200 0x200>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ watchdog@7e100000 { ++ compatible = "brcm,bcm2835-pm-wdt"; ++ reg = <0x7e100000 0x28>; ++ }; ++ ++ clocks: cprman@7e101000 { ++ compatible = "brcm,bcm2835-cprman"; ++ #clock-cells = <1>; ++ reg = <0x7e101000 0x2000>; ++ ++ /* CPRMAN derives everything from the platform's ++ * oscillator. ++ */ ++ clocks = <&clk_osc>; ++ }; ++ ++ rng@7e104000 { ++ compatible = "brcm,bcm2835-rng"; ++ reg = <0x7e104000 0x10>; ++ }; ++ ++ mailbox: mailbox@7e00b800 { ++ compatible = "brcm,bcm2835-mbox"; ++ reg = <0x7e00b880 0x40>; ++ interrupts = <0 1>; ++ #mbox-cells = <0>; ++ }; ++ ++ gpio: gpio@7e200000 { ++ compatible = "brcm,bcm2835-gpio"; ++ reg = <0x7e200000 0xb4>; ++ /* ++ * The GPIO IP block is designed for 3 banks of GPIOs. ++ * Each bank has a GPIO interrupt for itself. ++ * There is an overall "any bank" interrupt. ++ * In order, these are GIC interrupts 17, 18, 19, 20. ++ * Since the BCM2835 only has 2 banks, the 2nd bank ++ * interrupt output appears to be mirrored onto the ++ * 3rd bank's interrupt signal. ++ * So, a bank0 interrupt shows up on 17, 20, and ++ * a bank1 interrupt shows up on 18, 19, 20! ++ */ ++ interrupts = <2 17>, <2 18>, <2 19>, <2 20>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ uart0: uart@7e201000 { ++ compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; ++ reg = <0x7e201000 0x1000>; ++ interrupts = <2 25>; ++ clocks = <&clocks BCM2835_CLOCK_UART>, ++ <&clocks BCM2835_CLOCK_VPU>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ }; ++ ++ i2s: i2s@7e203000 { ++ compatible = "brcm,bcm2835-i2s"; ++ reg = <0x7e203000 0x20>, ++ <0x7e101098 0x02>; ++ ++ dmas = <&dma 2>, ++ <&dma 3>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ spi: spi@7e204000 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7e204000 0x1000>; ++ interrupts = <2 22>; ++ clocks = <&clocks BCM2835_CLOCK_VPU>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@7e205000 { ++ compatible = "brcm,bcm2835-i2c"; ++ reg = <0x7e205000 0x1000>; ++ interrupts = <2 21>; ++ clocks = <&clocks BCM2835_CLOCK_VPU>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ aux: aux@0x7e215000 { ++ compatible = "brcm,bcm2835-aux"; ++ #clock-cells = <1>; ++ reg = <0x7e215000 0x8>; ++ clocks = <&clocks BCM2835_CLOCK_VPU>; ++ }; ++ ++ sdhci: sdhci@7e300000 { ++ compatible = "brcm,bcm2835-sdhci"; ++ reg = <0x7e300000 0x100>; ++ interrupts = <2 30>; ++ clocks = <&clocks BCM2835_CLOCK_EMMC>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@7e804000 { ++ compatible = "brcm,bcm2835-i2c"; ++ reg = <0x7e804000 0x1000>; ++ interrupts = <2 21>; ++ clocks = <&clocks BCM2835_CLOCK_VPU>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@7e805000 { ++ compatible = "brcm,bcm2835-i2c"; ++ reg = <0x7e805000 0x1000>; ++ interrupts = <2 21>; ++ clocks = <&clocks BCM2835_CLOCK_VPU>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ usb@7e980000 { ++ compatible = "brcm,bcm2835-usb"; ++ reg = <0x7e980000 0x10000>; ++ interrupts = <1 9>; ++ }; ++ }; ++ ++ clocks { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* The oscillator is the root of the clock tree. */ ++ clk_osc: clock@3 { ++ compatible = "fixed-clock"; ++ reg = <3>; ++ #clock-cells = <0>; ++ clock-output-names = "osc"; ++ clock-frequency = <19200000>; ++ }; ++ ++ }; ++}; +diff --git a/arch/arm/mach-bcm283x/core.c b/arch/arm/mach-bcm283x/core.c +index 64f37813883a..f11221dd6685 100644 +--- a/arch/arm/mach-bcm283x/core.c ++++ b/arch/arm/mach-bcm283x/core.c +@@ -42,15 +42,17 @@ static int bcm2835_clk_init(void) + + clk = clk_fixed("uart0-pl0110", 3 * 1000 * 1000); + clk_register_clkdev(clk, NULL, "uart0-pl0110"); ++ clk_register_clkdev(clk, NULL, "3f201000.uart"); + + clk = clk_fixed("bcm2835-cs", 1 * 1000 * 1000); + clk_register_clkdev(clk, NULL, "bcm2835-cs"); ++ clk_register_clkdev(clk, NULL, "3f003000.timer"); + + add_generic_device("bcm2835-cs", DEVICE_ID_SINGLE, NULL, BCM2835_ST_BASE, 0x1C, IORESOURCE_MEM, NULL); + + return 0; + } +-postcore_initcall(bcm2835_clk_init); ++pure_initcall(bcm2835_clk_init); + + void bcm2835_register_uart(void) + { diff --git a/configs/platform-v7a/patches/barebox-2016.05.0/0301-Release-2016.05.0-customers-pengutronix-multi_v7-201.patch b/configs/platform-v7a/patches/barebox-2016.05.0/0301-Release-2016.05.0-customers-pengutronix-multi_v7-201.patch new file mode 100644 index 0000000..76e12c8 --- /dev/null +++ b/configs/platform-v7a/patches/barebox-2016.05.0/0301-Release-2016.05.0-customers-pengutronix-multi_v7-201.patch @@ -0,0 +1,22 @@ +From: Michael Grzeschik +Date: Fri, 10 Jun 2016 14:10:58 +0200 +Subject: [PATCH] Release 2016.05.0/customers/pengutronix/multi_v7/20160610-1 + +Signed-off-by: Michael Grzeschik +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 93f1d17d99d2..b844aa674da5 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + VERSION = 2016 + PATCHLEVEL = 05 + SUBLEVEL = 0 +-EXTRAVERSION = ++EXTRAVERSION =-20160610-1 + NAME = None + + # *DOCUMENTATION* diff --git a/configs/platform-v7a/patches/barebox-2016.05.0/series b/configs/platform-v7a/patches/barebox-2016.05.0/series new file mode 100644 index 0000000..a93c9d2 --- /dev/null +++ b/configs/platform-v7a/patches/barebox-2016.05.0/series @@ -0,0 +1,22 @@ +# umpf-base: v2016.05.0 +# umpf-name: 2016.05.0/customers/pengutronix/multi_v7 +# umpf-version: 2016.05.0/customers/pengutronix/multi_v7/20160610-1 +# umpf-topic: v2016.05.0/topic/bootstate +# umpf-hashinfo: bfaa55682a5f53a0f679ab08e6b55350594ed047 +# umpf-topic-range: f5142b8564005d95324e4c326dbc390ce85e8bef..bfaa55682a5f53a0f679ab08e6b55350594ed047 +0001-bootstate-add-framework-for-redundant-boot-scenarios.patch +0002-bootstate-Add-kernel-option-containing-the-system-th.patch +0003-bootstate-separate-names-from-boot-targets.patch +0004-bootstate-set-kernel-option-to-name-of-boot-target.patch +# umpf-topic: v2016.05.0/customers/pengutronix/beaglebone +# umpf-hashinfo: 9cbaeb8cfaa8b5e7837725df242aacccbbc5fa53 +# umpf-topic-range: bfaa55682a5f53a0f679ab08e6b55350594ed047..c95ad802cdf09922b56027338b85cd58de732c2a +0101-beaglebone-add-state-entrie-for-mmc0-and-mmc1.patch +# umpf-topic: v2016.05.0/customers/pengutronix/rpi2 +# umpf-hashinfo: 2df94ba7d6c5680032d7da8c1554cf01c7ca845b +# umpf-topic-range: c95ad802cdf09922b56027338b85cd58de732c2a..64afca484be01d3a0329b289fe4667608495e14b +0201-rpi2-add-basic-boot-spec-devicetree-support.patch +# umpf-release: 2016.05.0/customers/pengutronix/multi_v7/20160610-1 +# umpf-topic-range: 64afca484be01d3a0329b289fe4667608495e14b..92019e24a71b3a5484927b84863d0f2bf34aae51 +0301-Release-2016.05.0-customers-pengutronix-multi_v7-201.patch +# umpf-end -- cgit v1.2.3