summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2020-09-28 16:45:12 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2020-09-29 10:25:02 +0200
commitc142b3ff3df1fe847407cd969f9ebb627c54c85a (patch)
treed0182e5706bc9ec80081704c6830aad7631706ec /drivers
parent41d7d2fdc86b990843cb7c74eecda88baee0cac7 (diff)
downloadbarebox-c142b3ff3df1fe847407cd969f9ebb627c54c85a.tar.gz
barebox-c142b3ff3df1fe847407cd969f9ebb627c54c85a.tar.xz
power: reset: reboot-mode: support multi-word magic
The upstream binding and driver implementation only supports reboot modes of 32-bit length. This is insufficient for cases where multiple registers need to be written for the reboot mode to become active. The i.MX6 is an example for this, the BootROM expects a second 32-bit register to indicate whether the reboot mode in the first is valid. In preparation for adding support for this to the syscon-reboot-mode driver. Migrate the reboot-mode core to support this. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/power/reset/reboot-mode.c37
-rw-r--r--drivers/power/reset/syscon-reboot-mode.c11
2 files changed, 29 insertions, 19 deletions
diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c
index bf51c00aee..313ba6dc3a 100644
--- a/drivers/power/reset/reboot-mode.c
+++ b/drivers/power/reset/reboot-mode.c
@@ -20,11 +20,9 @@ static struct reboot_mode_driver *__boot_mode;
static int reboot_mode_param_set(struct param_d *p, void *priv)
{
struct reboot_mode_driver *reboot = priv;
- u32 magic;
+ size_t i = reboot->reboot_mode_next * reboot->nelems;
- magic = reboot->magics[reboot->reboot_mode_next];
-
- return reboot->write(reboot, magic);
+ return reboot->write(reboot, &reboot->magics[i]);
}
static int reboot_mode_add_param(struct device_d *dev,
@@ -108,9 +106,13 @@ late_initcall(reboot_mode_add_globalvar);
static void reboot_mode_print(struct reboot_mode_driver *reboot,
- const char *prefix, u32 magic)
+ const char *prefix, const u32 *arr)
{
- dev_dbg(reboot->dev, "%s: %08x\n", prefix, magic);
+ size_t i;
+ dev_dbg(reboot->dev, "%s: ", prefix);
+ for (i = 0; i < reboot->nelems; i++)
+ __pr_printk(7, "%08x ", arr[i]);
+ __pr_printk(7, "\n");
}
/**
@@ -120,7 +122,8 @@ static void reboot_mode_print(struct reboot_mode_driver *reboot,
*
* Returns: 0 on success or a negative error code on failure.
*/
-int reboot_mode_register(struct reboot_mode_driver *reboot, u32 reboot_mode)
+int reboot_mode_register(struct reboot_mode_driver *reboot,
+ const u32 *reboot_mode, size_t nelems)
{
struct property *prop;
struct device_node *np = reboot->dev->device_node;
@@ -142,7 +145,8 @@ int reboot_mode_register(struct reboot_mode_driver *reboot, u32 reboot_mode)
}
reboot->nmodes = nmodes;
- reboot->magics = xzalloc(nmodes * sizeof(u32));
+ reboot->nelems = nelems;
+ reboot->magics = xzalloc(nmodes * nelems * sizeof(u32));
reboot->modes = xzalloc(nmodes * sizeof(const char *));
reboot_mode_print(reboot, "registering magic", reboot_mode);
@@ -151,13 +155,13 @@ int reboot_mode_register(struct reboot_mode_driver *reboot, u32 reboot_mode)
const char **mode;
u32 *magic;
- magic = &reboot->magics[i];
+ magic = &reboot->magics[i * nelems];
mode = &reboot->modes[i];
if (strncmp(prop->name, PREFIX, len))
continue;
- if (of_property_read_u32(np, prop->name, magic)) {
+ if (of_property_read_u32_array(np, prop->name, magic, nelems)) {
dev_err(reboot->dev, "reboot mode %s without magic number\n",
*mode);
continue;
@@ -171,22 +175,23 @@ int reboot_mode_register(struct reboot_mode_driver *reboot, u32 reboot_mode)
goto error;
}
- reboot_mode_print(reboot, *mode, *magic);
+ reboot_mode_print(reboot, *mode, magic);
i++;
}
for (i = 0; i < reboot->nmodes; i++) {
- if (reboot->magics[i] == reboot_mode) {
- reboot->reboot_mode_prev = i;
- break;
- }
+ if (memcmp(&reboot->magics[i * nelems], reboot_mode, nelems * sizeof(u32)))
+ continue;
+
+ reboot->reboot_mode_prev = i;
+ break;
}
reboot_mode_add_param(reboot->dev, "", reboot);
/* clear mode for next reboot */
- reboot->write(reboot, 0);
+ reboot->write(reboot, &(u32) { 0 });
if (!reboot->priority)
reboot->priority = REBOOT_MODE_DEFAULT_PRIORITY;
diff --git a/drivers/power/reset/syscon-reboot-mode.c b/drivers/power/reset/syscon-reboot-mode.c
index 5e4aed943d..bd4f1a3d04 100644
--- a/drivers/power/reset/syscon-reboot-mode.c
+++ b/drivers/power/reset/syscon-reboot-mode.c
@@ -19,7 +19,7 @@ struct syscon_reboot_mode {
};
static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot,
- unsigned int magic)
+ const u32 *magic)
{
struct syscon_reboot_mode *syscon_rbm;
int ret;
@@ -27,7 +27,7 @@ static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot,
syscon_rbm = container_of(reboot, struct syscon_reboot_mode, reboot);
ret = regmap_update_bits(syscon_rbm->map, syscon_rbm->offset,
- syscon_rbm->mask, magic);
+ syscon_rbm->mask, *magic);
if (ret < 0)
dev_err(reboot->dev, "update reboot mode bits failed\n");
@@ -39,8 +39,13 @@ static int syscon_reboot_mode_probe(struct device_d *dev)
int ret;
struct syscon_reboot_mode *syscon_rbm;
struct device_node *np = dev->device_node;
+ size_t nelems;
u32 magic;
+ nelems = of_property_count_elems_of_size(np, "offset", sizeof(__be32));
+ if (nelems != 1)
+ return -EINVAL;
+
syscon_rbm = xzalloc(sizeof(*syscon_rbm));
syscon_rbm->reboot.dev = dev;
@@ -65,7 +70,7 @@ static int syscon_reboot_mode_probe(struct device_d *dev)
magic &= syscon_rbm->mask;
- ret = reboot_mode_register(&syscon_rbm->reboot, magic);
+ ret = reboot_mode_register(&syscon_rbm->reboot, &magic, 1);
if (ret)
dev_err(dev, "can't register reboot mode\n");