Merge commit 'main-jb-2012.08.03-B4' into t114-0806
[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-2012 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/slab.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/export.h>
23 #include <linux/nvhost.h>
24 #include <linux/io.h>
25
26 #include "bus.h"
27 #include "dev.h"
28
29 struct nvhost_bus *nvhost_bus_inst;
30 struct nvhost_master *nvhost;
31
32 struct resource *nvhost_get_resource(struct nvhost_device *dev,
33                                        unsigned int type, unsigned int num)
34 {
35         int i;
36
37         for (i = 0; i < dev->num_resources; i++) {
38                 struct resource *r = &dev->resource[i];
39
40                 if (type == resource_type(r) && num-- == 0)
41                         return r;
42         }
43         return NULL;
44 }
45 EXPORT_SYMBOL_GPL(nvhost_get_resource);
46
47 int nvhost_get_irq(struct nvhost_device *dev, unsigned int num)
48 {
49         struct resource *r = nvhost_get_resource(dev, IORESOURCE_IRQ, num);
50
51         return r ? r->start : -ENXIO;
52 }
53 EXPORT_SYMBOL_GPL(nvhost_get_irq);
54
55 struct resource *nvhost_get_resource_byname(struct nvhost_device *dev,
56                                               unsigned int type,
57                                               const char *name)
58 {
59         int i;
60
61         for (i = 0; i < dev->num_resources; i++) {
62                 struct resource *r = &dev->resource[i];
63
64                 if (type == resource_type(r) && !strcmp(r->name, name))
65                         return r;
66         }
67         return NULL;
68 }
69 EXPORT_SYMBOL_GPL(nvhost_get_resource_byname);
70
71 int nvhost_get_irq_byname(struct nvhost_device *dev, const char *name)
72 {
73         struct resource *r = nvhost_get_resource_byname(dev, IORESOURCE_IRQ,
74                                                           name);
75
76         return r ? r->start : -ENXIO;
77 }
78 EXPORT_SYMBOL_GPL(nvhost_get_irq_byname);
79
80 static struct nvhost_device_id *nvhost_bus_match_id(struct nvhost_device *dev,
81         struct nvhost_device_id *id_table)
82 {
83         while (id_table->name[0]) {
84                 if (strcmp(dev->name, id_table->name) == 0
85                                 && dev->version == id_table->version)
86                         return id_table;
87                 id_table++;
88         }
89         return NULL;
90 }
91
92 static int nvhost_bus_match(struct device *_dev, struct device_driver *drv)
93 {
94         struct nvhost_device *dev = to_nvhost_device(_dev);
95         struct nvhost_driver *ndrv = to_nvhost_driver(drv);
96
97         /* check if driver support multiple devices through id_table */
98         if (ndrv->id_table)
99                 return nvhost_bus_match_id(dev, ndrv->id_table) != NULL;
100         else /* driver does not support id_table */
101                 return !strcmp(dev->name, drv->name);
102 }
103
104 static int nvhost_drv_probe(struct device *_dev)
105 {
106         struct nvhost_driver *drv = to_nvhost_driver(_dev->driver);
107         struct nvhost_device *dev = to_nvhost_device(_dev);
108
109         if (drv && drv->probe) {
110                 if (drv->id_table)
111                         return drv->probe(dev, nvhost_bus_match_id(dev, drv->id_table));
112                 else
113                         return drv->probe(dev, NULL);
114         }
115         else
116                 return -ENODEV;
117 }
118
119 static int nvhost_drv_remove(struct device *_dev)
120 {
121         struct nvhost_driver *drv = to_nvhost_driver(_dev->driver);
122         struct nvhost_device *dev = to_nvhost_device(_dev);
123
124         return drv->remove(dev);
125 }
126
127 static void nvhost_drv_shutdown(struct device *_dev)
128 {
129         struct nvhost_driver *drv = to_nvhost_driver(_dev->driver);
130         struct nvhost_device *dev = to_nvhost_device(_dev);
131
132         drv->shutdown(dev);
133 }
134
135 int nvhost_driver_register(struct nvhost_driver *drv)
136 {
137         drv->driver.bus = &nvhost_bus_inst->nvhost_bus_type;
138         if (drv->probe)
139                 drv->driver.probe = nvhost_drv_probe;
140         if (drv->remove)
141                 drv->driver.remove = nvhost_drv_remove;
142         if (drv->shutdown)
143                 drv->driver.shutdown = nvhost_drv_shutdown;
144
145         return driver_register(&drv->driver);
146 }
147 EXPORT_SYMBOL(nvhost_driver_register);
148
149 void nvhost_driver_unregister(struct nvhost_driver *drv)
150 {
151         driver_unregister(&drv->driver);
152 }
153 EXPORT_SYMBOL_GPL(nvhost_driver_unregister);
154
155 int nvhost_add_devices(struct nvhost_device **devs, int num)
156 {
157         int i, ret = 0;
158
159         for (i = 0; i < num; i++) {
160                 ret = nvhost_device_register(devs[i]);
161                 if (ret) {
162                         while (--i >= 0)
163                                 nvhost_device_unregister(devs[i]);
164                         break;
165                 }
166         }
167
168         return ret;
169 }
170 EXPORT_SYMBOL_GPL(nvhost_add_devices);
171
172 int nvhost_device_register(struct nvhost_device *dev)
173 {
174         int i, ret = 0;
175
176         if (!dev)
177                 return -EINVAL;
178
179         device_initialize(&dev->dev);
180
181         /*  If the dev does not have a parent, assign host1x as parent */
182         if (!dev->dev.parent && nvhost && nvhost->dev != dev)
183                 dev->dev.parent = &nvhost->dev->dev;
184
185         dev->dev.bus = &nvhost_bus_inst->nvhost_bus_type;
186
187         if (dev->id != -1)
188                 dev_set_name(&dev->dev, "%s.%d", dev->name,  dev->id);
189         else
190                 dev_set_name(&dev->dev, "%s", dev->name);
191
192         for (i = 0; i < dev->num_resources; i++) {
193                 struct resource *p, *r = &dev->resource[i];
194
195                 if (r->name == NULL)
196                         r->name = dev_name(&dev->dev);
197
198                 p = r->parent;
199                 if (!p) {
200                         if (resource_type(r) == IORESOURCE_MEM)
201                                 p = &iomem_resource;
202                         else if (resource_type(r) == IORESOURCE_IO)
203                                 p = &ioport_resource;
204                 }
205
206                 if (p && insert_resource(p, r)) {
207                         pr_err("%s: failed to claim resource %d\n",
208                                dev_name(&dev->dev), i);
209                         ret = -EBUSY;
210                         goto failed;
211                 }
212         }
213
214         ret = device_add(&dev->dev);
215         if (ret == 0)
216                 return ret;
217
218 failed:
219         while (--i >= 0) {
220                 struct resource *r = &dev->resource[i];
221                 unsigned long type = resource_type(r);
222
223                 if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
224                         release_resource(r);
225         }
226
227         return ret;
228 }
229 EXPORT_SYMBOL_GPL(nvhost_device_register);
230
231 void nvhost_device_unregister(struct nvhost_device *dev)
232 {
233         int i;
234         if (dev) {
235                 device_del(&dev->dev);
236
237                 for (i = 0; i < dev->num_resources; i++) {
238                         struct resource *r = &dev->resource[i];
239                         unsigned long type = resource_type(r);
240
241                         if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
242                                 release_resource(r);
243                 }
244
245                 put_device(&dev->dev);
246         }
247 }
248 EXPORT_SYMBOL_GPL(nvhost_device_unregister);
249
250 void nvhost_device_writel(struct nvhost_device *dev, u32 r, u32 v)
251 {
252         writel(v, dev->aperture + r);
253 }
254 EXPORT_SYMBOL_GPL(nvhost_device_writel);
255
256 u32 nvhost_device_readl(struct nvhost_device *dev, u32 r)
257 {
258         return readl(dev->aperture + r);
259 }
260 EXPORT_SYMBOL_GPL(nvhost_device_readl);
261
262 #ifdef CONFIG_PM_SLEEP
263
264 static int nvhost_legacy_suspend(struct device *dev, pm_message_t mesg)
265 {
266         struct nvhost_driver *pdrv = to_nvhost_driver(dev->driver);
267         struct nvhost_device *pdev = to_nvhost_device(dev);
268         int ret = 0;
269
270         if (dev->driver && pdrv->suspend)
271                 ret = pdrv->suspend(pdev, mesg);
272
273         return ret;
274 }
275
276 static int nvhost_legacy_resume(struct device *dev)
277 {
278         struct nvhost_driver *pdrv = to_nvhost_driver(dev->driver);
279         struct nvhost_device *pdev = to_nvhost_device(dev);
280         int ret = 0;
281
282         if (dev->driver && pdrv->resume)
283                 ret = pdrv->resume(pdev);
284
285         return ret;
286 }
287
288 static int nvhost_pm_prepare(struct device *dev)
289 {
290         struct device_driver *drv = dev->driver;
291         int ret = 0;
292
293         if (drv && drv->pm && drv->pm->prepare)
294                 ret = drv->pm->prepare(dev);
295
296         return ret;
297 }
298
299 static void nvhost_pm_complete(struct device *dev)
300 {
301         struct device_driver *drv = dev->driver;
302
303         if (drv && drv->pm && drv->pm->complete)
304                 drv->pm->complete(dev);
305 }
306
307 #else /* !CONFIG_PM_SLEEP */
308
309 #define nvhost_pm_prepare               NULL
310 #define nvhost_pm_complete              NULL
311
312 #endif /* !CONFIG_PM_SLEEP */
313
314 #ifdef CONFIG_SUSPEND
315
316 int __weak nvhost_pm_suspend(struct device *dev)
317 {
318         struct device_driver *drv = dev->driver;
319         int ret = 0;
320
321         if (!drv)
322                 return 0;
323
324         if (drv->pm) {
325                 if (drv->pm->suspend)
326                         ret = drv->pm->suspend(dev);
327         } else {
328                 ret = nvhost_legacy_suspend(dev, PMSG_SUSPEND);
329         }
330
331         return ret;
332 }
333
334 int __weak nvhost_pm_suspend_noirq(struct device *dev)
335 {
336         struct device_driver *drv = dev->driver;
337         int ret = 0;
338
339         if (!drv)
340                 return 0;
341
342         if (drv->pm) {
343                 if (drv->pm->suspend_noirq)
344                         ret = drv->pm->suspend_noirq(dev);
345         }
346
347         return ret;
348 }
349
350 int __weak nvhost_pm_resume(struct device *dev)
351 {
352         struct device_driver *drv = dev->driver;
353         int ret = 0;
354
355         if (!drv)
356                 return 0;
357
358         if (drv->pm) {
359                 if (drv->pm->resume)
360                         ret = drv->pm->resume(dev);
361         } else {
362                 ret = nvhost_legacy_resume(dev);
363         }
364
365         return ret;
366 }
367
368 int __weak nvhost_pm_resume_noirq(struct device *dev)
369 {
370         struct device_driver *drv = dev->driver;
371         int ret = 0;
372
373         if (!drv)
374                 return 0;
375
376         if (drv->pm) {
377                 if (drv->pm->resume_noirq)
378                         ret = drv->pm->resume_noirq(dev);
379         }
380
381         return ret;
382 }
383
384 #else /* !CONFIG_SUSPEND */
385
386 #define nvhost_pm_suspend               NULL
387 #define nvhost_pm_resume                NULL
388 #define nvhost_pm_suspend_noirq NULL
389 #define nvhost_pm_resume_noirq  NULL
390
391 #endif /* !CONFIG_SUSPEND */
392
393 #ifdef CONFIG_HIBERNATION
394
395 static int nvhost_pm_freeze(struct device *dev)
396 {
397         struct device_driver *drv = dev->driver;
398         int ret = 0;
399
400         if (!drv)
401                 return 0;
402
403         if (drv->pm) {
404                 if (drv->pm->freeze)
405                         ret = drv->pm->freeze(dev);
406         } else {
407                 ret = nvhost_legacy_suspend(dev, PMSG_FREEZE);
408         }
409
410         return ret;
411 }
412
413 static int nvhost_pm_freeze_noirq(struct device *dev)
414 {
415         struct device_driver *drv = dev->driver;
416         int ret = 0;
417
418         if (!drv)
419                 return 0;
420
421         if (drv->pm) {
422                 if (drv->pm->freeze_noirq)
423                         ret = drv->pm->freeze_noirq(dev);
424         }
425
426         return ret;
427 }
428
429 static int nvhost_pm_thaw(struct device *dev)
430 {
431         struct device_driver *drv = dev->driver;
432         int ret = 0;
433
434         if (!drv)
435                 return 0;
436
437         if (drv->pm) {
438                 if (drv->pm->thaw)
439                         ret = drv->pm->thaw(dev);
440         } else {
441                 ret = nvhost_legacy_resume(dev);
442         }
443
444         return ret;
445 }
446
447 static int nvhost_pm_thaw_noirq(struct device *dev)
448 {
449         struct device_driver *drv = dev->driver;
450         int ret = 0;
451
452         if (!drv)
453                 return 0;
454
455         if (drv->pm) {
456                 if (drv->pm->thaw_noirq)
457                         ret = drv->pm->thaw_noirq(dev);
458         }
459
460         return ret;
461 }
462
463 static int nvhost_pm_poweroff(struct device *dev)
464 {
465         struct device_driver *drv = dev->driver;
466         int ret = 0;
467
468         if (!drv)
469                 return 0;
470
471         if (drv->pm) {
472                 if (drv->pm->poweroff)
473                         ret = drv->pm->poweroff(dev);
474         } else {
475                 ret = nvhost_legacy_suspend(dev, PMSG_HIBERNATE);
476         }
477
478         return ret;
479 }
480
481 static int nvhost_pm_poweroff_noirq(struct device *dev)
482 {
483         struct device_driver *drv = dev->driver;
484         int ret = 0;
485
486         if (!drv)
487                 return 0;
488
489         if (drv->pm) {
490                 if (drv->pm->poweroff_noirq)
491                         ret = drv->pm->poweroff_noirq(dev);
492         }
493
494         return ret;
495 }
496
497 static int nvhost_pm_restore(struct device *dev)
498 {
499         struct device_driver *drv = dev->driver;
500         int ret = 0;
501
502         if (!drv)
503                 return 0;
504
505         if (drv->pm) {
506                 if (drv->pm->restore)
507                         ret = drv->pm->restore(dev);
508         } else {
509                 ret = nvhost_legacy_resume(dev);
510         }
511
512         return ret;
513 }
514
515 static int nvhost_pm_restore_noirq(struct device *dev)
516 {
517         struct device_driver *drv = dev->driver;
518         int ret = 0;
519
520         if (!drv)
521                 return 0;
522
523         if (drv->pm) {
524                 if (drv->pm->restore_noirq)
525                         ret = drv->pm->restore_noirq(dev);
526         }
527
528         return ret;
529 }
530
531 #else /* !CONFIG_HIBERNATION */
532
533 #define nvhost_pm_freeze                NULL
534 #define nvhost_pm_thaw          NULL
535 #define nvhost_pm_poweroff              NULL
536 #define nvhost_pm_restore               NULL
537 #define nvhost_pm_freeze_noirq  NULL
538 #define nvhost_pm_thaw_noirq            NULL
539 #define nvhost_pm_poweroff_noirq        NULL
540 #define nvhost_pm_restore_noirq NULL
541
542 #endif /* !CONFIG_HIBERNATION */
543
544 #ifdef CONFIG_PM_RUNTIME
545
546 int __weak nvhost_pm_runtime_suspend(struct device *dev)
547 {
548         return pm_generic_runtime_suspend(dev);
549 };
550
551 int __weak nvhost_pm_runtime_resume(struct device *dev)
552 {
553         return pm_generic_runtime_resume(dev);
554 };
555
556 int __weak nvhost_pm_runtime_idle(struct device *dev)
557 {
558         return pm_generic_runtime_idle(dev);
559 };
560
561 #else /* !CONFIG_PM_RUNTIME */
562
563 #define nvhost_pm_runtime_suspend NULL
564 #define nvhost_pm_runtime_resume NULL
565 #define nvhost_pm_runtime_idle NULL
566
567 #endif /* !CONFIG_PM_RUNTIME */
568
569 static const struct dev_pm_ops nvhost_dev_pm_ops = {
570         .prepare = nvhost_pm_prepare,
571         .complete = nvhost_pm_complete,
572         .suspend = nvhost_pm_suspend,
573         .resume = nvhost_pm_resume,
574         .freeze = nvhost_pm_freeze,
575         .thaw = nvhost_pm_thaw,
576         .poweroff = nvhost_pm_poweroff,
577         .restore = nvhost_pm_restore,
578         .suspend_noirq = nvhost_pm_suspend_noirq,
579         .resume_noirq = nvhost_pm_resume_noirq,
580         .freeze_noirq = nvhost_pm_freeze_noirq,
581         .thaw_noirq = nvhost_pm_thaw_noirq,
582         .poweroff_noirq = nvhost_pm_poweroff_noirq,
583         .restore_noirq = nvhost_pm_restore_noirq,
584         .runtime_suspend = nvhost_pm_runtime_suspend,
585         .runtime_resume = nvhost_pm_runtime_resume,
586         .runtime_idle = nvhost_pm_runtime_idle,
587 };
588
589 static int set_parent(struct device *dev, void *data)
590 {
591         struct nvhost_device *ndev = to_nvhost_device(dev);
592         struct nvhost_master *host = data;
593         if (!dev->parent && ndev != host->dev)
594                 dev->parent = &host->dev->dev;
595         return 0;
596 }
597
598 int nvhost_bus_add_host(struct nvhost_master *host)
599 {
600         nvhost = host;
601
602         /*  Assign host1x as parent to all devices in nvhost bus */
603         bus_for_each_dev(&nvhost_bus_inst->nvhost_bus_type, NULL, host, set_parent);
604
605         return 0;
606 }
607
608 struct nvhost_bus *nvhost_bus_get(void)
609 {
610         return nvhost_bus_inst;
611 }
612
613 int nvhost_bus_init(void)
614 {
615         int err;
616         struct nvhost_chip_support *chip_ops;
617
618         pr_info("host1x bus init\n");
619
620         nvhost_bus_inst = kzalloc(sizeof(*nvhost_bus_inst), GFP_KERNEL);
621         if (nvhost_bus_inst == NULL) {
622                 pr_err("%s: Cannot allocate nvhost_bus\n", __func__);
623                 return -ENOMEM;
624         }
625
626         chip_ops = kzalloc(sizeof(*chip_ops), GFP_KERNEL);
627         if (chip_ops == NULL) {
628                 pr_err("%s: Cannot allocate nvhost_chip_support\n", __func__);
629                 kfree(nvhost_bus_inst);
630                 nvhost_bus_inst = NULL;
631                 return -ENOMEM;
632         }
633
634         nvhost_bus_inst->nvhost_bus_type.name = "nvhost";
635         nvhost_bus_inst->nvhost_bus_type.match = nvhost_bus_match;
636         nvhost_bus_inst->nvhost_bus_type.pm = &nvhost_dev_pm_ops;
637         nvhost_bus_inst->nvhost_chip_ops = chip_ops;
638
639         err = bus_register(&nvhost_bus_inst->nvhost_bus_type);
640
641         return err;
642 }
643 postcore_initcall(nvhost_bus_init);