greybus: control: add bundle suspend and resume preparations

Add the AP implementation for the Greybus Control Bundle Suspend
Operation. This Operation is used to request a Bundle to enter the
BUNDLE_SUSPENDED state, all Connections associated with this Bundle must
be closed before issuing this operation.

Add the AP implementation for the Greybus Control Bundle Resume
Operation. This operation request a specific Bundle to transition from
the BUNDLE_SUSPENDED state to the BUNDLE_ACTIVE state.

Signed-off-by: David Lin <dtwlin@google.com>
Reviewed-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Alex Elder <elder@linaro.org>
This commit is contained in:
David Lin 2016-07-07 22:07:00 -05:00 committed by Alex Elder
parent 776165481d
commit 2c8e8841e3
3 changed files with 88 additions and 1 deletions

View File

@ -233,6 +233,71 @@ int gb_control_timesync_authoritative(struct gb_control *control,
NULL, 0);
}
static int gb_control_bundle_pm_status_map(u8 status)
{
switch (status) {
case GB_CONTROL_BUNDLE_PM_INVAL:
return -EINVAL;
case GB_CONTROL_BUNDLE_PM_BUSY:
return -EBUSY;
case GB_CONTROL_BUNDLE_PM_NA:
return -ENOMSG;
case GB_CONTROL_BUNDLE_PM_FAIL:
default:
return -EREMOTEIO;
}
}
int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id)
{
struct gb_control_bundle_pm_request request;
struct gb_control_bundle_pm_response response;
int ret;
request.bundle_id = bundle_id;
ret = gb_operation_sync(control->connection,
GB_CONTROL_TYPE_BUNDLE_SUSPEND, &request,
sizeof(request), &response, sizeof(response));
if (ret) {
dev_err(&control->dev,
"failed to send bundle suspend: %d\n", ret);
return ret;
}
if (response.status != GB_CONTROL_BUNDLE_PM_OK) {
dev_err(&control->dev,
"bundle error while suspending: %d\n", response.status);
return gb_control_bundle_pm_status_map(response.status);
}
return 0;
}
int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id)
{
struct gb_control_bundle_pm_request request;
struct gb_control_bundle_pm_response response;
int ret;
request.bundle_id = bundle_id;
ret = gb_operation_sync(control->connection,
GB_CONTROL_TYPE_BUNDLE_RESUME, &request,
sizeof(request), &response, sizeof(response));
if (ret) {
dev_err(&control->dev,
"failed to send bundle resume: %d\n", ret);
return ret;
}
if (response.status != GB_CONTROL_BUNDLE_PM_OK) {
dev_err(&control->dev,
"bundle error while resuming: %d\n", response.status);
return gb_control_bundle_pm_status_map(response.status);
}
return 0;
}
static ssize_t vendor_string_show(struct device *dev,
struct device_attribute *attr, char *buf)
{

View File

@ -52,5 +52,6 @@ int gb_control_timesync_get_last_event(struct gb_control *control,
u64 *frame_time);
int gb_control_timesync_authoritative(struct gb_control *control,
u64 *frame_time);
int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id);
int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id);
#endif /* __CONTROL_H */

View File

@ -126,6 +126,8 @@ struct gb_protocol_version_response {
#define GB_CONTROL_TYPE_DISCONNECTING 0x0c
#define GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT 0x0d
#define GB_CONTROL_TYPE_MODE_SWITCH 0x0e
#define GB_CONTROL_TYPE_BUNDLE_SUSPEND 0x0f
#define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10
struct gb_control_version_request {
__u8 major;
@ -191,6 +193,25 @@ struct gb_control_timesync_get_last_event_response {
__le64 frame_time;
} __packed;
/*
* All Bundle power management operations use the same request and response
* layout and status codes.
*/
#define GB_CONTROL_BUNDLE_PM_OK 0x00
#define GB_CONTROL_BUNDLE_PM_INVAL 0x01
#define GB_CONTROL_BUNDLE_PM_BUSY 0x02
#define GB_CONTROL_BUNDLE_PM_FAIL 0x03
#define GB_CONTROL_BUNDLE_PM_NA 0x04
struct gb_control_bundle_pm_request {
__u8 bundle_id;
} __packed;
struct gb_control_bundle_pm_response {
__u8 status;
} __packed;
/* APBridge protocol */
/* request APB1 log */