sysreset: Add a way to find the last reset
We have a method to return the last reset as a string for humans, but not a method that allows it to be used programmatically. Add a new method that returns the last reset as an enum. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		
							parent
							
								
									eb517315a6
								
							
						
					
					
						commit
						751fed426f
					
				|  | @ -36,6 +36,16 @@ int sysreset_get_status(struct udevice *dev, char *buf, int size) | ||||||
| 	return ops->get_status(dev, buf, size); | 	return ops->get_status(dev, buf, size); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int sysreset_get_last(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct sysreset_ops *ops = sysreset_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->get_last) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 
 | ||||||
|  | 	return ops->get_last(dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int sysreset_walk(enum sysreset_t type) | int sysreset_walk(enum sysreset_t type) | ||||||
| { | { | ||||||
| 	struct udevice *dev; | 	struct udevice *dev; | ||||||
|  | @ -55,6 +65,26 @@ int sysreset_walk(enum sysreset_t type) | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int sysreset_get_last_walk(void) | ||||||
|  | { | ||||||
|  | 	struct udevice *dev; | ||||||
|  | 	int value = -ENOENT; | ||||||
|  | 
 | ||||||
|  | 	for (uclass_first_device(UCLASS_SYSRESET, &dev); | ||||||
|  | 	     dev; | ||||||
|  | 	     uclass_next_device(&dev)) { | ||||||
|  | 		int ret; | ||||||
|  | 
 | ||||||
|  | 		ret = sysreset_get_last(dev); | ||||||
|  | 		if (ret >= 0) { | ||||||
|  | 			value = ret; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void sysreset_walk_halt(enum sysreset_t type) | void sysreset_walk_halt(enum sysreset_t type) | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
|  |  | ||||||
|  | @ -36,6 +36,11 @@ int sandbox_warm_sysreset_get_status(struct udevice *dev, char *buf, int size) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int sandbox_warm_sysreset_get_last(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	return SYSRESET_WARM; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type) | static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type) | ||||||
| { | { | ||||||
| 	struct sandbox_state *state = state_get_current(); | 	struct sandbox_state *state = state_get_current(); | ||||||
|  | @ -58,6 +63,9 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type) | ||||||
| 			return -EACCES; | 			return -EACCES; | ||||||
| 		sandbox_exit(); | 		sandbox_exit(); | ||||||
| 		break; | 		break; | ||||||
|  | 	case SYSRESET_POWER_OFF: | ||||||
|  | 		if (!state->sysreset_allowed[type]) | ||||||
|  | 			return -EACCES; | ||||||
| 	default: | 	default: | ||||||
| 		return -ENOSYS; | 		return -ENOSYS; | ||||||
| 	} | 	} | ||||||
|  | @ -74,9 +82,15 @@ int sandbox_sysreset_get_status(struct udevice *dev, char *buf, int size) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int sandbox_sysreset_get_last(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	return SYSRESET_COLD; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static struct sysreset_ops sandbox_sysreset_ops = { | static struct sysreset_ops sandbox_sysreset_ops = { | ||||||
| 	.request	= sandbox_sysreset_request, | 	.request	= sandbox_sysreset_request, | ||||||
| 	.get_status	= sandbox_sysreset_get_status, | 	.get_status	= sandbox_sysreset_get_status, | ||||||
|  | 	.get_last	= sandbox_sysreset_get_last, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const struct udevice_id sandbox_sysreset_ids[] = { | static const struct udevice_id sandbox_sysreset_ids[] = { | ||||||
|  | @ -94,6 +108,7 @@ U_BOOT_DRIVER(sysreset_sandbox) = { | ||||||
| static struct sysreset_ops sandbox_warm_sysreset_ops = { | static struct sysreset_ops sandbox_warm_sysreset_ops = { | ||||||
| 	.request	= sandbox_warm_sysreset_request, | 	.request	= sandbox_warm_sysreset_request, | ||||||
| 	.get_status	= sandbox_warm_sysreset_get_status, | 	.get_status	= sandbox_warm_sysreset_get_status, | ||||||
|  | 	.get_last	= sandbox_warm_sysreset_get_last, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const struct udevice_id sandbox_warm_sysreset_ids[] = { | static const struct udevice_id sandbox_warm_sysreset_ids[] = { | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ enum sysreset_t { | ||||||
| 	SYSRESET_WARM,	/* Reset CPU, keep GPIOs active */ | 	SYSRESET_WARM,	/* Reset CPU, keep GPIOs active */ | ||||||
| 	SYSRESET_COLD,	/* Reset CPU and GPIOs */ | 	SYSRESET_COLD,	/* Reset CPU and GPIOs */ | ||||||
| 	SYSRESET_POWER,	/* Reset PMIC (remove and restore power) */ | 	SYSRESET_POWER,	/* Reset PMIC (remove and restore power) */ | ||||||
|  | 	SYSRESET_POWER_OFF,	/* Turn off power */ | ||||||
| 
 | 
 | ||||||
| 	SYSRESET_COUNT, | 	SYSRESET_COUNT, | ||||||
| }; | }; | ||||||
|  | @ -37,6 +38,14 @@ struct sysreset_ops { | ||||||
| 	 * @return 0 if OK, -ve on error | 	 * @return 0 if OK, -ve on error | ||||||
| 	 */ | 	 */ | ||||||
| 	int (*get_status)(struct udevice *dev, char *buf, int size); | 	int (*get_status)(struct udevice *dev, char *buf, int size); | ||||||
|  | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * get_last() - get information on the last reset | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	Device to check | ||||||
|  | 	 * @return last reset state (enum sysreset_t) or -ve error | ||||||
|  | 	 */ | ||||||
|  | 	int (*get_last)(struct udevice *dev); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define sysreset_get_ops(dev)        ((struct sysreset_ops *)(dev)->driver->ops) | #define sysreset_get_ops(dev)        ((struct sysreset_ops *)(dev)->driver->ops) | ||||||
|  | @ -59,6 +68,14 @@ int sysreset_request(struct udevice *dev, enum sysreset_t type); | ||||||
|  */ |  */ | ||||||
| int sysreset_get_status(struct udevice *dev, char *buf, int size); | int sysreset_get_status(struct udevice *dev, char *buf, int size); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * sysreset_get_last() - get information on the last reset | ||||||
|  |  * | ||||||
|  |  * @dev:	Device to check | ||||||
|  |  * @return last reset state (enum sysreset_t) or -ve error | ||||||
|  |  */ | ||||||
|  | int sysreset_get_last(struct udevice *dev); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * sysreset_walk() - cause a system reset |  * sysreset_walk() - cause a system reset | ||||||
|  * |  * | ||||||
|  | @ -73,6 +90,19 @@ int sysreset_get_status(struct udevice *dev, char *buf, int size); | ||||||
|  */ |  */ | ||||||
| int sysreset_walk(enum sysreset_t type); | int sysreset_walk(enum sysreset_t type); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * sysreset_get_last_walk() - get information on the last reset | ||||||
|  |  * | ||||||
|  |  * This works through the available sysreset devices until it finds one that can | ||||||
|  |  * perform a reset. If the provided sysreset type is not available, the next one | ||||||
|  |  * will be tried. | ||||||
|  |  * | ||||||
|  |  * If no device prives the information, this function returns -ENOENT | ||||||
|  |  * | ||||||
|  |  * @return last reset state (enum sysreset_t) or -ve error | ||||||
|  |  */ | ||||||
|  | int sysreset_get_last_walk(void); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * sysreset_walk_halt() - try to reset, otherwise halt |  * sysreset_walk_halt() - try to reset, otherwise halt | ||||||
|  * |  * | ||||||
|  |  | ||||||
|  | @ -71,6 +71,7 @@ static int dm_test_sysreset_walk(struct unit_test_state *uts) | ||||||
| 
 | 
 | ||||||
| 	/* If we generate a power sysreset, we will exit sandbox! */ | 	/* If we generate a power sysreset, we will exit sandbox! */ | ||||||
| 	state->sysreset_allowed[SYSRESET_POWER] = false; | 	state->sysreset_allowed[SYSRESET_POWER] = false; | ||||||
|  | 	state->sysreset_allowed[SYSRESET_POWER_OFF] = false; | ||||||
| 	ut_asserteq(-EACCES, sysreset_walk(SYSRESET_WARM)); | 	ut_asserteq(-EACCES, sysreset_walk(SYSRESET_WARM)); | ||||||
| 	ut_asserteq(-EACCES, sysreset_walk(SYSRESET_COLD)); | 	ut_asserteq(-EACCES, sysreset_walk(SYSRESET_COLD)); | ||||||
| 	ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER)); | 	ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER)); | ||||||
|  | @ -90,3 +91,22 @@ static int dm_test_sysreset_walk(struct unit_test_state *uts) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| DM_TEST(dm_test_sysreset_walk, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); | DM_TEST(dm_test_sysreset_walk, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); | ||||||
|  | 
 | ||||||
|  | static int dm_test_sysreset_get_last(struct unit_test_state *uts) | ||||||
|  | { | ||||||
|  | 	struct udevice *dev; | ||||||
|  | 
 | ||||||
|  | 	/* Device 1 is the warm sysreset device */ | ||||||
|  | 	ut_assertok(uclass_get_device(UCLASS_SYSRESET, 1, &dev)); | ||||||
|  | 	ut_asserteq(SYSRESET_WARM, sysreset_get_last(dev)); | ||||||
|  | 
 | ||||||
|  | 	/* Device 2 is the cold sysreset device */ | ||||||
|  | 	ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev)); | ||||||
|  | 	ut_asserteq(SYSRESET_COLD, sysreset_get_last(dev)); | ||||||
|  | 
 | ||||||
|  | 	/* This is device 0, the non-DT one */ | ||||||
|  | 	ut_asserteq(SYSRESET_COLD, sysreset_get_last_walk()); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | DM_TEST(dm_test_sysreset_get_last, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue