xref: /rk3399_rockchip-uboot/drivers/sysreset/sysreset-uclass.c (revision b25732c22beccb5a2ce3ec4174ea084ba0e176ab)
1*b25732c2SMax Filippov /*
2*b25732c2SMax Filippov  * Copyright (C) 2015 Google, Inc
3*b25732c2SMax Filippov  * Written by Simon Glass <sjg@chromium.org>
4*b25732c2SMax Filippov  *
5*b25732c2SMax Filippov  * SPDX-License-Identifier:	GPL-2.0+
6*b25732c2SMax Filippov  */
7*b25732c2SMax Filippov 
8*b25732c2SMax Filippov #include <common.h>
9*b25732c2SMax Filippov #include <sysreset.h>
10*b25732c2SMax Filippov #include <dm.h>
11*b25732c2SMax Filippov #include <errno.h>
12*b25732c2SMax Filippov #include <regmap.h>
13*b25732c2SMax Filippov #include <dm/device-internal.h>
14*b25732c2SMax Filippov #include <dm/lists.h>
15*b25732c2SMax Filippov #include <dm/root.h>
16*b25732c2SMax Filippov #include <linux/err.h>
17*b25732c2SMax Filippov 
18*b25732c2SMax Filippov int sysreset_request(struct udevice *dev, enum sysreset_t type)
19*b25732c2SMax Filippov {
20*b25732c2SMax Filippov 	struct sysreset_ops *ops = sysreset_get_ops(dev);
21*b25732c2SMax Filippov 
22*b25732c2SMax Filippov 	if (!ops->request)
23*b25732c2SMax Filippov 		return -ENOSYS;
24*b25732c2SMax Filippov 
25*b25732c2SMax Filippov 	return ops->request(dev, type);
26*b25732c2SMax Filippov }
27*b25732c2SMax Filippov 
28*b25732c2SMax Filippov int sysreset_walk(enum sysreset_t type)
29*b25732c2SMax Filippov {
30*b25732c2SMax Filippov 	struct udevice *dev;
31*b25732c2SMax Filippov 	int ret = -ENOSYS;
32*b25732c2SMax Filippov 
33*b25732c2SMax Filippov 	while (ret != -EINPROGRESS && type < SYSRESET_COUNT) {
34*b25732c2SMax Filippov 		for (uclass_first_device(UCLASS_SYSRESET, &dev);
35*b25732c2SMax Filippov 		     dev;
36*b25732c2SMax Filippov 		     uclass_next_device(&dev)) {
37*b25732c2SMax Filippov 			ret = sysreset_request(dev, type);
38*b25732c2SMax Filippov 			if (ret == -EINPROGRESS)
39*b25732c2SMax Filippov 				break;
40*b25732c2SMax Filippov 		}
41*b25732c2SMax Filippov 		type++;
42*b25732c2SMax Filippov 	}
43*b25732c2SMax Filippov 
44*b25732c2SMax Filippov 	return ret;
45*b25732c2SMax Filippov }
46*b25732c2SMax Filippov 
47*b25732c2SMax Filippov void sysreset_walk_halt(enum sysreset_t type)
48*b25732c2SMax Filippov {
49*b25732c2SMax Filippov 	int ret;
50*b25732c2SMax Filippov 
51*b25732c2SMax Filippov 	ret = sysreset_walk(type);
52*b25732c2SMax Filippov 
53*b25732c2SMax Filippov 	/* Wait for the reset to take effect */
54*b25732c2SMax Filippov 	if (ret == -EINPROGRESS)
55*b25732c2SMax Filippov 		mdelay(100);
56*b25732c2SMax Filippov 
57*b25732c2SMax Filippov 	/* Still no reset? Give up */
58*b25732c2SMax Filippov 	debug("System reset not supported on this platform\n");
59*b25732c2SMax Filippov 	hang();
60*b25732c2SMax Filippov }
61*b25732c2SMax Filippov 
62*b25732c2SMax Filippov /**
63*b25732c2SMax Filippov  * reset_cpu() - calls sysreset_walk(SYSRESET_WARM)
64*b25732c2SMax Filippov  */
65*b25732c2SMax Filippov void reset_cpu(ulong addr)
66*b25732c2SMax Filippov {
67*b25732c2SMax Filippov 	sysreset_walk_halt(SYSRESET_WARM);
68*b25732c2SMax Filippov }
69*b25732c2SMax Filippov 
70*b25732c2SMax Filippov 
71*b25732c2SMax Filippov int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72*b25732c2SMax Filippov {
73*b25732c2SMax Filippov 	sysreset_walk_halt(SYSRESET_WARM);
74*b25732c2SMax Filippov 
75*b25732c2SMax Filippov 	return 0;
76*b25732c2SMax Filippov }
77*b25732c2SMax Filippov 
78*b25732c2SMax Filippov UCLASS_DRIVER(sysreset) = {
79*b25732c2SMax Filippov 	.id		= UCLASS_SYSRESET,
80*b25732c2SMax Filippov 	.name		= "sysreset",
81*b25732c2SMax Filippov };
82