2 * Greybus legacy-protocol driver
4 * Copyright 2015 Google Inc.
5 * Copyright 2015 Linaro Ltd.
7 * Released under the GPLv2 only.
15 struct legacy_connection {
16 struct gb_connection *connection;
18 struct gb_protocol *protocol;
23 struct legacy_connection *connections;
27 static int legacy_connection_get_version(struct gb_connection *connection)
31 ret = gb_protocol_get_version(connection);
33 dev_err(&connection->hd->dev,
34 "%s: failed to get protocol version: %d\n",
35 connection->name, ret);
42 static int legacy_request_handler(struct gb_operation *operation)
44 struct gb_protocol *protocol = operation->connection->protocol;
46 return protocol->request_recv(operation->type, operation);
49 static int legacy_connection_init(struct legacy_connection *lc)
51 struct gb_connection *connection = lc->connection;
54 dev_dbg(&connection->bundle->dev, "%s - %s\n", __func__,
57 ret = gb_connection_enable(connection);
61 ret = legacy_connection_get_version(connection);
65 ret = connection->protocol->connection_init(connection);
69 lc->initialized = true;
74 gb_connection_disable(connection);
79 static void legacy_connection_exit(struct legacy_connection *lc)
81 struct gb_connection *connection = lc->connection;
86 gb_connection_disable(connection);
88 connection->protocol->connection_exit(connection);
90 lc->initialized = false;
93 static int legacy_connection_create(struct legacy_connection *lc,
94 struct gb_bundle *bundle,
95 struct greybus_descriptor_cport *desc)
97 struct gb_connection *connection;
98 struct gb_protocol *protocol;
99 gb_request_handler_t handler;
104 * The legacy protocols have always been looked up using a hard-coded
105 * version of 0.1, despite (or perhaps rather, due to) the fact that
106 * module version negotiation could not take place until after the
107 * protocol was bound.
112 protocol = gb_protocol_get(desc->protocol_id, major, minor);
114 dev_err(&bundle->dev,
115 "protocol 0x%02x version %u.%u not found\n",
116 desc->protocol_id, major, minor);
117 return -EPROTONOSUPPORT;
120 if (protocol->request_recv)
121 handler = legacy_request_handler;
125 connection = gb_connection_create(bundle, le16_to_cpu(desc->id),
127 if (IS_ERR(connection)) {
128 ret = PTR_ERR(connection);
129 goto err_protocol_put;
133 * NOTE: We need to keep a pointer to the protocol in the actual
134 * connection structure for now.
136 connection->protocol = protocol;
138 lc->connection = connection;
139 lc->protocol = protocol;
144 gb_protocol_put(protocol);
149 static void legacy_connection_destroy(struct legacy_connection *lc)
151 lc->connection->protocol = NULL;
153 gb_connection_destroy(lc->connection);
155 gb_protocol_put(lc->protocol);
158 static int legacy_probe(struct gb_bundle *bundle,
159 const struct greybus_bundle_id *id)
161 struct greybus_descriptor_cport *cport_desc;
162 struct legacy_data *data;
163 struct legacy_connection *lc;
167 dev_dbg(&bundle->dev,
168 "%s - bundle class = 0x%02x, num_cports = %zu\n",
169 __func__, bundle->class, bundle->num_cports);
171 data = kzalloc(sizeof(*data), GFP_KERNEL);
175 data->num_cports = bundle->num_cports;
176 data->connections = kcalloc(data->num_cports,
177 sizeof(*data->connections),
179 if (!data->connections) {
184 for (i = 0; i < data->num_cports; ++i) {
185 cport_desc = &bundle->cport_desc[i];
186 lc = &data->connections[i];
188 ret = legacy_connection_create(lc, bundle, cport_desc);
190 goto err_connections_destroy;
193 greybus_set_drvdata(bundle, data);
195 for (i = 0; i < data->num_cports; ++i) {
196 lc = &data->connections[i];
198 ret = legacy_connection_init(lc);
200 goto err_connections_disable;
205 err_connections_disable:
206 for (--i; i >= 0; --i)
207 legacy_connection_exit(&data->connections[i]);
208 err_connections_destroy:
209 for (i = 0; i < data->num_cports; ++i)
210 legacy_connection_destroy(&data->connections[i]);
211 kfree(data->connections);
218 static void legacy_disconnect(struct gb_bundle *bundle)
220 struct legacy_data *data = greybus_get_drvdata(bundle);
223 dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__,
226 for (i = 0; i < data->num_cports; ++i) {
227 legacy_connection_exit(&data->connections[i]);
228 legacy_connection_destroy(&data->connections[i]);
231 kfree(data->connections);
235 static const struct greybus_bundle_id legacy_id_table[] = {
236 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) },
237 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) },
238 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) },
239 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) },
240 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) },
241 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) },
242 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) },
243 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) },
244 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_DISPLAY) },
245 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) },
246 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SENSOR) },
247 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) },
248 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) },
249 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_MGMT) },
250 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_DATA) },
251 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SVC) },
252 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FIRMWARE) },
253 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) },
256 MODULE_DEVICE_TABLE(greybus, legacy_id_table);
258 static struct greybus_driver legacy_driver = {
260 .probe = legacy_probe,
261 .disconnect = legacy_disconnect,
262 .id_table = legacy_id_table,
265 int gb_legacy_init(void)
267 return greybus_register(&legacy_driver);
270 void gb_legacy_exit(void)
272 greybus_deregister(&legacy_driver);