]> Pileus Git - ~andy/linux/blob - drivers/gpu/host1x/bus.c
ASoC: hdmi-codec: Add devicetree binding with documentation
[~andy/linux] / drivers / gpu / host1x / bus.c
1 /*
2  * Copyright (C) 2012 Avionic Design GmbH
3  * Copyright (C) 2012-2013, NVIDIA Corporation
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <linux/host1x.h>
19 #include <linux/of.h>
20 #include <linux/slab.h>
21
22 #include "dev.h"
23
24 static DEFINE_MUTEX(clients_lock);
25 static LIST_HEAD(clients);
26
27 static DEFINE_MUTEX(drivers_lock);
28 static LIST_HEAD(drivers);
29
30 static DEFINE_MUTEX(devices_lock);
31 static LIST_HEAD(devices);
32
33 struct host1x_subdev {
34         struct host1x_client *client;
35         struct device_node *np;
36         struct list_head list;
37 };
38
39 /**
40  * host1x_subdev_add() - add a new subdevice with an associated device node
41  */
42 static int host1x_subdev_add(struct host1x_device *device,
43                              struct device_node *np)
44 {
45         struct host1x_subdev *subdev;
46
47         subdev = kzalloc(sizeof(*subdev), GFP_KERNEL);
48         if (!subdev)
49                 return -ENOMEM;
50
51         INIT_LIST_HEAD(&subdev->list);
52         subdev->np = of_node_get(np);
53
54         mutex_lock(&device->subdevs_lock);
55         list_add_tail(&subdev->list, &device->subdevs);
56         mutex_unlock(&device->subdevs_lock);
57
58         return 0;
59 }
60
61 /**
62  * host1x_subdev_del() - remove subdevice
63  */
64 static void host1x_subdev_del(struct host1x_subdev *subdev)
65 {
66         list_del(&subdev->list);
67         of_node_put(subdev->np);
68         kfree(subdev);
69 }
70
71 /**
72  * host1x_device_parse_dt() - scan device tree and add matching subdevices
73  */
74 static int host1x_device_parse_dt(struct host1x_device *device)
75 {
76         struct device_node *np;
77         int err;
78
79         for_each_child_of_node(device->dev.parent->of_node, np) {
80                 if (of_match_node(device->driver->subdevs, np) &&
81                     of_device_is_available(np)) {
82                         err = host1x_subdev_add(device, np);
83                         if (err < 0)
84                                 return err;
85                 }
86         }
87
88         return 0;
89 }
90
91 static void host1x_subdev_register(struct host1x_device *device,
92                                    struct host1x_subdev *subdev,
93                                    struct host1x_client *client)
94 {
95         int err;
96
97         /*
98          * Move the subdevice to the list of active (registered) subdevices
99          * and associate it with a client. At the same time, associate the
100          * client with its parent device.
101          */
102         mutex_lock(&device->subdevs_lock);
103         mutex_lock(&device->clients_lock);
104         list_move_tail(&client->list, &device->clients);
105         list_move_tail(&subdev->list, &device->active);
106         client->parent = &device->dev;
107         subdev->client = client;
108         mutex_unlock(&device->clients_lock);
109         mutex_unlock(&device->subdevs_lock);
110
111         /*
112          * When all subdevices have been registered, the composite device is
113          * ready to be probed.
114          */
115         if (list_empty(&device->subdevs)) {
116                 err = device->driver->probe(device);
117                 if (err < 0)
118                         dev_err(&device->dev, "probe failed: %d\n", err);
119         }
120 }
121
122 static void __host1x_subdev_unregister(struct host1x_device *device,
123                                        struct host1x_subdev *subdev)
124 {
125         struct host1x_client *client = subdev->client;
126         int err;
127
128         /*
129          * If all subdevices have been activated, we're about to remove the
130          * first active subdevice, so unload the driver first.
131          */
132         if (list_empty(&device->subdevs)) {
133                 err = device->driver->remove(device);
134                 if (err < 0)
135                         dev_err(&device->dev, "remove failed: %d\n", err);
136         }
137
138         /*
139          * Move the subdevice back to the list of idle subdevices and remove
140          * it from list of clients.
141          */
142         mutex_lock(&device->clients_lock);
143         subdev->client = NULL;
144         client->parent = NULL;
145         list_move_tail(&subdev->list, &device->subdevs);
146         /*
147          * XXX: Perhaps don't do this here, but rather explicitly remove it
148          * when the device is about to be deleted.
149          *
150          * This is somewhat complicated by the fact that this function is
151          * used to remove the subdevice when a client is unregistered but
152          * also when the composite device is about to be removed.
153          */
154         list_del_init(&client->list);
155         mutex_unlock(&device->clients_lock);
156 }
157
158 static void host1x_subdev_unregister(struct host1x_device *device,
159                                      struct host1x_subdev *subdev)
160 {
161         mutex_lock(&device->subdevs_lock);
162         __host1x_subdev_unregister(device, subdev);
163         mutex_unlock(&device->subdevs_lock);
164 }
165
166 int host1x_device_init(struct host1x_device *device)
167 {
168         struct host1x_client *client;
169         int err;
170
171         mutex_lock(&device->clients_lock);
172
173         list_for_each_entry(client, &device->clients, list) {
174                 if (client->ops && client->ops->init) {
175                         err = client->ops->init(client);
176                         if (err < 0) {
177                                 dev_err(&device->dev,
178                                         "failed to initialize %s: %d\n",
179                                         dev_name(client->dev), err);
180                                 mutex_unlock(&device->clients_lock);
181                                 return err;
182                         }
183                 }
184         }
185
186         mutex_unlock(&device->clients_lock);
187
188         return 0;
189 }
190
191 int host1x_device_exit(struct host1x_device *device)
192 {
193         struct host1x_client *client;
194         int err;
195
196         mutex_lock(&device->clients_lock);
197
198         list_for_each_entry_reverse(client, &device->clients, list) {
199                 if (client->ops && client->ops->exit) {
200                         err = client->ops->exit(client);
201                         if (err < 0) {
202                                 dev_err(&device->dev,
203                                         "failed to cleanup %s: %d\n",
204                                         dev_name(client->dev), err);
205                                 mutex_unlock(&device->clients_lock);
206                                 return err;
207                         }
208                 }
209         }
210
211         mutex_unlock(&device->clients_lock);
212
213         return 0;
214 }
215
216 static int host1x_register_client(struct host1x *host1x,
217                                   struct host1x_client *client)
218 {
219         struct host1x_device *device;
220         struct host1x_subdev *subdev;
221
222         mutex_lock(&host1x->devices_lock);
223
224         list_for_each_entry(device, &host1x->devices, list) {
225                 list_for_each_entry(subdev, &device->subdevs, list) {
226                         if (subdev->np == client->dev->of_node) {
227                                 host1x_subdev_register(device, subdev, client);
228                                 mutex_unlock(&host1x->devices_lock);
229                                 return 0;
230                         }
231                 }
232         }
233
234         mutex_unlock(&host1x->devices_lock);
235         return -ENODEV;
236 }
237
238 static int host1x_unregister_client(struct host1x *host1x,
239                                     struct host1x_client *client)
240 {
241         struct host1x_device *device, *dt;
242         struct host1x_subdev *subdev;
243
244         mutex_lock(&host1x->devices_lock);
245
246         list_for_each_entry_safe(device, dt, &host1x->devices, list) {
247                 list_for_each_entry(subdev, &device->active, list) {
248                         if (subdev->client == client) {
249                                 host1x_subdev_unregister(device, subdev);
250                                 mutex_unlock(&host1x->devices_lock);
251                                 return 0;
252                         }
253                 }
254         }
255
256         mutex_unlock(&host1x->devices_lock);
257         return -ENODEV;
258 }
259
260 struct bus_type host1x_bus_type = {
261         .name = "host1x",
262 };
263
264 int host1x_bus_init(void)
265 {
266         return bus_register(&host1x_bus_type);
267 }
268
269 void host1x_bus_exit(void)
270 {
271         bus_unregister(&host1x_bus_type);
272 }
273
274 static void host1x_device_release(struct device *dev)
275 {
276         struct host1x_device *device = to_host1x_device(dev);
277
278         kfree(device);
279 }
280
281 static int host1x_device_add(struct host1x *host1x,
282                              struct host1x_driver *driver)
283 {
284         struct host1x_client *client, *tmp;
285         struct host1x_subdev *subdev;
286         struct host1x_device *device;
287         int err;
288
289         device = kzalloc(sizeof(*device), GFP_KERNEL);
290         if (!device)
291                 return -ENOMEM;
292
293         mutex_init(&device->subdevs_lock);
294         INIT_LIST_HEAD(&device->subdevs);
295         INIT_LIST_HEAD(&device->active);
296         mutex_init(&device->clients_lock);
297         INIT_LIST_HEAD(&device->clients);
298         INIT_LIST_HEAD(&device->list);
299         device->driver = driver;
300
301         device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
302         device->dev.dma_mask = &device->dev.coherent_dma_mask;
303         device->dev.release = host1x_device_release;
304         dev_set_name(&device->dev, driver->name);
305         device->dev.bus = &host1x_bus_type;
306         device->dev.parent = host1x->dev;
307
308         err = device_register(&device->dev);
309         if (err < 0)
310                 return err;
311
312         err = host1x_device_parse_dt(device);
313         if (err < 0) {
314                 device_unregister(&device->dev);
315                 return err;
316         }
317
318         mutex_lock(&host1x->devices_lock);
319         list_add_tail(&device->list, &host1x->devices);
320         mutex_unlock(&host1x->devices_lock);
321
322         mutex_lock(&clients_lock);
323
324         list_for_each_entry_safe(client, tmp, &clients, list) {
325                 list_for_each_entry(subdev, &device->subdevs, list) {
326                         if (subdev->np == client->dev->of_node) {
327                                 host1x_subdev_register(device, subdev, client);
328                                 break;
329                         }
330                 }
331         }
332
333         mutex_unlock(&clients_lock);
334
335         return 0;
336 }
337
338 /*
339  * Removes a device by first unregistering any subdevices and then removing
340  * itself from the list of devices.
341  *
342  * This function must be called with the host1x->devices_lock held.
343  */
344 static void host1x_device_del(struct host1x *host1x,
345                               struct host1x_device *device)
346 {
347         struct host1x_subdev *subdev, *sd;
348         struct host1x_client *client, *cl;
349
350         mutex_lock(&device->subdevs_lock);
351
352         /* unregister subdevices */
353         list_for_each_entry_safe(subdev, sd, &device->active, list) {
354                 /*
355                  * host1x_subdev_unregister() will remove the client from
356                  * any lists, so we'll need to manually add it back to the
357                  * list of idle clients.
358                  *
359                  * XXX: Alternatively, perhaps don't remove the client from
360                  * any lists in host1x_subdev_unregister() and instead do
361                  * that explicitly from host1x_unregister_client()?
362                  */
363                 client = subdev->client;
364
365                 __host1x_subdev_unregister(device, subdev);
366
367                 /* add the client to the list of idle clients */
368                 mutex_lock(&clients_lock);
369                 list_add_tail(&client->list, &clients);
370                 mutex_unlock(&clients_lock);
371         }
372
373         /* remove subdevices */
374         list_for_each_entry_safe(subdev, sd, &device->subdevs, list)
375                 host1x_subdev_del(subdev);
376
377         mutex_unlock(&device->subdevs_lock);
378
379         /* move clients to idle list */
380         mutex_lock(&clients_lock);
381         mutex_lock(&device->clients_lock);
382
383         list_for_each_entry_safe(client, cl, &device->clients, list)
384                 list_move_tail(&client->list, &clients);
385
386         mutex_unlock(&device->clients_lock);
387         mutex_unlock(&clients_lock);
388
389         /* finally remove the device */
390         list_del_init(&device->list);
391         device_unregister(&device->dev);
392 }
393
394 static void host1x_attach_driver(struct host1x *host1x,
395                                  struct host1x_driver *driver)
396 {
397         struct host1x_device *device;
398         int err;
399
400         mutex_lock(&host1x->devices_lock);
401
402         list_for_each_entry(device, &host1x->devices, list) {
403                 if (device->driver == driver) {
404                         mutex_unlock(&host1x->devices_lock);
405                         return;
406                 }
407         }
408
409         mutex_unlock(&host1x->devices_lock);
410
411         err = host1x_device_add(host1x, driver);
412         if (err < 0)
413                 dev_err(host1x->dev, "failed to allocate device: %d\n", err);
414 }
415
416 static void host1x_detach_driver(struct host1x *host1x,
417                                  struct host1x_driver *driver)
418 {
419         struct host1x_device *device, *tmp;
420
421         mutex_lock(&host1x->devices_lock);
422
423         list_for_each_entry_safe(device, tmp, &host1x->devices, list)
424                 if (device->driver == driver)
425                         host1x_device_del(host1x, device);
426
427         mutex_unlock(&host1x->devices_lock);
428 }
429
430 int host1x_register(struct host1x *host1x)
431 {
432         struct host1x_driver *driver;
433
434         mutex_lock(&devices_lock);
435         list_add_tail(&host1x->list, &devices);
436         mutex_unlock(&devices_lock);
437
438         mutex_lock(&drivers_lock);
439
440         list_for_each_entry(driver, &drivers, list)
441                 host1x_attach_driver(host1x, driver);
442
443         mutex_unlock(&drivers_lock);
444
445         return 0;
446 }
447
448 int host1x_unregister(struct host1x *host1x)
449 {
450         struct host1x_driver *driver;
451
452         mutex_lock(&drivers_lock);
453
454         list_for_each_entry(driver, &drivers, list)
455                 host1x_detach_driver(host1x, driver);
456
457         mutex_unlock(&drivers_lock);
458
459         mutex_lock(&devices_lock);
460         list_del_init(&host1x->list);
461         mutex_unlock(&devices_lock);
462
463         return 0;
464 }
465
466 int host1x_driver_register(struct host1x_driver *driver)
467 {
468         struct host1x *host1x;
469
470         INIT_LIST_HEAD(&driver->list);
471
472         mutex_lock(&drivers_lock);
473         list_add_tail(&driver->list, &drivers);
474         mutex_unlock(&drivers_lock);
475
476         mutex_lock(&devices_lock);
477
478         list_for_each_entry(host1x, &devices, list)
479                 host1x_attach_driver(host1x, driver);
480
481         mutex_unlock(&devices_lock);
482
483         return 0;
484 }
485 EXPORT_SYMBOL(host1x_driver_register);
486
487 void host1x_driver_unregister(struct host1x_driver *driver)
488 {
489         mutex_lock(&drivers_lock);
490         list_del_init(&driver->list);
491         mutex_unlock(&drivers_lock);
492 }
493 EXPORT_SYMBOL(host1x_driver_unregister);
494
495 int host1x_client_register(struct host1x_client *client)
496 {
497         struct host1x *host1x;
498         int err;
499
500         mutex_lock(&devices_lock);
501
502         list_for_each_entry(host1x, &devices, list) {
503                 err = host1x_register_client(host1x, client);
504                 if (!err) {
505                         mutex_unlock(&devices_lock);
506                         return 0;
507                 }
508         }
509
510         mutex_unlock(&devices_lock);
511
512         mutex_lock(&clients_lock);
513         list_add_tail(&client->list, &clients);
514         mutex_unlock(&clients_lock);
515
516         return 0;
517 }
518 EXPORT_SYMBOL(host1x_client_register);
519
520 int host1x_client_unregister(struct host1x_client *client)
521 {
522         struct host1x_client *c;
523         struct host1x *host1x;
524         int err;
525
526         mutex_lock(&devices_lock);
527
528         list_for_each_entry(host1x, &devices, list) {
529                 err = host1x_unregister_client(host1x, client);
530                 if (!err) {
531                         mutex_unlock(&devices_lock);
532                         return 0;
533                 }
534         }
535
536         mutex_unlock(&devices_lock);
537         mutex_lock(&clients_lock);
538
539         list_for_each_entry(c, &clients, list) {
540                 if (c == client) {
541                         list_del_init(&c->list);
542                         break;
543                 }
544         }
545
546         mutex_unlock(&clients_lock);
547
548         return 0;
549 }
550 EXPORT_SYMBOL(host1x_client_unregister);