Delete all instances of asm/system.h
[linux-flexiantxendom0-3.2.10.git] / drivers / mfd / mcp-sa11x0.c
1 /*
2  *  linux/drivers/mfd/mcp-sa11x0.c
3  *
4  *  Copyright (C) 2001-2005 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  *  SA11x0 MCP (Multimedia Communications Port) driver.
11  *
12  *  MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
13  */
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/errno.h>
17 #include <linux/kernel.h>
18 #include <linux/delay.h>
19 #include <linux/spinlock.h>
20 #include <linux/platform_device.h>
21 #include <linux/mfd/mcp.h>
22
23 #include <mach/dma.h>
24 #include <mach/hardware.h>
25 #include <asm/mach-types.h>
26 #include <mach/mcp.h>
27
28 #include <mach/assabet.h>
29
30
31 struct mcp_sa11x0 {
32         u32     mccr0;
33         u32     mccr1;
34 };
35
36 #define priv(mcp)       ((struct mcp_sa11x0 *)mcp_priv(mcp))
37
38 static void
39 mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
40 {
41         unsigned int mccr0;
42
43         divisor /= 32;
44
45         mccr0 = Ser4MCCR0 & ~0x00007f00;
46         mccr0 |= divisor << 8;
47         Ser4MCCR0 = mccr0;
48 }
49
50 static void
51 mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
52 {
53         unsigned int mccr0;
54
55         divisor /= 32;
56
57         mccr0 = Ser4MCCR0 & ~0x0000007f;
58         mccr0 |= divisor;
59         Ser4MCCR0 = mccr0;
60 }
61
62 /*
63  * Write data to the device.  The bit should be set after 3 subframe
64  * times (each frame is 64 clocks).  We wait a maximum of 6 subframes.
65  * We really should try doing something more productive while we
66  * wait.
67  */
68 static void
69 mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
70 {
71         int ret = -ETIME;
72         int i;
73
74         Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
75
76         for (i = 0; i < 2; i++) {
77                 udelay(mcp->rw_timeout);
78                 if (Ser4MCSR & MCSR_CWC) {
79                         ret = 0;
80                         break;
81                 }
82         }
83
84         if (ret < 0)
85                 printk(KERN_WARNING "mcp: write timed out\n");
86 }
87
88 /*
89  * Read data from the device.  The bit should be set after 3 subframe
90  * times (each frame is 64 clocks).  We wait a maximum of 6 subframes.
91  * We really should try doing something more productive while we
92  * wait.
93  */
94 static unsigned int
95 mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
96 {
97         int ret = -ETIME;
98         int i;
99
100         Ser4MCDR2 = reg << 17 | MCDR2_Rd;
101
102         for (i = 0; i < 2; i++) {
103                 udelay(mcp->rw_timeout);
104                 if (Ser4MCSR & MCSR_CRC) {
105                         ret = Ser4MCDR2 & 0xffff;
106                         break;
107                 }
108         }
109
110         if (ret < 0)
111                 printk(KERN_WARNING "mcp: read timed out\n");
112
113         return ret;
114 }
115
116 static void mcp_sa11x0_enable(struct mcp *mcp)
117 {
118         Ser4MCSR = -1;
119         Ser4MCCR0 |= MCCR0_MCE;
120 }
121
122 static void mcp_sa11x0_disable(struct mcp *mcp)
123 {
124         Ser4MCCR0 &= ~MCCR0_MCE;
125 }
126
127 /*
128  * Our methods.
129  */
130 static struct mcp_ops mcp_sa11x0 = {
131         .set_telecom_divisor    = mcp_sa11x0_set_telecom_divisor,
132         .set_audio_divisor      = mcp_sa11x0_set_audio_divisor,
133         .reg_write              = mcp_sa11x0_write,
134         .reg_read               = mcp_sa11x0_read,
135         .enable                 = mcp_sa11x0_enable,
136         .disable                = mcp_sa11x0_disable,
137 };
138
139 static int mcp_sa11x0_probe(struct platform_device *pdev)
140 {
141         struct mcp_plat_data *data = pdev->dev.platform_data;
142         struct mcp *mcp;
143         int ret;
144
145         if (!data)
146                 return -ENODEV;
147
148         if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
149                 return -EBUSY;
150
151         mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
152         if (!mcp) {
153                 ret = -ENOMEM;
154                 goto release;
155         }
156
157         mcp->owner              = THIS_MODULE;
158         mcp->ops                = &mcp_sa11x0;
159         mcp->sclk_rate          = data->sclk_rate;
160         mcp->dma_audio_rd       = DMA_Ser4MCP0Rd;
161         mcp->dma_audio_wr       = DMA_Ser4MCP0Wr;
162         mcp->dma_telco_rd       = DMA_Ser4MCP1Rd;
163         mcp->dma_telco_wr       = DMA_Ser4MCP1Wr;
164         mcp->gpio_base          = data->gpio_base;
165
166         platform_set_drvdata(pdev, mcp);
167
168         if (machine_is_assabet()) {
169                 ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
170         }
171
172         /*
173          * Setup the PPC unit correctly.
174          */
175         PPDR &= ~PPC_RXD4;
176         PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
177         PSDR |= PPC_RXD4;
178         PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
179         PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
180
181         /*
182          * Initialise device.  Note that we initially
183          * set the sampling rate to minimum.
184          */
185         Ser4MCSR = -1;
186         Ser4MCCR1 = data->mccr1;
187         Ser4MCCR0 = data->mccr0 | 0x7f7f;
188
189         /*
190          * Calculate the read/write timeout (us) from the bit clock
191          * rate.  This is the period for 3 64-bit frames.  Always
192          * round this time up.
193          */
194         mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
195                           mcp->sclk_rate;
196
197         ret = mcp_host_register(mcp);
198         if (ret == 0)
199                 goto out;
200
201  release:
202         release_mem_region(0x80060000, 0x60);
203         platform_set_drvdata(pdev, NULL);
204
205  out:
206         return ret;
207 }
208
209 static int mcp_sa11x0_remove(struct platform_device *dev)
210 {
211         struct mcp *mcp = platform_get_drvdata(dev);
212
213         platform_set_drvdata(dev, NULL);
214         mcp_host_unregister(mcp);
215         release_mem_region(0x80060000, 0x60);
216
217         return 0;
218 }
219
220 static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
221 {
222         struct mcp *mcp = platform_get_drvdata(dev);
223
224         priv(mcp)->mccr0 = Ser4MCCR0;
225         priv(mcp)->mccr1 = Ser4MCCR1;
226         Ser4MCCR0 &= ~MCCR0_MCE;
227
228         return 0;
229 }
230
231 static int mcp_sa11x0_resume(struct platform_device *dev)
232 {
233         struct mcp *mcp = platform_get_drvdata(dev);
234
235         Ser4MCCR1 = priv(mcp)->mccr1;
236         Ser4MCCR0 = priv(mcp)->mccr0;
237
238         return 0;
239 }
240
241 /*
242  * The driver for the SA11x0 MCP port.
243  */
244 MODULE_ALIAS("platform:sa11x0-mcp");
245
246 static struct platform_driver mcp_sa11x0_driver = {
247         .probe          = mcp_sa11x0_probe,
248         .remove         = mcp_sa11x0_remove,
249         .suspend        = mcp_sa11x0_suspend,
250         .resume         = mcp_sa11x0_resume,
251         .driver         = {
252                 .name   = "sa11x0-mcp",
253         },
254 };
255
256 /*
257  * This needs re-working
258  */
259 module_platform_driver(mcp_sa11x0_driver);
260
261 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
262 MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
263 MODULE_LICENSE("GPL");