1e3889691SÁlvaro Fernández Rojas /*
2e3889691SÁlvaro Fernández Rojas * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
3e3889691SÁlvaro Fernández Rojas *
4e3889691SÁlvaro Fernández Rojas * Derived from linux/drivers/power/reset/syscon-reboot.c:
5e3889691SÁlvaro Fernández Rojas * Copyright (C) 2013, Applied Micro Circuits Corporation
6e3889691SÁlvaro Fernández Rojas * Author: Feng Kan <fkan@apm.com>
7e3889691SÁlvaro Fernández Rojas *
8e3889691SÁlvaro Fernández Rojas * SPDX-License-Identifier: GPL-2.0+
9e3889691SÁlvaro Fernández Rojas */
10e3889691SÁlvaro Fernández Rojas
11e3889691SÁlvaro Fernández Rojas #include <common.h>
12e3889691SÁlvaro Fernández Rojas #include <dm.h>
13e3889691SÁlvaro Fernández Rojas #include <errno.h>
14e3889691SÁlvaro Fernández Rojas #include <regmap.h>
15e3889691SÁlvaro Fernández Rojas #include <sysreset.h>
16e3889691SÁlvaro Fernández Rojas #include <syscon.h>
17e3889691SÁlvaro Fernández Rojas
18e3889691SÁlvaro Fernández Rojas DECLARE_GLOBAL_DATA_PTR;
19e3889691SÁlvaro Fernández Rojas
20e3889691SÁlvaro Fernández Rojas struct syscon_reboot_priv {
21e3889691SÁlvaro Fernández Rojas struct regmap *regmap;
22e3889691SÁlvaro Fernández Rojas unsigned int offset;
23e3889691SÁlvaro Fernández Rojas unsigned int mask;
24e3889691SÁlvaro Fernández Rojas };
25e3889691SÁlvaro Fernández Rojas
syscon_reboot_request(struct udevice * dev,enum sysreset_t type)26e3889691SÁlvaro Fernández Rojas static int syscon_reboot_request(struct udevice *dev, enum sysreset_t type)
27e3889691SÁlvaro Fernández Rojas {
28e3889691SÁlvaro Fernández Rojas struct syscon_reboot_priv *priv = dev_get_priv(dev);
29e3889691SÁlvaro Fernández Rojas
30e3889691SÁlvaro Fernández Rojas regmap_write(priv->regmap, priv->offset, priv->mask);
31e3889691SÁlvaro Fernández Rojas
32e3889691SÁlvaro Fernández Rojas return -EINPROGRESS;
33e3889691SÁlvaro Fernández Rojas }
34e3889691SÁlvaro Fernández Rojas
35e3889691SÁlvaro Fernández Rojas static struct sysreset_ops syscon_reboot_ops = {
36e3889691SÁlvaro Fernández Rojas .request = syscon_reboot_request,
37e3889691SÁlvaro Fernández Rojas };
38e3889691SÁlvaro Fernández Rojas
syscon_reboot_probe(struct udevice * dev)39e3889691SÁlvaro Fernández Rojas int syscon_reboot_probe(struct udevice *dev)
40e3889691SÁlvaro Fernández Rojas {
41e3889691SÁlvaro Fernández Rojas struct udevice *syscon;
42e3889691SÁlvaro Fernández Rojas struct syscon_reboot_priv *priv = dev_get_priv(dev);
43e3889691SÁlvaro Fernández Rojas int err;
44e3889691SÁlvaro Fernández Rojas
45e3889691SÁlvaro Fernández Rojas err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
46e3889691SÁlvaro Fernández Rojas "regmap", &syscon);
47e3889691SÁlvaro Fernández Rojas if (err) {
48*90aa625cSMasahiro Yamada pr_err("unable to find syscon device\n");
49e3889691SÁlvaro Fernández Rojas return err;
50e3889691SÁlvaro Fernández Rojas }
51e3889691SÁlvaro Fernández Rojas
52e3889691SÁlvaro Fernández Rojas priv->regmap = syscon_get_regmap(syscon);
53e3889691SÁlvaro Fernández Rojas if (!priv->regmap) {
54*90aa625cSMasahiro Yamada pr_err("unable to find regmap\n");
55e3889691SÁlvaro Fernández Rojas return -ENODEV;
56e3889691SÁlvaro Fernández Rojas }
57e3889691SÁlvaro Fernández Rojas
58e3889691SÁlvaro Fernández Rojas priv->offset = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
59e3889691SÁlvaro Fernández Rojas "offset", 0);
60e3889691SÁlvaro Fernández Rojas priv->mask = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
61e3889691SÁlvaro Fernández Rojas "mask", 0);
62e3889691SÁlvaro Fernández Rojas
63e3889691SÁlvaro Fernández Rojas return 0;
64e3889691SÁlvaro Fernández Rojas }
65e3889691SÁlvaro Fernández Rojas
66e3889691SÁlvaro Fernández Rojas static const struct udevice_id syscon_reboot_ids[] = {
67e3889691SÁlvaro Fernández Rojas { .compatible = "syscon-reboot" },
68e3889691SÁlvaro Fernández Rojas { /* sentinel */ }
69e3889691SÁlvaro Fernández Rojas };
70e3889691SÁlvaro Fernández Rojas
71e3889691SÁlvaro Fernández Rojas U_BOOT_DRIVER(syscon_reboot) = {
72e3889691SÁlvaro Fernández Rojas .name = "syscon_reboot",
73e3889691SÁlvaro Fernández Rojas .id = UCLASS_SYSRESET,
74e3889691SÁlvaro Fernández Rojas .of_match = syscon_reboot_ids,
75e3889691SÁlvaro Fernández Rojas .probe = syscon_reboot_probe,
76e3889691SÁlvaro Fernández Rojas .priv_auto_alloc_size = sizeof(struct syscon_reboot_priv),
77e3889691SÁlvaro Fernández Rojas .ops = &syscon_reboot_ops,
78e3889691SÁlvaro Fernández Rojas };
79