blob: ba2754aa513c8f2d96edd935dabcec9c67953547 [file] [log] [blame]
Viresh Kumarcdee4f72015-06-22 16:42:26 +05301/*
2 * Greybus CPort control protocol.
3 *
4 * Copyright 2015 Google Inc.
5 * Copyright 2015 Linaro Ltd.
6 *
7 * Released under the GPLv2 only.
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/slab.h>
13#include "greybus.h"
14
Johan Hovold6bd6e142016-01-19 12:51:13 +010015/* Highest control-protocol version supported */
16#define GB_CONTROL_VERSION_MAJOR 0
17#define GB_CONTROL_VERSION_MINOR 1
18
19
Viresh Kumaree9627b2016-01-28 15:50:49 +053020static int gb_control_get_version(struct gb_control *control)
Johan Hovolde217ae72016-01-19 12:51:14 +010021{
22 struct gb_interface *intf = control->connection->intf;
23 struct gb_control_version_request request;
24 struct gb_control_version_response response;
25 int ret;
26
27 request.major = GB_CONTROL_VERSION_MAJOR;
28 request.minor = GB_CONTROL_VERSION_MINOR;
29
30 ret = gb_operation_sync(control->connection,
31 GB_CONTROL_TYPE_VERSION,
32 &request, sizeof(request), &response,
33 sizeof(response));
34 if (ret) {
35 dev_err(&intf->dev,
36 "failed to get control-protocol version: %d\n",
37 ret);
38 return ret;
39 }
40
41 if (response.major > request.major) {
42 dev_err(&intf->dev,
43 "unsupported major control-protocol version (%u > %u)\n",
44 response.major, request.major);
45 return -ENOTSUPP;
46 }
47
48 control->protocol_major = response.major;
49 control->protocol_minor = response.minor;
50
51 dev_dbg(&intf->dev, "%s - %u.%u\n", __func__, response.major,
52 response.minor);
53
54 return 0;
55}
56
Johan Hovoldb807aa72016-01-19 12:51:21 +010057static int gb_control_get_bundle_version(struct gb_control *control,
58 struct gb_bundle *bundle)
59{
60 struct gb_interface *intf = control->connection->intf;
61 struct gb_control_bundle_version_request request;
62 struct gb_control_bundle_version_response response;
63 int ret;
64
65 request.bundle_id = bundle->id;
66
67 ret = gb_operation_sync(control->connection,
68 GB_CONTROL_TYPE_BUNDLE_VERSION,
69 &request, sizeof(request),
70 &response, sizeof(response));
71 if (ret) {
72 dev_err(&intf->dev,
73 "failed to get bundle %u class version: %d\n",
74 bundle->id, ret);
75 return ret;
76 }
77
78 bundle->class_major = response.major;
79 bundle->class_minor = response.minor;
80
81 dev_dbg(&intf->dev, "%s - %u: %u.%u\n", __func__, bundle->id,
82 response.major, response.minor);
83
84 return 0;
85}
86
87int gb_control_get_bundle_versions(struct gb_control *control)
88{
89 struct gb_interface *intf = control->connection->intf;
90 struct gb_bundle *bundle;
91 int ret;
92
93 if (!control->has_bundle_version)
94 return 0;
95
96 list_for_each_entry(bundle, &intf->bundles, links) {
97 ret = gb_control_get_bundle_version(control, bundle);
98 if (ret)
99 return ret;
100 }
101
102 return 0;
103}
104
Viresh Kumarcdee4f72015-06-22 16:42:26 +0530105/* Get Manifest's size from the interface */
106int gb_control_get_manifest_size_operation(struct gb_interface *intf)
107{
108 struct gb_control_get_manifest_size_response response;
109 struct gb_connection *connection = intf->control->connection;
110 int ret;
111
112 ret = gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST_SIZE,
113 NULL, 0, &response, sizeof(response));
114 if (ret) {
Johan Hovold7fa530a2015-11-25 15:59:23 +0100115 dev_err(&connection->intf->dev,
116 "failed to get manifest size: %d\n", ret);
Viresh Kumarcdee4f72015-06-22 16:42:26 +0530117 return ret;
118 }
119
120 return le16_to_cpu(response.size);
121}
122
123/* Reads Manifest from the interface */
124int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest,
125 size_t size)
126{
127 struct gb_connection *connection = intf->control->connection;
128
129 return gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST,
130 NULL, 0, manifest, size);
131}
132
133int gb_control_connected_operation(struct gb_control *control, u16 cport_id)
134{
135 struct gb_control_connected_request request;
136
137 request.cport_id = cpu_to_le16(cport_id);
138 return gb_operation_sync(control->connection, GB_CONTROL_TYPE_CONNECTED,
139 &request, sizeof(request), NULL, 0);
140}
141
142int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id)
143{
144 struct gb_control_disconnected_request request;
145
146 request.cport_id = cpu_to_le16(cport_id);
147 return gb_operation_sync(control->connection,
148 GB_CONTROL_TYPE_DISCONNECTED, &request,
149 sizeof(request), NULL, 0);
150}
151
Viresh Kumard39bf702015-12-28 11:59:01 +0530152int gb_control_get_interface_version_operation(struct gb_interface *intf)
153{
154 struct gb_control_interface_version_response response;
155 struct gb_connection *connection = intf->control->connection;
156 int ret;
157
158 /* The ES3 bootrom fails to boot if this request it sent to it */
159 if (intf->boot_over_unipro)
160 return 0;
161
162 ret = gb_operation_sync(connection, GB_CONTROL_TYPE_INTERFACE_VERSION,
163 NULL, 0, &response, sizeof(response));
164 if (ret) {
165 dev_err(&connection->intf->dev,
166 "failed to get interface version: %d\n", ret);
167 /*
168 * FIXME: Return success until the time we bump version of
169 * control protocol. The interface-version is already set to
170 * 0.0, so no need to update that.
171 */
172 return 0;
173 }
174
175 intf->version_major = le16_to_cpu(response.major);
176 intf->version_minor = le16_to_cpu(response.minor);
177
178 return 0;
179}
180
Johan Hovoldc6346502015-12-15 15:28:56 +0100181struct gb_control *gb_control_create(struct gb_interface *intf)
Viresh Kumarcdee4f72015-06-22 16:42:26 +0530182{
183 struct gb_control *control;
Viresh Kumarcdee4f72015-06-22 16:42:26 +0530184
185 control = kzalloc(sizeof(*control), GFP_KERNEL);
186 if (!control)
Johan Hovoldc6346502015-12-15 15:28:56 +0100187 return NULL;
Viresh Kumarcdee4f72015-06-22 16:42:26 +0530188
Johan Hovold59507e22016-01-21 17:34:12 +0100189 control->connection = gb_connection_create_control(intf);
Johan Hovold24e094d2016-01-21 17:34:16 +0100190 if (IS_ERR(control->connection)) {
191 dev_err(&intf->dev,
192 "failed to create control connection: %ld\n",
193 PTR_ERR(control->connection));
Johan Hovoldc6346502015-12-15 15:28:56 +0100194 kfree(control);
195 return NULL;
196 }
Viresh Kumarcdee4f72015-06-22 16:42:26 +0530197
Johan Hovoldc6346502015-12-15 15:28:56 +0100198 control->connection->private = control;
199
200 return control;
201}
202
203int gb_control_enable(struct gb_control *control)
204{
205 int ret;
206
207 dev_dbg(&control->connection->intf->dev, "%s\n", __func__);
208
Johan Hovolde217ae72016-01-19 12:51:14 +0100209 ret = gb_connection_enable_tx(control->connection);
Johan Hovoldc6346502015-12-15 15:28:56 +0100210 if (ret) {
211 dev_err(&control->connection->intf->dev,
212 "failed to enable control connection: %d\n",
213 ret);
214 return ret;
215 }
216
Johan Hovolde217ae72016-01-19 12:51:14 +0100217 ret = gb_control_get_version(control);
218 if (ret)
219 goto err_disable_connection;
220
Johan Hovoldb807aa72016-01-19 12:51:21 +0100221 if (control->protocol_major > 0 || control->protocol_minor > 1)
222 control->has_bundle_version = true;
223
Johan Hovoldc6346502015-12-15 15:28:56 +0100224 return 0;
Johan Hovolde217ae72016-01-19 12:51:14 +0100225
226err_disable_connection:
227 gb_connection_disable(control->connection);
228
229 return ret;
Johan Hovoldc6346502015-12-15 15:28:56 +0100230}
231
232void gb_control_disable(struct gb_control *control)
233{
234 dev_dbg(&control->connection->intf->dev, "%s\n", __func__);
235
Johan Hovolde217ae72016-01-19 12:51:14 +0100236 gb_connection_disable(control->connection);
Johan Hovoldc6346502015-12-15 15:28:56 +0100237}
238
239void gb_control_destroy(struct gb_control *control)
240{
241 gb_connection_destroy(control->connection);
242 kfree(control);
243}