f082658d4d0377564d4a313806867ea991714d76
[cascardo/linux.git] / drivers / staging / greybus / gpbridge.c
1 /*
2  * Greybus GP Bridge driver
3  *
4  * Copyright 2014 Google Inc.
5  * Copyright 2014 Linaro Ltd.
6  *
7  * Released under the GPLv2 only.
8  */
9
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
12 #include <linux/types.h>
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/kernel.h>
16 #include <linux/slab.h>
17 #include <linux/device.h>
18
19 #include "greybus.h"
20 #include "gpbridge.h"
21
22 struct gpbridge_host {
23         struct gb_bundle *bundle;
24         struct list_head devices;
25 };
26
27 static DEFINE_IDA(gpbridge_id);
28
29 static ssize_t protocol_id_show(struct device *dev,
30                                  struct device_attribute *attr, char *buf)
31 {
32         struct gpbridge_device *gpbdev = to_gpbridge_dev(dev);
33
34         return sprintf(buf, "0x%02x\n", gpbdev->cport_desc->protocol_id);
35 }
36 static DEVICE_ATTR_RO(protocol_id);
37
38 static struct attribute *gpbdev_attrs[] = {
39         &dev_attr_protocol_id.attr,
40         NULL,
41 };
42
43 ATTRIBUTE_GROUPS(gpbdev);
44
45 static void gpbdev_release(struct device *dev)
46 {
47         struct gpbridge_device *gpbdev = to_gpbridge_dev(dev);
48
49         ida_simple_remove(&gpbridge_id, gpbdev->id);
50         kfree(gpbdev);
51 }
52
53 struct device_type greybus_gpbdev_type = {
54         .name    =      "gpbridge_device",
55         .release =      gpbdev_release,
56 };
57
58 static int gpbdev_uevent(struct device *dev, struct kobj_uevent_env *env)
59 {
60         struct gpbridge_device *gpbdev = to_gpbridge_dev(dev);
61         struct greybus_descriptor_cport *cport_desc = gpbdev->cport_desc;
62         struct gb_bundle *bundle = gpbdev->bundle;
63         struct gb_interface *intf = bundle->intf;
64         struct gb_module *module = intf->module;
65         struct gb_host_device *hd = intf->hd;
66
67         if (add_uevent_var(env, "BUS=%u", hd->bus_id))
68                 return -ENOMEM;
69         if (add_uevent_var(env, "MODULE=%u", module->module_id))
70                 return -ENOMEM;
71         if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id))
72                 return -ENOMEM;
73         if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x",
74                            intf->vendor_id, intf->product_id))
75                 return -ENOMEM;
76         if (add_uevent_var(env, "BUNDLE=%u", gpbdev->bundle->id))
77                 return -ENOMEM;
78         if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class))
79                 return -ENOMEM;
80         if (add_uevent_var(env, "GPBDEV_ID=%u", gpbdev->id))
81                 return -ENOMEM;
82         if (add_uevent_var(env, "PROTOCOL_ID=%02x", cport_desc->protocol_id))
83                 return -ENOMEM;
84
85         return 0;
86 }
87
88 static const struct gpbridge_device_id *
89 gpbdev_match_id(struct gpbridge_device *gpbdev, struct gpbridge_driver *gpbdrv)
90 {
91         const struct gpbridge_device_id *id = gpbdrv->id_table;
92
93         if (!id)
94                 return NULL;
95
96         for (; id->protocol_id; id++)
97                 if (id->protocol_id == gpbdev->cport_desc->protocol_id)
98                         return id;
99
100         return NULL;
101 }
102
103 static int gpbdev_match(struct device *dev, struct device_driver *drv)
104 {
105         struct gpbridge_driver *gpbdrv = to_gpbridge_driver(drv);
106         struct gpbridge_device *gpbdev = to_gpbridge_dev(dev);
107         const struct gpbridge_device_id *id;
108
109         id = gpbdev_match_id(gpbdev, gpbdrv);
110         if (id)
111                 return 1;
112
113         return 0;
114 }
115
116 static int gpbdev_probe(struct device *dev)
117 {
118         struct gpbridge_driver *gpbdrv = to_gpbridge_driver(dev->driver);
119         struct gpbridge_device *gpbdev = to_gpbridge_dev(dev);
120         const struct gpbridge_device_id *id;
121
122         id = gpbdev_match_id(gpbdev, gpbdrv);
123         if (!id)
124                 return -ENODEV;
125
126         return gpbdrv->probe(gpbdev, id);
127 }
128
129 static int gpbdev_remove(struct device *dev)
130 {
131         struct gpbridge_driver *gpbdrv = to_gpbridge_driver(dev->driver);
132         struct gpbridge_device *gpbdev = to_gpbridge_dev(dev);
133
134         gpbdrv->remove(gpbdev);
135         return 0;
136 }
137
138 static struct bus_type gpbridge_bus_type = {
139         .name =         "gpbridge",
140         .match =        gpbdev_match,
141         .probe =        gpbdev_probe,
142         .remove =       gpbdev_remove,
143         .uevent =       gpbdev_uevent,
144 };
145
146 int gb_gpbridge_register_driver(struct gpbridge_driver *driver,
147                              struct module *owner, const char *mod_name)
148 {
149         int retval;
150
151         if (greybus_disabled())
152                 return -ENODEV;
153
154         driver->driver.bus = &gpbridge_bus_type;
155         driver->driver.name = driver->name;
156         driver->driver.owner = owner;
157         driver->driver.mod_name = mod_name;
158
159         retval = driver_register(&driver->driver);
160         if (retval)
161                 return retval;
162
163         pr_info("registered new driver %s\n", driver->name);
164         return 0;
165 }
166 EXPORT_SYMBOL_GPL(gb_gpbridge_register_driver);
167
168 void gb_gpbridge_deregister_driver(struct gpbridge_driver *driver)
169 {
170         driver_unregister(&driver->driver);
171 }
172 EXPORT_SYMBOL_GPL(gb_gpbridge_deregister_driver);
173
174 int gb_gpbridge_get_version(struct gb_connection *connection)
175 {
176         struct gb_protocol_version_request request;
177         struct gb_protocol_version_response response;
178         int retval;
179
180         request.major = 1;
181         request.minor = 0;
182
183         retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION,
184                                    &request, sizeof(request), &response,
185                                    sizeof(response));
186         if (retval)
187                 return retval;
188
189         /* FIXME - do proper version negotiation here someday... */
190
191         connection->module_major = response.major;
192         connection->module_minor = response.minor;
193
194         dev_dbg(&connection->hd->dev, "%s: v%u.%u\n", connection->name,
195                 response.major, response.minor);
196
197         return 0;
198 }
199 EXPORT_SYMBOL_GPL(gb_gpbridge_get_version);
200
201 static struct gpbridge_device *gb_gpbridge_create_dev(struct gb_bundle *bundle,
202                                 struct greybus_descriptor_cport *cport_desc)
203 {
204         struct gpbridge_device *gpbdev;
205         int retval;
206         int id;
207
208         id = ida_simple_get(&gpbridge_id, 1, 0, GFP_KERNEL);
209         if (id < 0)
210                 return ERR_PTR(id);
211
212         gpbdev = kzalloc(sizeof(*gpbdev), GFP_KERNEL);
213         if (!gpbdev) {
214                 ida_simple_remove(&gpbridge_id, id);
215                 return ERR_PTR(-ENOMEM);
216         }
217
218         gpbdev->id = id;
219         gpbdev->bundle = bundle;
220         gpbdev->cport_desc = cport_desc;
221         gpbdev->dev.parent = &bundle->dev;
222         gpbdev->dev.bus = &gpbridge_bus_type;
223         gpbdev->dev.type = &greybus_gpbdev_type;
224         gpbdev->dev.groups = gpbdev_groups;
225         gpbdev->dev.dma_mask = bundle->dev.dma_mask;
226         dev_set_name(&gpbdev->dev, "gpb%d", id);
227
228         retval = device_register(&gpbdev->dev);
229         if (retval) {
230                 put_device(&gpbdev->dev);
231                 return ERR_PTR(retval);
232         }
233
234         return gpbdev;
235 }
236
237 static void gb_gpbridge_disconnect(struct gb_bundle *bundle)
238 {
239         struct gpbridge_host *gpb_host = greybus_get_drvdata(bundle);
240         struct gpbridge_device *gpbdev, *temp;
241
242         list_for_each_entry_safe(gpbdev, temp, &gpb_host->devices, list) {
243                 list_del(&gpbdev->list);
244                 device_unregister(&gpbdev->dev);
245         }
246
247         kfree(gpb_host);
248 }
249
250 static int gb_gpbridge_probe(struct gb_bundle *bundle,
251                           const struct greybus_bundle_id *id)
252 {
253         struct gpbridge_host *gpb_host;
254         struct gpbridge_device *gpbdev;
255         int i;
256
257         if (bundle->num_cports == 0)
258                 return -ENODEV;
259
260         gpb_host = kzalloc(sizeof(*gpb_host), GFP_KERNEL);
261         if (!gpb_host)
262                 return -ENOMEM;
263
264         gpb_host->bundle = bundle;
265         INIT_LIST_HEAD(&gpb_host->devices);
266         greybus_set_drvdata(bundle, gpb_host);
267
268         /*
269          * Create a bunch of children devices, one per cport, and bind the
270          * bridged phy drivers to them.
271          */
272         for (i = 0; i < bundle->num_cports; ++i) {
273                 gpbdev = gb_gpbridge_create_dev(bundle, &bundle->cport_desc[i]);
274                 if (IS_ERR(gpbdev)) {
275                         gb_gpbridge_disconnect(bundle);
276                         return PTR_ERR(gpbdev);
277                 }
278                 list_add(&gpbdev->list, &gpb_host->devices);
279         }
280
281         return 0;
282 }
283
284 static const struct greybus_bundle_id gb_gpbridge_id_table[] = {
285         { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) },
286         { },
287 };
288 MODULE_DEVICE_TABLE(greybus, gb_gpbridge_id_table);
289
290 static struct greybus_driver gb_gpbridge_driver = {
291         .name           = "gpbridge",
292         .probe          = gb_gpbridge_probe,
293         .disconnect     = gb_gpbridge_disconnect,
294         .id_table       = gb_gpbridge_id_table,
295 };
296
297 static int __init gpbridge_init(void)
298 {
299         int retval;
300
301         retval = bus_register(&gpbridge_bus_type);
302         if (retval) {
303                 pr_err("gpbridge bus register failed (%d)\n", retval);
304                 return retval;
305         }
306
307         retval = greybus_register(&gb_gpbridge_driver);
308         if (retval) {
309                 pr_err("error registering greybus driver\n");
310                 goto error_gpbridge;
311         }
312
313         return 0;
314
315 error_gpbridge:
316         bus_unregister(&gpbridge_bus_type);
317         ida_destroy(&gpbridge_id);
318         return retval;
319 }
320 module_init(gpbridge_init);
321
322 static void __exit gpbridge_exit(void)
323 {
324         greybus_deregister(&gb_gpbridge_driver);
325         bus_unregister(&gpbridge_bus_type);
326         ida_destroy(&gpbridge_id);
327 }
328 module_exit(gpbridge_exit);
329
330 MODULE_LICENSE("GPL v2");