greybus: control: add bundle suspend and resume preparations
authorDavid Lin <dtwlin@google.com>
Fri, 8 Jul 2016 03:07:00 +0000 (22:07 -0500)
committerAlex Elder <elder@linaro.org>
Fri, 8 Jul 2016 19:56:28 +0000 (14:56 -0500)
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>
drivers/staging/greybus/control.c
drivers/staging/greybus/control.h
drivers/staging/greybus/greybus_protocols.h

index 88e5718..a95c776 100644 (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)
 {
index b1e5af2..c7f3463 100644 (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 */
index 0043b91..3b6fd02 100644 (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 */