All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/3] Add reboot mode support
@ 2019-11-12  9:13 Han Nandor
  2019-11-12  9:13 ` [U-Boot] [PATCH 1/3] reboot-mode: add support for reboot mode control Han Nandor
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Han Nandor @ 2019-11-12  9:13 UTC (permalink / raw)
  To: u-boot

Description
-----------
Add support for reboot-mode configuration using GPIOs and RTC SRAM as
back-end.

Testing
-------

Tested on a Zynq based board where device tree was configured to contain
the reboot-mode configuration:

&amba {
    status = "okay";

    reboot-mode-gpio {
        compatible = "reboot-mode-gpio";
        gpios = <&gpio0 47 GPIO_ACTIVE_LOW>;
        mode-test = <0x1>;
    };

    reboot-mode-rtc {
        compatible = "reboot-mode-rtc";
        rtc = <&rtc_0>;
        reg = <0x14 4>;
        mode-test = <0x21969147>;
    };
};

In addition to this and not part of this patchset is a change to board.c
where GPIO or RTC SRAM backed is selected dynamically at runtime.

1. Test that the reboot mode configured in user-space is read in U-Boot and
environment configured: PASS

Userspace ~ # reboot test
....
[  177.335936] reboot: Restarting system with command 'test'

U-Boot SPL 2019.01 (Mar 29 2019 - 10:44:22 +0000)
...
U-Boot> print reboot-mode
reboot-mode=test

2. Reset the system using the reset command and stop in U-Boot.
3. Verify that reboot-mode env variable is not configured anymore: PASS

U-Boot> print reboot-mode
## Error: "reboot-mode" not defined

4. Toggle the GPIO configured for test mode to active and reset the system
with command reset.
5. Stop in U-Boot and check that reboot-mode env variable is configured:PASS

U-Boot> print reboot-mode
reboot-mode=test

Nandor Han (3):
  reboot-mode: add support for reboot mode control
  reboot-mode: read the boot mode from GPIOs status
  reboot-mode: read the boot mode from RTC memory

 .../reboot-mode/reboot-mode-gpio.txt          |  20 +++
 .../reboot-mode/reboot-mode-rtc.txt           |  22 +++
 drivers/Kconfig                               |   2 +
 drivers/Makefile                              |   1 +
 drivers/reboot-mode/Kconfig                   |  36 +++++
 drivers/reboot-mode/Makefile                  |   9 ++
 drivers/reboot-mode/reboot-mode-gpio.c        | 125 +++++++++++++++++
 drivers/reboot-mode/reboot-mode-rtc.c         | 132 ++++++++++++++++++
 drivers/reboot-mode/reboot-mode-uclass.c      | 132 ++++++++++++++++++
 include/dm/uclass-id.h                        |   1 +
 include/reboot-mode/reboot-mode-gpio.h        |  32 +++++
 include/reboot-mode/reboot-mode-rtc.h         |  16 +++
 include/reboot-mode/reboot-mode.h             |  56 ++++++++
 13 files changed, 584 insertions(+)
 create mode 100644 doc/device-tree-bindings/reboot-mode/reboot-mode-gpio.txt
 create mode 100644 doc/device-tree-bindings/reboot-mode/reboot-mode-rtc.txt
 create mode 100644 drivers/reboot-mode/Kconfig
 create mode 100644 drivers/reboot-mode/Makefile
 create mode 100644 drivers/reboot-mode/reboot-mode-gpio.c
 create mode 100644 drivers/reboot-mode/reboot-mode-rtc.c
 create mode 100644 drivers/reboot-mode/reboot-mode-uclass.c
 create mode 100644 include/reboot-mode/reboot-mode-gpio.h
 create mode 100644 include/reboot-mode/reboot-mode-rtc.h
 create mode 100644 include/reboot-mode/reboot-mode.h

-- 
2.20.1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 1/3] reboot-mode: add support for reboot mode control
  2019-11-12  9:13 [U-Boot] [PATCH 0/3] Add reboot mode support Han Nandor
@ 2019-11-12  9:13 ` Han Nandor
  2020-01-30 11:49   ` Nandor Han
  2019-11-12  9:13 ` [U-Boot] [PATCH 2/3] reboot-mode: read the boot mode from GPIOs status Han Nandor
  2019-11-12  9:13 ` [U-Boot] [PATCH 3/3] reboot-mode: read the boot mode from RTC memory Han Nandor
  2 siblings, 1 reply; 5+ messages in thread
From: Han Nandor @ 2019-11-12  9:13 UTC (permalink / raw)
  To: u-boot

A new driver uclass is created to handle the reboot mode control.

The new uclass driver is updating an environment variable with the
configured reboot mode. The mode is extracted from a map provided
at initialization time. The map contains a list of modes
and associated ids.

Signed-off-by: Nandor Han <nandor.han@vaisala.com>
---
 drivers/Kconfig                          |   2 +
 drivers/Makefile                         |   1 +
 drivers/reboot-mode/Kconfig              |  18 ++++
 drivers/reboot-mode/Makefile             |   7 ++
 drivers/reboot-mode/reboot-mode-uclass.c | 132 +++++++++++++++++++++++
 include/dm/uclass-id.h                   |   1 +
 include/reboot-mode/reboot-mode.h        |  56 ++++++++++
 7 files changed, 217 insertions(+)
 create mode 100644 drivers/reboot-mode/Kconfig
 create mode 100644 drivers/reboot-mode/Makefile
 create mode 100644 drivers/reboot-mode/reboot-mode-uclass.c
 create mode 100644 include/reboot-mode/reboot-mode.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 9d99ce0226..aa7c35331e 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -86,6 +86,8 @@ source "drivers/qe/Kconfig"
 
 source "drivers/ram/Kconfig"
 
+source "drivers/reboot-mode/Kconfig"
+
 source "drivers/remoteproc/Kconfig"
 
 source "drivers/reset/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 0befeddfcb..6435bac2db 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -92,6 +92,7 @@ obj-y += dfu/
 obj-$(CONFIG_PCH) += pch/
 obj-y += phy/allwinner/
 obj-y += phy/marvell/
+obj-$(CONFIG_DM_REBOOT_MODE) += reboot-mode/
 obj-y += rtc/
 obj-y += scsi/
 obj-y += sound/
diff --git a/drivers/reboot-mode/Kconfig b/drivers/reboot-mode/Kconfig
new file mode 100644
index 0000000000..0edc3209d7
--- /dev/null
+++ b/drivers/reboot-mode/Kconfig
@@ -0,0 +1,18 @@
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c), Vaisala Oyj
+#
+
+menu "Reboot Mode Support"
+
+config DM_REBOOT_MODE
+	bool "Enable reboot mode using Driver Model"
+	depends on DM
+	default n
+	help
+		Enable support for reboot mode control. This will allow users to
+		adjust the boot process based on reboot mode parameter
+		passed to U-Boot.
+
+endmenu
diff --git a/drivers/reboot-mode/Makefile b/drivers/reboot-mode/Makefile
new file mode 100644
index 0000000000..2ab0fddac9
--- /dev/null
+++ b/drivers/reboot-mode/Makefile
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c), Vaisala Oyj
+#
+
+obj-$(CONFIG_DM_REBOOT_MODE) += reboot-mode-uclass.o
diff --git a/drivers/reboot-mode/reboot-mode-uclass.c b/drivers/reboot-mode/reboot-mode-uclass.c
new file mode 100644
index 0000000000..78b54836df
--- /dev/null
+++ b/drivers/reboot-mode/reboot-mode-uclass.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c), Vaisala Oyj
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <reboot-mode/reboot-mode.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dm_reboot_mode_update(struct udevice *dev)
+{
+	struct reboot_mode_ops *ops = reboot_mode_get_ops(dev);
+	u32 rebootmode;
+	int ret, i;
+
+	assert(ops);
+
+	if (!ops->get)
+		return -ENOSYS;
+
+	ret = ops->get(dev, &rebootmode);
+	if (ret < 0) {
+		dev_err(dev, "Failed to retrieve the reboot mode value\n");
+		return ret;
+	}
+
+	const struct reboot_mode_uclass_platdata *plat_data =
+		dev_get_uclass_platdata(dev);
+
+	for (i = 0; i < plat_data->count; i++) {
+		if (plat_data->modes[i].mode_id == rebootmode) {
+			ret = env_set(plat_data->env_variable,
+				      plat_data->modes[i].mode_name);
+			if (ret) {
+				dev_err(dev, "Failed to set env: %s\n",
+					plat_data->env_variable);
+				return ret;
+			}
+		}
+	}
+
+	if (ops->set) {
+		/* Clear the value */
+		rebootmode = 0;
+		ret = ops->set(dev, rebootmode);
+		if (ret) {
+			dev_err(dev, "Failed to clear the reboot mode\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int dm_reboot_mode_pre_probe(struct udevice *dev)
+{
+	struct reboot_mode_uclass_platdata *plat_data;
+
+	plat_data = dev_get_uclass_platdata(dev);
+	if (!plat_data)
+		return -EINVAL;
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	const int node = dev_of_offset(dev);
+	const char *mode_prefix = "mode-";
+	const int mode_prefix_len = strlen(mode_prefix);
+	int property;
+	const u32 *propvalue;
+	const char *propname;
+
+	plat_data->env_variable = fdt_getprop(gd->fdt_blob,
+					      node,
+					      "u-boot,env-variable",
+					      NULL);
+	if (!plat_data->env_variable)
+		plat_data->env_variable = "reboot-mode";
+
+	plat_data->count = 0;
+
+	fdt_for_each_property_offset(property, gd->fdt_blob, node) {
+		propvalue = fdt_getprop_by_offset(gd->fdt_blob,
+						  property, &propname, NULL);
+		if (!propvalue) {
+			dev_err(dev, "Could not get the value for property %s\n",
+				propname);
+			return -EINVAL;
+		}
+
+		if (!strncmp(propname, mode_prefix, mode_prefix_len))
+			plat_data->count++;
+	}
+
+	plat_data->modes = devm_kcalloc(dev, plat_data->count,
+					sizeof(struct reboot_mode_mode), 0);
+
+	struct reboot_mode_mode *next = plat_data->modes;
+
+	fdt_for_each_property_offset(property, gd->fdt_blob, node) {
+		propvalue = fdt_getprop_by_offset(gd->fdt_blob,
+						  property, &propname, NULL);
+		if (!propvalue) {
+			dev_err(dev, "Could not get the value for property %s\n",
+				propname);
+			return -EINVAL;
+		}
+
+		if (!strncmp(propname, mode_prefix, mode_prefix_len)) {
+			next->mode_name = &propname[mode_prefix_len];
+			next->mode_id = fdt32_to_cpu(*propvalue);
+
+			next++;
+		}
+	}
+#else
+	if (!plat_data->env_variable)
+		plat_data->env_variable = "reboot-mode";
+
+#endif
+
+	return 0;
+}
+
+UCLASS_DRIVER(reboot_mode) = {
+	.name	= "reboot-mode",
+	.id	= UCLASS_REBOOT_MODE,
+	.pre_probe	= dm_reboot_mode_pre_probe,
+	.per_device_platdata_auto_alloc_size =
+		sizeof(struct reboot_mode_uclass_platdata),
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 0c563d898b..7f5605504c 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -83,6 +83,7 @@ enum uclass_id {
 	UCLASS_PWM,		/* Pulse-width modulator */
 	UCLASS_PWRSEQ,		/* Power sequence device */
 	UCLASS_RAM,		/* RAM controller */
+	UCLASS_REBOOT_MODE,	/* Reboot mode */
 	UCLASS_REGULATOR,	/* Regulator device */
 	UCLASS_REMOTEPROC,	/* Remote Processor device */
 	UCLASS_RESET,		/* Reset controller device */
diff --git a/include/reboot-mode/reboot-mode.h b/include/reboot-mode/reboot-mode.h
new file mode 100644
index 0000000000..86b51f881c
--- /dev/null
+++ b/include/reboot-mode/reboot-mode.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c), Vaisala Oyj
+ */
+
+#ifndef REBOOT_MODE_REBOOT_MODE_H__
+#define REBOOT_MODE_REBOOT_MODE_H__
+
+#include <asm/types.h>
+#include <dm/device.h>
+
+struct reboot_mode_mode {
+	const char *mode_name;
+	u32 mode_id;
+};
+
+struct reboot_mode_uclass_platdata {
+	struct reboot_mode_mode *modes;
+	u8 count;
+	const char *env_variable;
+};
+
+struct reboot_mode_ops {
+	/**
+	 * get() - get the current reboot mode value
+	 *
+	 * Returns the current value from the reboot mode backing store.
+	 *
+	 * @dev:	Device to read from
+	 * @rebootmode:	Address to save the current reboot mode value
+	 */
+	int (*get)(struct udevice *dev, u32 *rebootmode);
+
+	/**
+	 * set() - set a reboot mode value
+	 *
+	 * Sets the value in the reboot mode backing store.
+	 *
+	 * @dev:	Device to read from
+	 * @rebootmode:	New reboot mode value to store
+	 */
+	int (*set)(struct udevice *dev, u32 rebootmode);
+};
+
+/* Access the operations for a reboot mode device */
+#define reboot_mode_get_ops(dev) ((struct reboot_mode_ops *)(dev)->driver->ops)
+
+/**
+ * dm_reboot_mode_update() - Update the reboot mode env variable.
+ *
+ * @dev:	Device to read from
+ * @return 0 if OK, -ve on error
+ */
+int dm_reboot_mode_update(struct udevice *dev);
+
+#endif /* REBOOT_MODE_REBOOT_MODE_H__ */
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 2/3] reboot-mode: read the boot mode from GPIOs status
  2019-11-12  9:13 [U-Boot] [PATCH 0/3] Add reboot mode support Han Nandor
  2019-11-12  9:13 ` [U-Boot] [PATCH 1/3] reboot-mode: add support for reboot mode control Han Nandor
