"Das U-Boot" Source Tree
at master 162 lines 3.0 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2015 Google, Inc 4 * Written by Simon Glass <sjg@chromium.org> 5 */ 6 7#define LOG_CATEGORY UCLASS_SYSRESET 8 9#include <command.h> 10#include <cpu_func.h> 11#include <dm.h> 12#include <errno.h> 13#include <hang.h> 14#include <log.h> 15#include <regmap.h> 16#include <spl.h> 17#include <sysreset.h> 18#include <dm/device-internal.h> 19#include <dm/lists.h> 20#include <dm/root.h> 21#include <linux/delay.h> 22#include <linux/err.h> 23#include <asm/global_data.h> 24 25int sysreset_request(struct udevice *dev, enum sysreset_t type) 26{ 27 struct sysreset_ops *ops = sysreset_get_ops(dev); 28 29 if (!ops->request) 30 return -ENOSYS; 31 32 return ops->request(dev, type); 33} 34 35int sysreset_get_status(struct udevice *dev, char *buf, int size) 36{ 37 struct sysreset_ops *ops = sysreset_get_ops(dev); 38 39 if (!ops->get_status) 40 return -ENOSYS; 41 42 return ops->get_status(dev, buf, size); 43} 44 45int sysreset_get_last(struct udevice *dev) 46{ 47 struct sysreset_ops *ops = sysreset_get_ops(dev); 48 49 if (!ops->get_last) 50 return -ENOSYS; 51 52 return ops->get_last(dev); 53} 54 55int sysreset_walk(enum sysreset_t type) 56{ 57 struct udevice *dev; 58 int ret = -ENOSYS; 59 60 while (ret != -EINPROGRESS && type < SYSRESET_COUNT) { 61 for (uclass_first_device(UCLASS_SYSRESET, &dev); 62 dev; 63 uclass_next_device(&dev)) { 64 ret = sysreset_request(dev, type); 65 if (ret == -EINPROGRESS) 66 break; 67 } 68 type++; 69 } 70 71 return ret; 72} 73 74int sysreset_get_last_walk(void) 75{ 76 struct udevice *dev; 77 int value = -ENOENT; 78 79 for (uclass_first_device(UCLASS_SYSRESET, &dev); 80 dev; 81 uclass_next_device(&dev)) { 82 int ret; 83 84 ret = sysreset_get_last(dev); 85 if (ret >= 0) { 86 value = ret; 87 break; 88 } 89 } 90 91 return value; 92} 93 94void sysreset_walk_halt(enum sysreset_t type) 95{ 96 int ret; 97 98 ret = sysreset_walk(type); 99 100 /* Wait for the reset to take effect */ 101 if (ret == -EINPROGRESS) 102 mdelay(100); 103 104 /* Still no reset? Give up */ 105 if (xpl_phase() <= PHASE_SPL) 106 log_err("no sysreset\n"); 107 else 108 log_err("System reset not supported on this platform\n"); 109 hang(); 110} 111 112/** 113 * reset_cpu() - calls sysreset_walk(SYSRESET_WARM) 114 */ 115void reset_cpu(void) 116{ 117 sysreset_walk_halt(SYSRESET_WARM); 118} 119 120#if IS_ENABLED(CONFIG_SYSRESET_CMD_RESET) 121int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 122{ 123 enum sysreset_t reset_type = SYSRESET_COLD; 124 125 if (argc > 2) 126 return CMD_RET_USAGE; 127 128 if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'w') { 129 reset_type = SYSRESET_WARM; 130 } 131 132 printf("resetting ...\n"); 133 mdelay(100); 134 135 sysreset_walk_halt(reset_type); 136 137 return 0; 138} 139#endif 140 141#if IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF) 142int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 143{ 144 int ret; 145 146 puts("poweroff ...\n"); 147 mdelay(100); 148 149 ret = sysreset_walk(SYSRESET_POWER_OFF); 150 151 if (ret == -EINPROGRESS) 152 mdelay(1000); 153 154 /*NOTREACHED when power off*/ 155 return CMD_RET_FAILURE; 156} 157#endif 158 159UCLASS_DRIVER(sysreset) = { 160 .id = UCLASS_SYSRESET, 161 .name = "sysreset", 162};