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
Block a user