diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a53fa3d68280de2886e7085983cd757790f1f455..252352ce366459300f83206ceda524b3a6d4038b 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -348,6 +348,41 @@ int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id) return 0; } +static int gb_control_interface_pm_status_map(u8 status) +{ + switch (status) { + case GB_CONTROL_INTF_PM_BUSY: + return -EBUSY; + case GB_CONTROL_INTF_PM_NA: + return -ENOMSG; + default: + return -EREMOTEIO; + } +} + +int gb_control_interface_suspend_prepare(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send interface suspend prepare: %d\n", ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while preparing suspend: %d\n", + response.status); + return gb_control_interface_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 5ddf0138c6c5538895bd982c446f2b829c54baca..bc32ca78d2256e7d33b62484abc72e963fb72a47 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -56,4 +56,5 @@ int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id); int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); +int gb_control_interface_suspend_prepare(struct gb_control *control); #endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 1ae335040139854c31aefc12e545476a4bbff8d4..cd64a99debfa113d692be44dccedf93794a27a07 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -130,6 +130,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10 #define GB_CONTROL_TYPE_BUNDLE_DEACTIVATE 0x11 #define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12 +#define GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE 0x13 struct gb_control_version_request { __u8 major; @@ -214,6 +215,20 @@ struct gb_control_bundle_pm_response { __u8 status; } __packed; +/* + * Interface Suspend Prepare and Deactivate Prepare operations use the same + * response layout and error codes. Define a single response structure and reuse + * it. Both operations have no payload. + */ + +#define GB_CONTROL_INTF_PM_OK 0x00 +#define GB_CONTROL_INTF_PM_BUSY 0x01 +#define GB_CONTROL_INTF_PM_NA 0x02 + +struct gb_control_intf_pm_response { + __u8 status; +} __packed; + /* APBridge protocol */ /* request APB1 log */