video: tegra: host: Move device data to nvhost_device
[linux-2.6.git] / drivers / video / tegra / host / bus.c
1 /*
2  * drivers/video/tegra/host/bus.c
3  *
4  * Copyright (C) 2010 Google, Inc.
5  * Author: Erik Gilling <konkers@google.com>
6  *
7  * Copyright (C) 2010-2011 NVIDIA Corporation
8  *
9  * This software is licensed under the terms of the GNU General Public
10  * License version 2, as published by the Free Software Foundation, and
11  * may be copied, distributed, and modified under those terms.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  */
19
20 #include <linux/pm_runtime.h>
21 #include <linux/nvhost.h>
22
23 #include "dev.h"
24
25 struct nvhost_master *nvhost;
26
27 struct resource *nvhost_get_resource(struct nvhost_device *dev,
28                                        unsigned int type, unsigned int num)
29 {
30         int i;
31
32         for (i = 0; i < dev->num_resources; i++) {
33                 struct resource *r = &dev->resource[i];
34
35                 if (type == resource_type(r) && num-- == 0)
36                         return r;
37         }
38         return NULL;
39 }
40 EXPORT_SYMBOL_GPL(nvhost_get_resource);
41
42 int nvhost_get_irq(struct nvhost_device *dev, unsigned int num)
43 {
44         struct resource *r = nvhost_get_resource(dev, IORESOURCE_IRQ, num);
45
46         return r ? r->start : -ENXIO;
47 }
48 EXPORT_SYMBOL_GPL(nvhost_get_irq);
49
50 struct resource *nvhost_get_resource_byname(struct nvhost_device *dev,
51                                               unsigned int type,
52                                               const char *name)
53 {
54         int i;
55
56         for (i = 0; i < dev->num_resources; i++) {
57                 struct resource *r = &dev->resource[i];
58
59                 if (type == resource_type(r) && !strcmp(r->name, name))
60                         return r;
61         }
62         return NULL;
63 }
64 EXPORT_SYMBOL_GPL(nvhost_get_resource_byname);
65
66 int nvhost_get_irq_byname(struct nvhost_device *dev, const char *name)
67 {
68         struct resource *r = nvhost_get_resource_byname(dev, IORESOURCE_IRQ,
69                                                           name);
70
71         return r ? r->start : -ENXIO;
72 }
73 EXPORT_SYMBOL_GPL(nvhost_get_irq_byname);
74
75 static int nvhost_drv_probe(struct device *_dev)
76 {
77         struct nvhost_driver *drv = to_nvhost_driver(_dev->driver);
78         struct nvhost_device *dev = to_nvhost_device(_dev);
79
80         dev->host = nvhost;
81
82         return drv->probe(dev);
83 }
84
85 static int nvhost_drv_remove(struct device *_dev)
86 {
87         struct nvhost_driver *drv = to_nvhost_driver(_dev->driver);
88         struct nvhost_device *dev = to_nvhost_device(_dev);
89
90         return drv->remove(dev);
91 }
92
93 static void nvhost_drv_shutdown(struct device *_dev)
94 {
95         struct nvhost_driver *drv = to_nvhost_driver(_dev->driver);
96         struct nvhost_device *dev = to_nvhost_device(_dev);
97
98         drv->shutdown(dev);
99 }
100
101 int nvhost_driver_register(struct nvhost_driver *drv)
102 {
103         drv->driver.bus = &nvhost_bus_type;
104         if (drv->probe)
105                 drv->driver.probe = nvhost_drv_probe;
106         if (drv->remove)
107                 drv->driver.remove = nvhost_drv_remove;
108         if (drv->shutdown)
109                 drv->driver.shutdown = nvhost_drv_shutdown;
110
111         return driver_register(&drv->driver);
112 }
113 EXPORT_SYMBOL(nvhost_driver_register);
114
115 void nvhost_driver_unregister(struct nvhost_driver *drv)
116 {
117         driver_unregister(&drv->driver);
118 }
119 EXPORT_SYMBOL_GPL(nvhost_driver_unregister);
120
121 int nvhost_device_register(struct nvhost_device *dev)
122 {
123         int i, ret = 0;
124
125         if (!dev)
126                 return -EINVAL;
127
128         device_initialize(&dev->dev);
129
130         /*  If the dev does not have a parent, assign host1x as parent */
131         if (!dev->dev.parent && nvhost && nvhost->dev != dev)
132                 dev->dev.parent = &nvhost->dev->dev;
133
134         /*  Give pointer to host1x */
135         dev->host = nvhost;
136         dev->dev.bus = &nvhost_bus_type;
137
138         if (dev->id != -1)
139                 dev_set_name(&dev->dev, "%s.%d", dev->name,  dev->id);
140         else
141                 dev_set_name(&dev->dev, "%s", dev->name);
142
143         for (i = 0; i < dev->num_resources; i++) {
144                 struct resource *p, *r = &dev->resource[i];
145
146                 if (r->name == NULL)
147                         r->name = dev_name(&dev->dev);
148
149                 p = r->parent;
150                 if (!p) {
151                         if (resource_type(r) == IORESOURCE_MEM)
152                                 p = &iomem_resource;
153                         else if (resource_type(r) == IORESOURCE_IO)
154                                 p = &ioport_resource;
155                 }
156
157                 if (p && insert_resource(p, r)) {
158                         pr_err("%s: failed to claim resource %d\n",
159                                dev_name(&dev->dev), i);
160                         ret = -EBUSY;
161                         goto failed;
162                 }
163         }
164
165         ret = device_add(&dev->dev);
166         if (ret == 0)
167                 return ret;
168
169 failed:
170         while (--i >= 0) {
171                 struct resource *r = &dev->resource[i];
172                 unsigned long type = resource_type(r);
173
174                 if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
175                         release_resource(r);
176         }
177
178         return ret;
179 }
180 EXPORT_SYMBOL_GPL(nvhost_device_register);
181
182 void nvhost_device_unregister(struct nvhost_device *dev)
183 {
184         int i;
185         if (dev) {
186                 device_del(&dev->dev);
187
188                 for (i = 0; i < dev->num_resources; i++) {
189                         struct resource *r = &dev->resource[i];
190                         unsigned long type = resource_type(r);
191
192                         if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
193                                 release_resource(r);
194                 }
195
196                 put_device(&dev->dev);
197         }
198 }
199 EXPORT_SYMBOL_GPL(nvhost_device_unregister);
200
201 static int nvhost_bus_match(struct device *_dev, struct device_driver *drv)
202 {
203         struct nvhost_device *dev = to_nvhost_device(_dev);
204
205         return !strncmp(dev->name, drv->name, strlen(drv->name));
206 }
207
208 #ifdef CONFIG_PM_SLEEP
209
210 static int nvhost_legacy_suspend(struct device *dev, pm_message_t mesg)
211 {
212         struct nvhost_driver *pdrv = to_nvhost_driver(dev->driver);
213         struct nvhost_device *pdev = to_nvhost_device(dev);
214         int ret = 0;
215
216         if (dev->driver && pdrv->suspend)
217                 ret = pdrv->suspend(pdev, mesg);
218
219         return ret;
220 }
221
222 static int nvhost_legacy_resume(struct device *dev)
223 {
224         struct nvhost_driver *pdrv = to_nvhost_driver(dev->driver);
225         struct nvhost_device *pdev = to_nvhost_device(dev);
226         int ret = 0;
227
228         if (dev->driver && pdrv->resume)
229                 ret = pdrv->resume(pdev);
230
231         return ret;
232 }
233
234 static int nvhost_pm_prepare(struct device *dev)
235 {
236         struct device_driver *drv = dev->driver;
237         int ret = 0;
238
239         if (drv && drv->pm && drv->pm->prepare)
240                 ret = drv->pm->prepare(dev);
241
242         return ret;
243 }
244
245 static void nvhost_pm_complete(struct device *dev)
246 {
247         struct device_driver *drv = dev->driver;
248
249         if (drv && drv->pm && drv->pm->complete)
250                 drv->pm->complete(dev);
251 }
252
253 #else /* !CONFIG_PM_SLEEP */
254
255 #define nvhost_pm_prepare               NULL
256 #define nvhost_pm_complete              NULL
257
258 #endif /* !CONFIG_PM_SLEEP */
259
260 #ifdef CONFIG_SUSPEND
261
262 int __weak nvhost_pm_suspend(struct device *dev)
263 {
264         struct device_driver *drv = dev->driver;
265         int ret = 0;
266
267         if (!drv)
268                 return 0;
269
270         if (drv->pm) {
271                 if (drv->pm->suspend)
272                         ret = drv->pm->suspend(dev);
273         } else {
274                 ret = nvhost_legacy_suspend(dev, PMSG_SUSPEND);
275         }
276
277         return ret;
278 }
279
280 int __weak nvhost_pm_suspend_noirq(struct device *dev)
281 {
282         struct device_driver *drv = dev->driver;
283         int ret = 0;
284
285         if (!drv)
286                 return 0;
287
288         if (drv->pm) {
289                 if (drv->pm->suspend_noirq)
290                         ret = drv->pm->suspend_noirq(dev);
291         }
292
293         return ret;
294 }
295
296 int __weak nvhost_pm_resume(struct device *dev)
297 {
298         struct device_driver *drv = dev->driver;
299         int ret = 0;
300
301         if (!drv)
302                 return 0;
303
304         if (drv->pm) {
305                 if (drv->pm->resume)
306                         ret = drv->pm->resume(dev);
307         } else {
308                 ret = nvhost_legacy_resume(dev);
309         }
310
311         return ret;
312 }
313
314 int __weak nvhost_pm_resume_noirq(struct device *dev)
315 {
316         struct device_driver *drv = dev->driver;
317         int ret = 0;
318
319         if (!drv)
320                 return 0;
321
322         if (drv->pm) {
323                 if (drv->pm->resume_noirq)
324                         ret = drv->pm->resume_noirq(dev);
325         }
326
327         return ret;
328 }
329
330 #else /* !CONFIG_SUSPEND */
331
332 #define nvhost_pm_suspend               NULL
333 #define nvhost_pm_resume                NULL
334 #define nvhost_pm_suspend_noirq NULL
335 #define nvhost_pm_resume_noirq  NULL
336
337 #endif /* !CONFIG_SUSPEND */
338
339 #ifdef CONFIG_HIBERNATION
340
341 static int nvhost_pm_freeze(struct device *dev)
342 {
343         struct device_driver *drv = dev->driver;
344         int ret = 0;
345
346         if (!drv)
347                 return 0;
348
349         if (drv->pm) {
350                 if (drv->pm->freeze)
351                         ret = drv->pm->freeze(dev);
352         } else {
353                 ret = nvhost_legacy_suspend(dev, PMSG_FREEZE);
354         }
355
356         return ret;
357 }
358
359 static int nvhost_pm_freeze_noirq(struct device *dev)
360 {
361         struct device_driver *drv = dev->driver;
362         int ret = 0;
363
364         if (!drv)
365                 return 0;
366
367         if (drv->pm) {
368                 if (drv->pm->freeze_noirq)
369                         ret = drv->pm->freeze_noirq(dev);
370         }
371
372         return ret;
373 }
374
375 static int nvhost_pm_thaw(struct device *dev)
376 {
377         struct device_driver *drv = dev->driver;
378         int ret = 0;
379
380         if (!drv)
381                 return 0;
382
383         if (drv->pm) {
384                 if (drv->pm->thaw)
385                         ret = drv->pm->thaw(dev);
386         } else {
387                 ret = nvhost_legacy_resume(dev);
388         }
389
390         return ret;
391 }
392
393 static int nvhost_pm_thaw_noirq(struct device *dev)
394 {
395         struct device_driver *drv = dev->driver;
396         int ret = 0;
397
398         if (!drv)
399                 return 0;
400
401         if (drv->pm) {
402                 if (drv->pm->thaw_noirq)
403                         ret = drv->pm->thaw_noirq(dev);
404         }
405
406         return ret;
407 }
408
409 static int nvhost_pm_poweroff(struct device *dev)
410 {
411         struct device_driver *drv = dev->driver;
412         int ret = 0;
413
414         if (!drv)
415                 return 0;
416
417         if (drv->pm) {
418                 if (drv->pm->poweroff)
419                         ret = drv->pm->poweroff(dev);
420         } else {
421                 ret = nvhost_legacy_suspend(dev, PMSG_HIBERNATE);
422         }
423
424         return ret;
425 }
426
427 static int nvhost_pm_poweroff_noirq(struct device *dev)
428 {
429         struct device_driver *drv = dev->driver;
430         int ret = 0;
431
432         if (!drv)
433                 return 0;
434
435         if (drv->pm) {
436                 if (drv->pm->poweroff_noirq)
437                         ret = drv->pm->poweroff_noirq(dev);
438         }
439
440         return ret;
441 }
442
443 static int nvhost_pm_restore(struct device *dev)
444 {
445         struct device_driver *drv = dev->driver;
446         int ret = 0;
447
448         if (!drv)
449                 return 0;
450
451         if (drv->pm) {
452                 if (drv->pm->restore)
453                         ret = drv->pm->restore(dev);
454         } else {
455                 ret = nvhost_legacy_resume(dev);
456         }
457
458         return ret;
459 }
460
461 static int nvhost_pm_restore_noirq(struct device *dev)
462 {
463         struct device_driver *drv = dev->driver;
464         int ret = 0;
465
466         if (!drv)
467                 return 0;
468
469         if (drv->pm) {
470                 if (drv->pm->restore_noirq)
471                         ret = drv->pm->restore_noirq(dev);
472         }
473
474         return ret;
475 }
476
477 #else /* !CONFIG_HIBERNATION */
478
479 #define nvhost_pm_freeze                NULL
480 #define nvhost_pm_thaw          NULL
481 #define nvhost_pm_poweroff              NULL
482 #define nvhost_pm_restore               NULL
483 #define nvhost_pm_freeze_noirq  NULL
484 #define nvhost_pm_thaw_noirq            NULL
485 #define nvhost_pm_poweroff_noirq        NULL
486 #define nvhost_pm_restore_noirq NULL
487
488 #endif /* !CONFIG_HIBERNATION */
489
490 #ifdef CONFIG_PM_RUNTIME
491
492 int __weak nvhost_pm_runtime_suspend(struct device *dev)
493 {
494         return pm_generic_runtime_suspend(dev);
495 };
496
497 int __weak nvhost_pm_runtime_resume(struct device *dev)
498 {
499         return pm_generic_runtime_resume(dev);
500 };
501
502 int __weak nvhost_pm_runtime_idle(struct device *dev)
503 {
504         return pm_generic_runtime_idle(dev);
505 };
506
507 #else /* !CONFIG_PM_RUNTIME */
508
509 #define nvhost_pm_runtime_suspend NULL
510 #define nvhost_pm_runtime_resume NULL
511 #define nvhost_pm_runtime_idle NULL
512
513 #endif /* !CONFIG_PM_RUNTIME */
514
515 static const struct dev_pm_ops nvhost_dev_pm_ops = {
516         .prepare = nvhost_pm_prepare,
517         .complete = nvhost_pm_complete,
518         .suspend = nvhost_pm_suspend,
519         .resume = nvhost_pm_resume,
520         .freeze = nvhost_pm_freeze,
521         .thaw = nvhost_pm_thaw,
522         .poweroff = nvhost_pm_poweroff,
523         .restore = nvhost_pm_restore,
524         .suspend_noirq = nvhost_pm_suspend_noirq,
525         .resume_noirq = nvhost_pm_resume_noirq,
526         .freeze_noirq = nvhost_pm_freeze_noirq,
527         .thaw_noirq = nvhost_pm_thaw_noirq,
528         .poweroff_noirq = nvhost_pm_poweroff_noirq,
529         .restore_noirq = nvhost_pm_restore_noirq,
530         .runtime_suspend = nvhost_pm_runtime_suspend,
531         .runtime_resume = nvhost_pm_runtime_resume,
532         .runtime_idle = nvhost_pm_runtime_idle,
533 };
534
535 struct bus_type nvhost_bus_type = {
536         .name           = "nvhost",
537         .match          = nvhost_bus_match,
538         .pm             = &nvhost_dev_pm_ops,
539 };
540 EXPORT_SYMBOL(nvhost_bus_type);
541
542 static int set_parent(struct device *dev, void *data)
543 {
544         struct nvhost_device *ndev = to_nvhost_device(dev);
545         struct nvhost_master *host = data;
546         if (!dev->parent && ndev != host->dev)
547                 dev->parent = &host->dev->dev;
548         ndev->host = host;
549         return 0;
550 }
551
552 int nvhost_bus_add_host(struct nvhost_master *host)
553 {
554         nvhost = host;
555
556         /*  Assign host1x as parent to all devices in nvhost bus */
557         bus_for_each_dev(&nvhost_bus_type, NULL, host, set_parent);
558
559         return 0;
560 }
561
562
563 int nvhost_bus_init(void)
564 {
565         int err;
566
567         pr_info("host1x bus init\n");
568
569         err = bus_register(&nvhost_bus_type);
570
571         return err;
572 }
573 postcore_initcall(nvhost_bus_init);
574