@ 2019-11-12  9:13 ` Han Nandor
  2019-11-12  9:13 ` [U-Boot] [PATCH 3/3] reboot-mode: read the boot mode from RTC memory Han Nandor
  2 siblings, 0 replies; 5+ messages in thread
From: Han Nandor @ 2019-11-12  9:13 UTC (permalink / raw)
  To: u-boot

A use case for controlling the boot mode is when the user wants
to control the device boot by pushing a button without needing to
go in user-space.

Add a new backed for reboot mode where GPIOs are used to control the
reboot-mode. The driver is able to scan a predefined list of GPIOs
and return the magic value. Having the modes associated with
the magic value generated based on the GPIO values, allows the
reboot mode uclass to select the proper mode.

Signed-off-by: Nandor Han <nandor.han@vaisala.com>
---
 .../reboot-mode/reboot-mode-gpio.txt          |  20 +++
 drivers/reboot-mode/Kconfig                   |   9 ++
 drivers/reboot-mode/Makefile                  |   1 +
 drivers/reboot-mode/reboot-mode-gpio.c        | 125 ++++++++++++++++++
 include/reboot-mode/reboot-mode-gpio.h        |  32 +++++
 5 files changed, 187 insertions(+)
 create mode 100644 doc/device-tree-bindings/reboot-mode/reboot-mode-gpio.txt
 create mode 100644 drivers/reboot-mode/reboot-mode-gpio.c
 create mode 100644 include/reboot-mode/reboot-mode-gpio.h

