From 2c8e8841e3b8cea90cc9b7172eebfdf90b06038a Mon Sep 17 00:00:00 2001 From: David Lin Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: [PATCH] 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 Reviewed-by: Johan Hovold Signed-off-by: Alex Elder --- drivers/staging/greybus/control.c | 65 +++++++++++++++++++++ drivers/staging/greybus/control.h | 3 +- drivers/staging/greybus/greybus_protocols.h | 21 +++++++ 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 88e5718965d6..a95c776f17a1 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -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) { diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index b1e5af25352a..c7f34635ea92 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -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 */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 0043b912f720..3b6fd0268529 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -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 */ -- 2.39.5