Delete all instances of asm/system.h
[linux-flexiantxendom0-3.2.10.git] / drivers / mfd / mcp-core.c
1 /*
2  *  linux/drivers/mfd/mcp-core.c
3  *
4  *  Copyright (C) 2001 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License.
9  *
10  *  Generic MCP (Multimedia Communications Port) layer.  All MCP locking
11  *  is solely held within this file.
12  */
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/smp.h>
17 #include <linux/device.h>
18 #include <linux/slab.h>
19 #include <linux/string.h>
20 #include <linux/mfd/mcp.h>
21
22 #include <mach/dma.h>
23
24
25 #define to_mcp(d)               container_of(d, struct mcp, attached_device)
26 #define to_mcp_driver(d)        container_of(d, struct mcp_driver, drv)
27
28 static int mcp_bus_match(struct device *dev, struct device_driver *drv)
29 {
30         return 1;
31 }
32
33 static int mcp_bus_probe(struct device *dev)
34 {
35         struct mcp *mcp = to_mcp(dev);
36         struct mcp_driver *drv = to_mcp_driver(dev->driver);
37
38         return drv->probe(mcp);
39 }
40
41 static int mcp_bus_remove(struct device *dev)
42 {
43         struct mcp *mcp = to_mcp(dev);
44         struct mcp_driver *drv = to_mcp_driver(dev->driver);
45
46         drv->remove(mcp);
47         return 0;
48 }
49
50 static int mcp_bus_suspend(struct device *dev, pm_message_t state)
51 {
52         struct mcp *mcp = to_mcp(dev);
53         int ret = 0;
54
55         if (dev->driver) {
56                 struct mcp_driver *drv = to_mcp_driver(dev->driver);
57
58                 ret = drv->suspend(mcp, state);
59         }
60         return ret;
61 }
62
63 static int mcp_bus_resume(struct device *dev)
64 {
65         struct mcp *mcp = to_mcp(dev);
66         int ret = 0;
67
68         if (dev->driver) {
69                 struct mcp_driver *drv = to_mcp_driver(dev->driver);
70
71                 ret = drv->resume(mcp);
72         }
73         return ret;
74 }
75
76 static struct bus_type mcp_bus_type = {
77         .name           = "mcp",
78         .match          = mcp_bus_match,
79         .probe          = mcp_bus_probe,
80         .remove         = mcp_bus_remove,
81         .suspend        = mcp_bus_suspend,
82         .resume         = mcp_bus_resume,
83 };
84
85 /**
86  *      mcp_set_telecom_divisor - set the telecom divisor
87  *      @mcp: MCP interface structure
88  *      @div: SIB clock divisor
89  *
90  *      Set the telecom divisor on the MCP interface.  The resulting
91  *      sample rate is SIBCLOCK/div.
92  */
93 void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
94 {
95         unsigned long flags;
96
97         spin_lock_irqsave(&mcp->lock, flags);
98         mcp->ops->set_telecom_divisor(mcp, div);
99         spin_unlock_irqrestore(&mcp->lock, flags);
100 }
101 EXPORT_SYMBOL(mcp_set_telecom_divisor);
102
103 /**
104  *      mcp_set_audio_divisor - set the audio divisor
105  *      @mcp: MCP interface structure
106  *      @div: SIB clock divisor
107  *
108  *      Set the audio divisor on the MCP interface.
109  */
110 void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
111 {
112         unsigned long flags;
113
114         spin_lock_irqsave(&mcp->lock, flags);
115         mcp->ops->set_audio_divisor(mcp, div);
116         spin_unlock_irqrestore(&mcp->lock, flags);
117 }
118 EXPORT_SYMBOL(mcp_set_audio_divisor);
119
120 /**
121  *      mcp_reg_write - write a device register
122  *      @mcp: MCP interface structure
123  *      @reg: 4-bit register index
124  *      @val: 16-bit data value
125  *
126  *      Write a device register.  The MCP interface must be enabled
127  *      to prevent this function hanging.
128  */
129 void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
130 {
131         unsigned long flags;
132
133         spin_lock_irqsave(&mcp->lock, flags);
134         mcp->ops->reg_write(mcp, reg, val);
135         spin_unlock_irqrestore(&mcp->lock, flags);
136 }
137 EXPORT_SYMBOL(mcp_reg_write);
138
139 /**
140  *      mcp_reg_read - read a device register
141  *      @mcp: MCP interface structure
142  *      @reg: 4-bit register index
143  *
144  *      Read a device register and return its value.  The MCP interface
145  *      must be enabled to prevent this function hanging.
146  */
147 unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
148 {
149         unsigned long flags;
150         unsigned int val;
151
152         spin_lock_irqsave(&mcp->lock, flags);
153         val = mcp->ops->reg_read(mcp, reg);
154         spin_unlock_irqrestore(&mcp->lock, flags);
155
156         return val;
157 }
158 EXPORT_SYMBOL(mcp_reg_read);
159
160 /**
161  *      mcp_enable - enable the MCP interface
162  *      @mcp: MCP interface to enable
163  *
164  *      Enable the MCP interface.  Each call to mcp_enable will need
165  *      a corresponding call to mcp_disable to disable the interface.
166  */
167 void mcp_enable(struct mcp *mcp)
168 {
169         unsigned long flags;
170         spin_lock_irqsave(&mcp->lock, flags);
171         if (mcp->use_count++ == 0)
172                 mcp->ops->enable(mcp);
173         spin_unlock_irqrestore(&mcp->lock, flags);
174 }
175 EXPORT_SYMBOL(mcp_enable);
176
177 /**
178  *      mcp_disable - disable the MCP interface
179  *      @mcp: MCP interface to disable
180  *
181  *      Disable the MCP interface.  The MCP interface will only be
182  *      disabled once the number of calls to mcp_enable matches the
183  *      number of calls to mcp_disable.
184  */
185 void mcp_disable(struct mcp *mcp)
186 {
187         unsigned long flags;
188
189         spin_lock_irqsave(&mcp->lock, flags);
190         if (--mcp->use_count == 0)
191                 mcp->ops->disable(mcp);
192         spin_unlock_irqrestore(&mcp->lock, flags);
193 }
194 EXPORT_SYMBOL(mcp_disable);
195
196 static void mcp_release(struct device *dev)
197 {
198         struct mcp *mcp = container_of(dev, struct mcp, attached_device);
199
200         kfree(mcp);
201 }
202
203 struct mcp *mcp_host_alloc(struct device *parent, size_t size)
204 {
205         struct mcp *mcp;
206
207         mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL);
208         if (mcp) {
209                 spin_lock_init(&mcp->lock);
210                 mcp->attached_device.parent = parent;
211                 mcp->attached_device.bus = &mcp_bus_type;
212                 mcp->attached_device.dma_mask = parent->dma_mask;
213                 mcp->attached_device.release = mcp_release;
214         }
215         return mcp;
216 }
217 EXPORT_SYMBOL(mcp_host_alloc);
218
219 int mcp_host_register(struct mcp *mcp)
220 {
221         dev_set_name(&mcp->attached_device, "mcp0");
222         return device_register(&mcp->attached_device);
223 }
224 EXPORT_SYMBOL(mcp_host_register);
225
226 void mcp_host_unregister(struct mcp *mcp)
227 {
228         device_unregister(&mcp->attached_device);
229 }
230 EXPORT_SYMBOL(mcp_host_unregister);
231
232 int mcp_driver_register(struct mcp_driver *mcpdrv)
233 {
234         mcpdrv->drv.bus = &mcp_bus_type;
235         return driver_register(&mcpdrv->drv);
236 }
237 EXPORT_SYMBOL(mcp_driver_register);
238
239 void mcp_driver_unregister(struct mcp_driver *mcpdrv)
240 {
241         driver_unregister(&mcpdrv->drv);
242 }
243 EXPORT_SYMBOL(mcp_driver_unregister);
244
245 static int __init mcp_init(void)
246 {
247         return bus_register(&mcp_bus_type);
248 }
249
250 static void __exit mcp_exit(void)
251 {
252         bus_unregister(&mcp_bus_type);
253 }
254
255 module_init(mcp_init);
256 module_exit(mcp_exit);
257
258 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
259 MODULE_DESCRIPTION("Core multimedia communications port driver");
260 MODULE_LICENSE("GPL");