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 struct syscon_reboot_priv {
19e3889691SÁlvaro Fernández Rojas 	struct regmap *regmap;
20e3889691SÁlvaro Fernández Rojas 	unsigned int offset;
21e3889691SÁlvaro Fernández Rojas 	unsigned int mask;
22e3889691SÁlvaro Fernández Rojas };
23e3889691SÁlvaro Fernández Rojas 
24e3889691SÁlvaro Fernández Rojas static int syscon_reboot_request(struct udevice *dev, enum sysreset_t type)
25e3889691SÁlvaro Fernández Rojas {
26e3889691SÁlvaro Fernández Rojas 	struct syscon_reboot_priv *priv = dev_get_priv(dev);
27e3889691SÁlvaro Fernández Rojas 
28e3889691SÁlvaro Fernández Rojas 	regmap_write(priv->regmap, priv->offset, priv->mask);
29e3889691SÁlvaro Fernández Rojas 
30e3889691SÁlvaro Fernández Rojas 	return -EINPROGRESS;
31e3889691SÁlvaro Fernández Rojas }
32e3889691SÁlvaro Fernández Rojas 
33e3889691SÁlvaro Fernández Rojas static struct sysreset_ops syscon_reboot_ops = {
34e3889691SÁlvaro Fernández Rojas 	.request = syscon_reboot_request,
35e3889691SÁlvaro Fernández Rojas };
36e3889691SÁlvaro Fernández Rojas 
37e3889691SÁlvaro Fernández Rojas int syscon_reboot_probe(struct udevice *dev)
38e3889691SÁlvaro Fernández Rojas {
39e3889691SÁlvaro Fernández Rojas 	struct udevice *syscon;
40e3889691SÁlvaro Fernández Rojas 	struct syscon_reboot_priv *priv = dev_get_priv(dev);
41e3889691SÁlvaro Fernández Rojas 	int err;
42e3889691SÁlvaro Fernández Rojas 
43e3889691SÁlvaro Fernández Rojas 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
44e3889691SÁlvaro Fernández Rojas 					   "regmap", &syscon);
45e3889691SÁlvaro Fernández Rojas 	if (err) {
469b643e31SMasahiro Yamada 		pr_err("unable to find syscon device\n");
47e3889691SÁlvaro Fernández Rojas 		return err;
48e3889691SÁlvaro Fernández Rojas 	}
49e3889691SÁlvaro Fernández Rojas 
50e3889691SÁlvaro Fernández Rojas 	priv->regmap = syscon_get_regmap(syscon);
51e3889691SÁlvaro Fernández Rojas 	if (!priv->regmap) {
529b643e31SMasahiro Yamada 		pr_err("unable to find regmap\n");
53e3889691SÁlvaro Fernández Rojas 		return -ENODEV;
54e3889691SÁlvaro Fernández Rojas 	}
55e3889691SÁlvaro Fernández Rojas 
56*06069066SÁlvaro Fernández Rojas 	priv->offset = dev_read_u32_default(dev, "offset", 0);
57*06069066SÁlvaro Fernández Rojas 	priv->mask = dev_read_u32_default(dev, "mask", 0);
58e3889691SÁlvaro Fernández Rojas 
59e3889691SÁlvaro Fernández Rojas 	return 0;
60e3889691SÁlvaro Fernández Rojas }
61e3889691SÁlvaro Fernández Rojas 
62e3889691SÁlvaro Fernández Rojas static const struct udevice_id syscon_reboot_ids[] = {
63e3889691SÁlvaro Fernández Rojas 	{ .compatible = "syscon-reboot" },
64e3889691SÁlvaro Fernández Rojas 	{ /* sentinel */ }
65e3889691SÁlvaro Fernández Rojas };
66e3889691SÁlvaro Fernández Rojas 
67e3889691SÁlvaro Fernández Rojas U_BOOT_DRIVER(syscon_reboot) = {
68e3889691SÁlvaro Fernández Rojas 	.name = "syscon_reboot",
69e3889691SÁlvaro Fernández Rojas 	.id = UCLASS_SYSRESET,
70e3889691SÁlvaro Fernández Rojas 	.of_match = syscon_reboot_ids,
71e3889691SÁlvaro Fernández Rojas 	.probe = syscon_reboot_probe,
72e3889691SÁlvaro Fernández Rojas 	.priv_auto_alloc_size = sizeof(struct syscon_reboot_priv),
73e3889691SÁlvaro Fernández Rojas 	.ops = &syscon_reboot_ops,
74e3889691SÁlvaro Fernández Rojas };
75