diff --git a/doc/device-tree-bindings/reboot-mode/reboot-mode-gpio.txt b/doc/device-tree-bindings/reboot-mode/reboot-mode-gpio.txt
new file mode 100644
index 0000000000..bb209d2742
--- /dev/null
+++ b/doc/device-tree-bindings/reboot-mode/reboot-mode-gpio.txt
@@ -0,0 +1,20 @@
+GPIO Reboot Mode Configuration
+
+Required Properties:
+- compatible: must be "reboot-mode-gpio".
+- gpios: list of gpios that are used to calculate the reboot-mode magic value.
+	 Every gpio represents a bit in the magic value in the same order
+	 as defined in device tree.
+- modes: list of properties that define the modes and associated unique ids.
+
+Optional Properties:
+- u-boot,env-variable: used to save the reboot mode (default: reboot-mode).
+
+Example:
+	reboot-mode {
+		compatible = "reboot-mode-gpio";
+		gpios = <&gpio1 2 GPIO_ACTIVE_LOW>, <&gpio2 6 GPIO_ACTIVE_HIGH>;
+		u-boot,env-variable = "bootstatus";
+		mode-test = <0x00000001>;
+		mode-download = <0x00000002>;
+	};
diff --git a/drivers/reboot-mode/Kconfig b/drivers/reboot-mode/Kconfig
index 0edc3209d7..ff65e2031a 100644
--- a/drivers/reboot-mode/Kconfig
+++ b/drivers/reboot-mode/Kconfig
@@ -15,4 +15,13 @@ config DM_REBOOT_MODE
 		adjust the boot process based on reboot mode parameter
 		passed to U-Boot.
 
