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