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;
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_connection_bind_protocol(struct legacy_connection *lc)
44 struct gb_connection *connection = lc->connection;
45 struct gb_protocol *protocol;
49 * The legacy protocols have always been looked up using a hard-coded
50 * version of 0.1, despite (or perhaps rather, due to) the fact that
51 * module version negotiation could not take place until after the
57 protocol = gb_protocol_get(lc->protocol_id, major, minor);
59 dev_err(&connection->hd->dev,
60 "protocol 0x%02x version %u.%u not found\n",
61 lc->protocol_id, major, minor);
62 return -EPROTONOSUPPORT;
64 connection->protocol = protocol;
69 static void legacy_connection_unbind_protocol(struct gb_connection *connection)
71 struct gb_protocol *protocol = connection->protocol;
73 gb_protocol_put(protocol);
75 connection->protocol = NULL;
78 static int legacy_request_handler(struct gb_operation *operation)
80 struct gb_protocol *protocol = operation->connection->protocol;
82 return protocol->request_recv(operation->type, operation);
85 static int legacy_connection_init(struct legacy_connection *lc)
87 struct gb_connection *connection = lc->connection;
88 gb_request_handler_t handler;
91 dev_dbg(&connection->bundle->dev, "%s - %s\n", __func__,
94 ret = legacy_connection_bind_protocol(lc);
98 if (connection->protocol->request_recv)
99 handler = legacy_request_handler;
103 ret = gb_connection_enable(connection, handler);
105 goto err_unbind_protocol;
107 ret = legacy_connection_get_version(connection);
111 ret = connection->protocol->connection_init(connection);
115 lc->initialized = true;
120 gb_connection_disable(connection);
122 legacy_connection_unbind_protocol(connection);
127 static void legacy_connection_exit(struct legacy_connection *lc)
129 struct gb_connection *connection = lc->connection;
131 if (!lc->initialized)
134 gb_connection_disable(connection);
136 connection->protocol->connection_exit(connection);
138 legacy_connection_unbind_protocol(connection);
140 lc->initialized = false;
143 static int legacy_connection_create(struct legacy_connection *lc,
144 struct gb_bundle *bundle,
145 struct greybus_descriptor_cport *desc)
147 struct gb_connection *connection;
149 connection = gb_connection_create(bundle, le16_to_cpu(desc->id));
150 if (IS_ERR(connection))
151 return PTR_ERR(connection);
153 lc->connection = connection;
154 lc->protocol_id = desc->protocol_id;
159 static void legacy_connection_destroy(struct legacy_connection *lc)
161 gb_connection_destroy(lc->connection);
164 static int legacy_probe(struct gb_bundle *bundle,
165 const struct greybus_bundle_id *id)
167 struct greybus_descriptor_cport *cport_desc;
168 struct legacy_data *data;
169 struct legacy_connection *lc;
173 dev_dbg(&bundle->dev,
174 "%s - bundle class = 0x%02x, num_cports = %zu\n",
175 __func__, bundle->class, bundle->num_cports);
177 data = kzalloc(sizeof(*data), GFP_KERNEL);
181 data->num_cports = bundle->num_cports;
182 data->connections = kcalloc(data->num_cports,
183 sizeof(*data->connections),
185 if (!data->connections) {
190 for (i = 0; i < data->num_cports; ++i) {
191 cport_desc = &bundle->cport_desc[i];
192 lc = &data->connections[i];
194 ret = legacy_connection_create(lc, bundle, cport_desc);
196 goto err_connections_destroy;
199 greybus_set_drvdata(bundle, data);
201 for (i = 0; i < data->num_cports; ++i) {
202 lc = &data->connections[i];
204 ret = legacy_connection_init(lc);
206 goto err_connections_disable;
211 err_connections_disable:
212 for (--i; i >= 0; --i)
213 legacy_connection_exit(&data->connections[i]);
214 err_connections_destroy:
215 for (i = 0; i < data->num_cports; ++i)
216 legacy_connection_destroy(&data->connections[i]);
217 kfree(data->connections);
224 static void legacy_disconnect(struct gb_bundle *bundle)
226 struct legacy_data *data = greybus_get_drvdata(bundle);
229 dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__,
232 for (i = 0; i < data->num_cports; ++i) {
233 legacy_connection_exit(&data->connections[i]);
234 legacy_connection_destroy(&data->connections[i]);
237 kfree(data->connections);
241 static const struct greybus_bundle_id legacy_id_table[] = {
242 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) },
243 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) },
244 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) },
245 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_HID) },
246 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) },
247 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) },
248 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) },
249 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) },
250 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) },
251 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_DISPLAY) },
252 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) },
253 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SENSOR) },
254 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) },
255 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) },
256 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) },
257 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_MGMT) },
258 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_DATA) },
259 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SVC) },
260 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FIRMWARE) },
261 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) },
264 MODULE_DEVICE_TABLE(greybus, legacy_id_table);
266 static struct greybus_driver legacy_driver = {
268 .probe = legacy_probe,
269 .disconnect = legacy_disconnect,
270 .id_table = legacy_id_table,
273 int gb_legacy_init(void)
275 return greybus_register(&legacy_driver);
278 void gb_legacy_exit(void)
280 greybus_deregister(&legacy_driver);