+config DM_REBOOT_MODE_GPIO
+	bool "Use GPIOs as reboot mode backend"
+	depends on DM_REBOOT_MODE
+	default n
+	help
+		Use GPIOs to control the reboot mode. This will allow users to boot
+		a device in a specific mode by using a GPIO that can be controlled
+		outside U-Boot.
+
 endmenu
diff --git a/drivers/reboot-mode/Makefile b/drivers/reboot-mode/Makefile
index 2ab0fddac9..04917be4f4 100644
--- a/drivers/reboot-mode/Makefile
+++ b/drivers/reboot-mode/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_DM_REBOOT_MODE) += reboot-mode-uclass.o
+obj-$(CONFIG_DM_REBOOT_MODE_GPIO) += reboot-mode-gpio.o
diff --git a/drivers/reboot-mode/reboot-mode-gpio.c b/drivers/reboot-mode/reboot-mode-gpio.c
new file mode 100644
index 0000000000..7d8d483cff
--- /dev/null
+++ b/drivers/reboot-mode/reboot-mode-gpio.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c), Vaisala Oyj
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <dm.h>
+#include <errno.h>
+#include <reboot-mode/reboot-mode-gpio.h>
+#include <reboot-mode/reboot-mode.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int reboot_mode_get(struct udevice *dev, u32 *buf)
+{
+	int ret;
+	struct reboot_mode_gpio_platdata *plat_data;
+
+	if (!buf)
+		return -EINVAL;
+
+	plat_data = dev_get_platdata(dev);
+	if (!plat_data)
+		return -EINVAL;
+
+	ret = dm_gpio_get_values_as_int(plat_data->gpio_desc,
+					plat_data->gpio_count);
+	if (ret < 0)
+		return ret;
+
+	*buf = ret;
+
+	return 0;
+}
+
+static int reboot_mode_probe(struct udevice *dev)
+{
+	struct reboot_mode_gpio_platdata *plat_data;
+
+	plat_data = dev_get_platdata(dev);
+	if (!plat_data)
+		return -EINVAL;
+
+	int ret;
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	ret = gpio_get_list_count(dev, "gpios");
+	if (ret < 0)
+		return ret;
+
+	plat_data->gpio_count = ret;
+#endif
+
+	if (plat_data->gpio_count <= 0)
+		return -EINVAL;
+
+	plat_data->gpio_desc = devm_kcalloc(dev, plat_data->gpio_count,
+					    sizeof(struct gpio_desc), 0);
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	ret = gpio_request_list_by_name(dev, "gpios", plat_data->gpio_desc,
+					plat_data->gpio_count, GPIOD_IS_IN);
+	if (ret < 0)
+		return ret;
+#else
+	for (int i = 0; i < plat_data->gpio_count; i++) {
+		struct reboot_mode_gpio_config *gpio =
+			plat_data->gpios_config + i;
+		struct gpio_desc *desc = plat_data->gpio_desc + i;
+
+		ret = uclass_get_device_by_seq(UCLASS_GPIO,
+					       gpio->gpio_dev_offset,
+					       &desc->dev);
+		if (ret < 0)
+			return ret;
+
+		desc->flags = gpio->flags;
+		desc->offset = gpio->gpio_offset;
+
+		ret = dm_gpio_request(desc, "");
+		if (ret < 0)
+			return ret;
+
+		ret = dm_gpio_set_dir(desc);
+		if (ret < 0)
+			return ret;
+	}
+#endif
+	return 0;
+}
+
+static int reboot_mode_remove(struct udevice *dev)
+{
+	struct reboot_mode_gpio_platdata *plat_data;
+
+	plat_data = dev_get_platdata(dev);
+	if (!plat_data)
+		return -EINVAL;
+
+	return gpio_free_list(dev, plat_data->gpio_desc, plat_data->gpio_count);
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id reboot_mode_ids[] = {
+	{ .compatible = "reboot-mode-gpio", 0 },
+	{ }
+};
+#endif
+
+static const struct reboot_mode_ops reboot_mode_gpio_ops = {
+	.get = reboot_mode_get,
+};
+
+U_BOOT_DRIVER(reboot_mode_gpio) = {
+	.name = "reboot-mode-gpio",
+	.id = UCLASS_REBOOT_MODE,
+	.probe = reboot_mode_probe,
+	.remove = reboot_mode_remove,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.of_match = reboot_mode_ids,
+#endif
+	.platdata_auto_alloc_size = sizeof(struct reboot_mode_gpio_platdata),
+	.ops = &reboot_mode_gpio_ops,
+};
diff --git a/include/reboot-mode/reboot-mode-gpio.h b/include/reboot-mode/reboot-mode-gpio.h
new file mode 100644
index 0000000000..16b1185c69
--- /dev/null
+++ b/include/reboot-mode/reboot-mode-gpio.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) Vaisala Oyj.
+ */
+
+#ifndef REBOOT_MODE_REBOOT_MODE_GPIO_H_
+#define REBOOT_MODE_REBOOT_MODE_GPIO_H_
+
+#include <asm/gpio.h>
+
+/*
+ * In case of initializing the driver statically (using U_BOOT_DEVICE macro),
+ * we can use this struct to declare the pins used.
+ */
+
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+struct reboot_mode_gpio_config {
+	int gpio_dev_offset;
+	int gpio_offset;
+	int flags;
+};
+#endif
+
+struct reboot_mode_gpio_platdata {
+	struct gpio_desc *gpio_desc;
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+	struct reboot_mode_gpio_config *gpios_config;
+#endif
+	int gpio_count;
+};
+
+#endif /* REBOOT_MODE_REBOOT_MODE_GPIO_H_ */
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 3/3] reboot-mode: read the boot mode from RTC memory
  2019-11-12  9:13 [U-Boot] [PATCH 0/3] Add reboot mode support Han Nandor
  2019-11-12  9:13 ` [U-Boot] [PATCH 1/3] reboot-mode: add support for reboot mode control Han Nandor
  2019-11-12  9:13 ` [U-Boot] [PATCH 2/3] reboot-mode: read the boot mode from GPIOs status Han Nandor
