summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEli Sennesh <esennesh@leaflabs.com>2016-05-16 14:55:17 -0400
committerGreg Kroah-Hartman <gregkh@google.com>2016-05-24 09:02:07 -0700
commit00606367141cf518e94d8354a02d298475de67e5 (patch)
treef67b4564d86ba430fc3f23577abded5c8a7c2053 /drivers
parentd7be800f7ae9398055509b3a83d0ea3118e9277f (diff)
downloadop-kernel-dev-00606367141cf518e94d8354a02d298475de67e5.zip
op-kernel-dev-00606367141cf518e94d8354a02d298475de67e5.tar.gz
greybus: update UniPro Set Interface Power Mode operation to match spec
Bring the gb_svc_intf_set_power_mode() up-to-date with the current Greybus specification. This largely involves adding more members to the structure sent across the wire. Also change the camera code to use the new operation properly, with default values passed for the new necessary arguments. The correctness of these default values is confirmed via testing and by asking Rob Johnson. Testing Done: Took a picture with a camera module, received error code when passing deliberately incorrect values for new parameters, got proper -EIO and Greybus result code printed when operation stopped halfway through. Associated Firmware Changes: 6810-6812 on Gerrit for SW-1239, 6870 and 5612-5613 on Gerrit for SW-2945 Signed-off-by: Eli Sennesh <esennesh@leaflabs.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/greybus/camera.c10
-rw-r--r--drivers/staging/greybus/greybus_protocols.h28
-rw-r--r--drivers/staging/greybus/svc.c24
-rw-r--r--drivers/staging/greybus/svc.h5
4 files changed, 61 insertions, 6 deletions
diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c
index dd482bd..654bfcd 100644
--- a/drivers/staging/greybus/camera.c
+++ b/drivers/staging/greybus/camera.c
@@ -121,17 +121,23 @@ static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id,
ret = gb_svc_intf_set_power_mode(svc, intf_id,
GB_SVC_UNIPRO_HS_SERIES_A,
GB_SVC_UNIPRO_FAST_MODE, 2, 2,
+ GB_SVC_SMALL_AMPLITUDE,
+ GB_SVC_NO_DE_EMPHASIS,
GB_SVC_UNIPRO_FAST_MODE, 2, 2,
GB_SVC_PWRM_RXTERMINATION |
- GB_SVC_PWRM_TXTERMINATION, 0);
+ GB_SVC_PWRM_TXTERMINATION, 0,
+ NULL, NULL);
else
ret = gb_svc_intf_set_power_mode(svc, intf_id,
GB_SVC_UNIPRO_HS_SERIES_A,
GB_SVC_UNIPRO_SLOW_AUTO_MODE,
2, 1,
+ GB_SVC_SMALL_AMPLITUDE,
+ GB_SVC_NO_DE_EMPHASIS,
GB_SVC_UNIPRO_SLOW_AUTO_MODE,
2, 1,
- 0, 0);
+ 0, 0,
+ NULL, NULL);
return ret;
}
diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h
index b98f02c..ec3570a 100644
--- a/drivers/staging/greybus/greybus_protocols.h
+++ b/drivers/staging/greybus/greybus_protocols.h
@@ -1136,6 +1136,13 @@ struct gb_svc_timesync_ping_response {
#define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11
#define GB_SVC_UNIPRO_OFF_MODE 0x12
+#define GB_SVC_SMALL_AMPLITUDE 0x01
+#define GB_SVC_LARGE_AMPLITUDE 0x02
+
+#define GB_SVC_NO_DE_EMPHASIS 0x00
+#define GB_SVC_SMALL_DE_EMPHASIS 0x01
+#define GB_SVC_LARGE_DE_EMPHASIS 0x02
+
#define GB_SVC_PWRM_RXTERMINATION 0x01
#define GB_SVC_PWRM_TXTERMINATION 0x02
#define GB_SVC_PWRM_LINE_RESET 0x04
@@ -1146,17 +1153,38 @@ struct gb_svc_timesync_ping_response {
#define GB_SVC_UNIPRO_HS_SERIES_A 0x01
#define GB_SVC_UNIPRO_HS_SERIES_B 0x02
+#define GB_SVC_SETPWRM_PWR_OK 0x00
+#define GB_SVC_SETPWRM_PWR_LOCAL 0x01
+#define GB_SVC_SETPWRM_PWR_REMOTE 0x02
+#define GB_SVC_SETPWRM_PWR_BUSY 0x03
+#define GB_SVC_SETPWRM_PWR_ERROR_CAP 0x04
+#define GB_SVC_SETPWRM_PWR_FATAL_ERROR 0x05
+
+struct gb_svc_l2_timer_cfg {
+ __le16 tsb_fc0_protection_timeout;
+ __le16 tsb_tc0_replay_timeout;
+ __le16 tsb_afc0_req_timeout;
+ __le16 tsb_fc1_protection_timeout;
+ __le16 tsb_tc1_replay_timeout;
+ __le16 tsb_afc1_req_timeout;
+ __le16 reserved_for_tc2[3];
+ __le16 reserved_for_tc3[3];
+} __packed;
+
struct gb_svc_intf_set_pwrm_request {
__u8 intf_id;
__u8 hs_series;
__u8 tx_mode;
__u8 tx_gear;
__u8 tx_nlanes;
+ __u8 tx_amplitude;
+ __u8 tx_hs_equalizer;
__u8 rx_mode;
__u8 rx_gear;
__u8 rx_nlanes;
__u8 flags;
__le32 quirks;
+ struct gb_svc_l2_timer_cfg local_l2timerdata, remote_l2timerdata;
} __packed;
struct gb_svc_intf_set_pwrm_response {
diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c
index 78cc0e3..90094cf 100644
--- a/drivers/staging/greybus/svc.c
+++ b/drivers/staging/greybus/svc.c
@@ -578,23 +578,33 @@ void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id)
int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series,
u8 tx_mode, u8 tx_gear, u8 tx_nlanes,
+ u8 tx_amplitude, u8 tx_hs_equalizer,
u8 rx_mode, u8 rx_gear, u8 rx_nlanes,
- u8 flags, u32 quirks)
+ u8 flags, u32 quirks,
+ struct gb_svc_l2_timer_cfg *local,
+ struct gb_svc_l2_timer_cfg *remote)
{
struct gb_svc_intf_set_pwrm_request request;
struct gb_svc_intf_set_pwrm_response response;
int ret;
+ u16 result_code;
request.intf_id = intf_id;
request.hs_series = hs_series;
request.tx_mode = tx_mode;
request.tx_gear = tx_gear;
request.tx_nlanes = tx_nlanes;
+ request.tx_amplitude = tx_amplitude;
+ request.tx_hs_equalizer = tx_hs_equalizer;
request.rx_mode = rx_mode;
request.rx_gear = rx_gear;
request.rx_nlanes = rx_nlanes;
request.flags = flags;
request.quirks = cpu_to_le32(quirks);
+ if (local)
+ request.local_l2timerdata = *local;
+ if (remote)
+ request.remote_l2timerdata = *remote;
ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM,
&request, sizeof(request),
@@ -602,7 +612,13 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series,
if (ret < 0)
return ret;
- return le16_to_cpu(response.result_code);
+ result_code = le16_to_cpu(response.result_code);
+ if (result_code != GB_SVC_SETPWRM_PWR_LOCAL) {
+ dev_err(&svc->dev, "set power mode = %d\n", result_code);
+ return -EIO;
+ }
+
+ return 0;
}
EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode);
@@ -926,9 +942,11 @@ static void gb_svc_process_hello_deferred(struct gb_operation *operation)
GB_SVC_UNIPRO_HS_SERIES_A,
GB_SVC_UNIPRO_SLOW_AUTO_MODE,
2, 1,
+ GB_SVC_SMALL_AMPLITUDE, GB_SVC_NO_DE_EMPHASIS,
GB_SVC_UNIPRO_SLOW_AUTO_MODE,
2, 1,
- 0, 0);
+ 0, 0,
+ NULL, NULL);
if (ret)
dev_warn(&svc->dev,
diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h
index e3e0aa1..438806d 100644
--- a/drivers/staging/greybus/svc.h
+++ b/drivers/staging/greybus/svc.h
@@ -77,8 +77,11 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector,
u32 value);
int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series,
u8 tx_mode, u8 tx_gear, u8 tx_nlanes,
+ u8 tx_amplitude, u8 tx_hs_equalizer,
u8 rx_mode, u8 rx_gear, u8 rx_nlanes,
- u8 flags, u32 quirks);
+ u8 flags, u32 quirks,
+ struct gb_svc_l2_timer_cfg *local,
+ struct gb_svc_l2_timer_cfg *remote);
int gb_svc_ping(struct gb_svc *svc);
int gb_svc_watchdog_create(struct gb_svc *svc);
void gb_svc_watchdog_destroy(struct gb_svc *svc);
OpenPOWER on IntegriCloud