]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/sh/kernel/cpu/bus.c
[PATCH] sh: DMA updates
[linux-2.6-omap-h63xx.git] / arch / sh / kernel / cpu / bus.c
1 /*
2  * arch/sh/kernel/cpu/bus.c
3  *
4  * Virtual bus for SuperH.
5  *
6  * Copyright (C) 2004 Paul Mundt
7  *
8  * Shamelessly cloned from arch/arm/mach-omap/bus.c, which was written
9  * by:
10  *
11  *      Copyright (C) 2003 - 2004 Nokia Corporation
12  *      Written by Tony Lindgren <tony@atomide.com>
13  *      Portions of code based on sa1111.c.
14  *
15  * This program is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published by the
17  * Free Software Foundation; either version 2 of the License, or (at your
18  * option) any later version.
19  */
20 #include <linux/kernel.h>
21 #include <linux/device.h>
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <asm/bus-sh.h>
25
26 static int sh_bus_match(struct device *dev, struct device_driver *drv)
27 {
28         struct sh_driver *shdrv = to_sh_driver(drv);
29         struct sh_dev *shdev = to_sh_dev(dev);
30
31         return shdev->dev_id == shdrv->dev_id;
32 }
33
34 static int sh_bus_suspend(struct device *dev, pm_message_t state)
35 {
36         struct sh_dev *shdev = to_sh_dev(dev);
37         struct sh_driver *shdrv = to_sh_driver(dev->driver);
38
39         if (shdrv && shdrv->suspend)
40                 return shdrv->suspend(shdev, state);
41
42         return 0;
43 }
44
45 static int sh_bus_resume(struct device *dev)
46 {
47         struct sh_dev *shdev = to_sh_dev(dev);
48         struct sh_driver *shdrv = to_sh_driver(dev->driver);
49
50         if (shdrv && shdrv->resume)
51                 return shdrv->resume(shdev);
52
53         return 0;
54 }
55
56 static int sh_device_probe(struct device *dev)
57 {
58         struct sh_dev *shdev = to_sh_dev(dev);
59         struct sh_driver *shdrv = to_sh_driver(dev->driver);
60
61         if (shdrv && shdrv->probe)
62                 return shdrv->probe(shdev);
63
64         return -ENODEV;
65 }
66
67 static int sh_device_remove(struct device *dev)
68 {
69         struct sh_dev *shdev = to_sh_dev(dev);
70         struct sh_driver *shdrv = to_sh_driver(dev->driver);
71
72         if (shdrv && shdrv->remove)
73                 return shdrv->remove(shdev);
74
75         return 0;
76 }
77
78 static struct device sh_bus_devices[SH_NR_BUSES] = {
79         {
80                 .bus_id         = SH_BUS_NAME_VIRT,
81         },
82 };
83
84 struct bus_type sh_bus_types[SH_NR_BUSES] = {
85         {
86                 .name           = SH_BUS_NAME_VIRT,
87                 .match          = sh_bus_match,
88                 .probe          = sh_bus_probe,
89                 .remove         = sh_bus_remove,
90                 .suspend        = sh_bus_suspend,
91                 .resume         = sh_bus_resume,
92         },
93 };
94
95 int sh_device_register(struct sh_dev *dev)
96 {
97         if (!dev)
98                 return -EINVAL;
99
100         if (dev->bus_id < 0 || dev->bus_id >= SH_NR_BUSES) {
101                 printk(KERN_ERR "%s: bus_id invalid: %s bus: %d\n",
102                        __FUNCTION__, dev->name, dev->bus_id);
103                 return -EINVAL;
104         }
105
106         dev->dev.parent = &sh_bus_devices[dev->bus_id];
107         dev->dev.bus    = &sh_bus_types[dev->bus_id];
108
109         /* This is needed for USB OHCI to work */
110         if (dev->dma_mask)
111                 dev->dev.dma_mask = dev->dma_mask;
112         if (dev->coherent_dma_mask)
113                 dev->dev.coherent_dma_mask = dev->coherent_dma_mask;
114
115         snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u",
116                  dev->name, dev->dev_id);
117
118         printk(KERN_INFO "Registering SH device '%s'. Parent at %s\n",
119                dev->dev.bus_id, dev->dev.parent->bus_id);
120
121         return device_register(&dev->dev);
122 }
123
124 void sh_device_unregister(struct sh_dev *dev)
125 {
126         device_unregister(&dev->dev);
127 }
128
129 int sh_driver_register(struct sh_driver *drv)
130 {
131         if (!drv)
132                 return -EINVAL;
133
134         if (drv->bus_id < 0 || drv->bus_id >= SH_NR_BUSES) {
135                 printk(KERN_ERR "%s: bus_id invalid: bus: %d device %d\n",
136                        __FUNCTION__, drv->bus_id, drv->dev_id);
137                 return -EINVAL;
138         }
139
140         drv->drv.bus    = &sh_bus_types[drv->bus_id];
141
142         return driver_register(&drv->drv);
143 }
144
145 void sh_driver_unregister(struct sh_driver *drv)
146 {
147         driver_unregister(&drv->drv);
148 }
149
150 static int __init sh_bus_init(void)
151 {
152         int i, ret = 0;
153
154         for (i = 0; i < SH_NR_BUSES; i++) {
155                 ret = device_register(&sh_bus_devices[i]);
156                 if (ret != 0) {
157                         printk(KERN_ERR "Unable to register bus device %s\n",
158                                sh_bus_devices[i].bus_id);
159                         continue;
160                 }
161
162                 ret = bus_register(&sh_bus_types[i]);
163                 if (ret != 0) {
164                         printk(KERN_ERR "Unable to register bus %s\n",
165                                sh_bus_types[i].name);
166                         device_unregister(&sh_bus_devices[i]);
167                 }
168         }
169
170         printk(KERN_INFO "SH Virtual Bus initialized\n");
171
172         return ret;
173 }
174
175 static void __exit sh_bus_exit(void)
176 {
177         int i;
178
179         for (i = 0; i < SH_NR_BUSES; i++) {
180                 bus_unregister(&sh_bus_types[i]);
181                 device_unregister(&sh_bus_devices[i]);
182         }
183 }
184
185 module_init(sh_bus_init);
186 module_exit(sh_bus_exit);
187
188 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
189 MODULE_DESCRIPTION("SH Virtual Bus");
190 MODULE_LICENSE("GPL");
191
192 EXPORT_SYMBOL(sh_bus_types);
193 EXPORT_SYMBOL(sh_device_register);
194 EXPORT_SYMBOL(sh_device_unregister);
195 EXPORT_SYMBOL(sh_driver_register);
196 EXPORT_SYMBOL(sh_driver_unregister);
197