@ 2019-11-12  9:13 ` Han Nandor
  2 siblings, 0 replies; 5+ messages in thread
From: Han Nandor @ 2019-11-12  9:13 UTC (permalink / raw)
  To: u-boot

RTC devices could provide battery-backed memory that can be used for
storing the reboot mode magic value.

Add a new reboot-mode back-end that uses RTC to store the reboot-mode
magic value. The driver also supports both endianness modes.

Signed-off-by: Nandor Han <nandor.han@vaisala.com>
---
 .../reboot-mode/reboot-mode-rtc.txt           |  22 +++
 drivers/reboot-mode/Kconfig                   |   9 ++
 drivers/reboot-mode/Makefile                  |   1 +
 drivers/reboot-mode/reboot-mode-rtc.c         | 132 ++++++++++++++++++
 include/reboot-mode/reboot-mode-rtc.h         |  16 +++
 5 files changed, 180 insertions(+)
 create mode 100644 doc/device-tree-bindings/reboot-mode/reboot-mode-rtc.txt
 create mode 100644 drivers/reboot-mode/reboot-mode-rtc.c
 create mode 100644 include/reboot-mode/reboot-mode-rtc.h

diff --git a/doc/device-tree-bindings/reboot-mode/reboot-mode-rtc.txt b/doc/device-tree-bindings/reboot-mode/reboot-mode-rtc.txt
new file mode 100644
index 0000000000..23aa12c88c
--- /dev/null
+++ b/doc/device-tree-bindings/reboot-mode/reboot-mode-rtc.txt
@@ -0,0 +1,22 @@
+RTC Reboot Mode Configuration
+
+Required Properties:
+- compatible: must be "reboot-mode-rtc".
+- rtc: reference to the rtc device used.
+- reg: start register and the number of bytes used. Maximum 4 bytes supported.
+- modes: list of properties that define the modes and associated unique ids.
+
+Optional Properties:
+- u-boot,env-variable: used to save the reboot mode (default: reboot-mode).
+- big-endian: if the magic value is stored in big-endian. (default: false).
+
+Example:
+	reboot-mode-rtc {
+		compatible = "reboot-mode-rtc";
+		rtc = <&rtc_0>;
+		reg = <0x14 4>;
+		u-boot,env-variable = "bootstatus";
+		big-endian;
+		modes-test = <0x21969147>;
+		modes-download = <0x51939147>;
+	};
diff --git a/drivers/reboot-mode/Kconfig b/drivers/reboot-mode/Kconfig
index ff65e2031a..ac67bfcef6 100644
--- a/drivers/reboot-mode/Kconfig
+++ b/drivers/reboot-mode/Kconfig
@@ -24,4 +24,13 @@ config DM_REBOOT_MODE_GPIO
 		a device in a specific mode by using a GPIO that can be controlled
 		outside U-Boot.
 
+config DM_REBOOT_MODE_RTC
+	bool "Use RTC as reboot mode backend"
+	depends on DM_REBOOT_MODE
+	default n
+	help
+		Use RTC non volatile memory to control the reboot mode. This will allow users to boot
+		a device in a specific mode by using a register(s) that can be controlled
+		outside U-Boot (e.g. Kernel).
+
 endmenu
diff --git a/drivers/reboot-mode/Makefile b/drivers/reboot-mode/Makefile
index 04917be4f4..2c13780ced 100644
--- a/drivers/reboot-mode/Makefile
+++ b/drivers/reboot-mode/Makefile
@@ -6,3 +6,4 @@
 
 obj-$(CONFIG_DM_REBOOT_MODE) += reboot-mode-uclass.o
 obj-$(CONFIG_DM_REBOOT_MODE_GPIO) += reboot-mode-gpio.o
+obj-$(CONFIG_DM_REBOOT_MODE_RTC) += reboot-mode-rtc.o
diff --git a/drivers/reboot-mode/reboot-mode-rtc.c b/drivers/reboot-mode/reboot-mode-rtc.c
new file mode 100644
index 0000000000..db11acc75a
--- /dev/null
+++ b/drivers/reboot-mode/reboot-mode-rtc.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c), Vaisala Oyj
+ */
+
+#include <common.h>
+#include <rtc.h>
+#include <dm.h>
+#include <errno.h>
+#include <reboot-mode/reboot-mode-rtc.h>
+#include <reboot-mode/reboot-mode.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int reboot_mode_get(struct udevice *dev, u32 *buf)
+{
+	if (!buf)
+		return -EINVAL;
+
+	int ret;
+	u8 *val = (u8 *)buf;
+	struct reboot_mode_rtc_platdata *plat_data;
+
+	plat_data = dev_get_platdata(dev);
+	if (!plat_data)
+		return -EINVAL;
+
+	for (int i = 0; i < plat_data->size; i++) {
+		ret = rtc_read8(plat_data->rtc, plat_data->addr + i);
+		if (ret < 0)
+			return ret;
+
+		val[i] = ret;
+	}
+
+	if (plat_data->is_big_endian)
+		*buf = __be32_to_cpu(*buf);
+	else
+		*buf = __le32_to_cpu(*buf);
+
+	return 0;
+}
+
+static int reboot_mode_set(struct udevice *dev, u32 buf)
+{
+	int ret;
+	u8 *val;
+	struct reboot_mode_rtc_platdata *plat_data;
+
+	plat_data = dev_get_platdata(dev);
+	if (!plat_data)
+		return -EINVAL;
+
+	if (plat_data->is_big_endian)
+		buf = __cpu_to_be32(buf);
+	else
+		buf = __cpu_to_le32(buf);
+
+	val = (u8 *)&buf;
+
+	for (int i = 0; i < plat_data->size; i++) {
+		ret = rtc_write8(plat_data->rtc, (plat_data->addr + i), val[i]);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int reboot_mode_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ofnode_phandle_args phandle_args;
+	struct reboot_mode_rtc_platdata *plat_data;
+
+	plat_data = dev_get_platdata(dev);
+	if (!plat_data)
+		return -EINVAL;
+
+	if (dev_read_phandle_with_args(dev, "rtc", NULL, 0, 0, &phandle_args)) {
+		dev_err(dev, "RTC device not specified\n");
+		return -ENOENT;
+	}
+
+	if (uclass_get_device_by_ofnode(UCLASS_RTC,
+					phandle_args.node, &plat_data->rtc)) {
+		dev_err(dev, "could not get the RTC device\n");
+		return -ENODEV;
+	}
+
+	plat_data->addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob,
+							     dev_of_offset(dev),
+							     "reg",
+							     0,
+							     (fdt_size_t *)&plat_data->size,
+							     false);
+	if (plat_data->addr == FDT_ADDR_T_NONE) {
+		dev_err(dev, "Invalid RTC address\n");
+		return -EINVAL;
+	}
+
+	if (plat_data->size > sizeof(u32)) {
+		dev_err(dev, "Invalid reg size\n");
+		return -EINVAL;
+	}
+
+	plat_data->is_big_endian = ofnode_read_bool(dev->node, "big-endian");
+
+	return 0;
+}
+
+static const struct udevice_id reboot_mode_ids[] = {
+	{ .compatible = "reboot-mode-rtc", 0 },
+	{ }
+};
+#endif
+
+static const struct reboot_mode_ops reboot_mode_rtc_ops = {
+	.get = reboot_mode_get,
+	.set = reboot_mode_set,
+};
+
+U_BOOT_DRIVER(reboot_mode_rtc) = {
+	.name = "reboot-mode-rtc",
+	.id = UCLASS_REBOOT_MODE,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.of_match = reboot_mode_ids,
+	.ofdata_to_platdata = reboot_mode_ofdata_to_platdata,
+#endif
+	.platdata_auto_alloc_size = sizeof(struct reboot_mode_rtc_platdata),
+	.ops = &reboot_mode_rtc_ops,
+};
diff --git a/include/reboot-mode/reboot-mode-rtc.h b/include/reboot-mode/reboot-mode-rtc.h
new file mode 100644
index 0000000000..3613678f63
--- /dev/null
+++ b/include/reboot-mode/reboot-mode-rtc.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c), Vaisala Oyj
+ */
+
+#ifndef REBOOT_MODE_REBOOT_MODE_RTC_H_
+#define REBOOT_MODE_REBOOT_MODE_RTC_H_
+
+struct reboot_mode_rtc_platdata {
+	struct udevice *rtc;
+	bool is_big_endian;
+	int addr;
+	size_t size;
+};
+
+#endif /* REBOOT_MODE_REBOOT_MODE_RTC_H_ */
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 1/3] reboot-mode: add support for reboot mode control
  2019-11-12  9:13 ` [U-Boot] [PATCH 1/3] reboot-mode: add support for reboot mode control Han Nandor
@ 2020-01-30 11:49   ` Nandor Han
  0 siblings, 0 replies; 5+ messages in thread
From: Nandor Han @ 2020-01-30 11:49 UTC (permalink / raw)
  To: u-boot


Hi,
   Any comments about this?

Regards,
     Nandor

On 2019-11-12 11:13, Han Nandor wrote:
> A new driver uclass is created to handle the reboot mode control.
> 
> The new uclass driver is updating an environment variable with the
> configured reboot mode. The mode is extracted from a map provided
> at initialization time. The map contains a list of modes
> and associated ids.
> 
> Signed-off-by: Nandor Han <nandor.han@vaisala.com>
> ---
>   drivers/Kconfig                          |   2 +
>   drivers/Makefile                         |   1 +
>   drivers/reboot-mode/Kconfig              |  18 ++++
>   drivers/reboot-mode/Makefile             |   7 ++
>   drivers/reboot-mode/reboot-mode-uclass.c | 132 +++++++++++++++++++++++
>   include/dm/uclass-id.h                   |   1 +
>   include/reboot-mode/reboot-mode.h        |  56 ++++++++++
>   7 files changed, 217 insertions(+)
>   create mode 100644 drivers/reboot-mode/Kconfig
>   create mode 100644 drivers/reboot-mode/Makefile
>   create mode 100644 drivers/reboot-mode/reboot-mode-uclass.c
>   create mode 100644 include/reboot-mode/reboot-mode.h
> 


<snip>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-01-30 11:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-12  9:13 [U-Boot] [PATCH 0/3] Add reboot mode support Han Nandor
2019-11-12  9:13 ` [U-Boot] [PATCH 1/3] reboot-mode: add support for reboot mode control Han Nandor
2020-01-30 11:49   ` Nandor Han
2019-11-12  9:13 ` [U-Boot] [PATCH 2/3] reboot-mode: read the boot mode from GPIOs status Han Nandor
2019-11-12  9:13 ` [U-Boot] [PATCH 3/3] reboot-mode: read the boot mode from RTC memory Han Nandor

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.