Linux-2.6.12-rc2
[pandora-kernel.git] / arch / arm / mach-pxa / ssp.c
1 /*
2  *  linux/arch/arm/mach-pxa/ssp.c
3  *
4  *  based on linux/arch/arm/mach-sa1100/ssp.c by Russell King
5  *
6  *  Copyright (C) 2003 Russell King.
7  *  Copyright (C) 2003 Wolfson Microelectronics PLC
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  *  PXA2xx SSP driver.  This provides the generic core for simple
14  *  IO-based SSP applications and allows easy port setup for DMA access.
15  *
16  *  Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
17  *
18  *  Revision history:
19  *   22nd Aug 2003 Initial version.
20  *   20th Dec 2004 Added ssp_config for changing port config without
21  *                 closing the port.
22  */
23
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/slab.h>
28 #include <linux/errno.h>
29 #include <linux/interrupt.h>
30 #include <linux/ioport.h>
31 #include <linux/init.h>
32 #include <asm/io.h>
33 #include <asm/irq.h>
34 #include <asm/hardware.h>
35 #include <asm/arch/ssp.h>
36 #include <asm/arch/pxa-regs.h>
37
38 #define PXA_SSP_PORTS   3
39
40 static DECLARE_MUTEX(sem);
41 static int use_count[PXA_SSP_PORTS] = {0, 0, 0};
42
43 static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
44 {
45         struct ssp_dev *dev = (struct ssp_dev*) dev_id;
46         unsigned int status = SSSR_P(dev->port);
47
48         SSSR_P(dev->port) = status; /* clear status bits */
49
50         if (status & SSSR_ROR)
51                 printk(KERN_WARNING "SSP(%d): receiver overrun\n", dev->port);
52
53         if (status & SSSR_TUR)
54                 printk(KERN_WARNING "SSP(%d): transmitter underrun\n", dev->port);
55
56         if (status & SSSR_BCE)
57                 printk(KERN_WARNING "SSP(%d): bit count error\n", dev->port);
58
59         return IRQ_HANDLED;
60 }
61
62 /**
63  * ssp_write_word - write a word to the SSP port
64  * @data: 32-bit, MSB justified data to write.
65  *
66  * Wait for a free entry in the SSP transmit FIFO, and write a data
67  * word to the SSP port.
68  *
69  * The caller is expected to perform the necessary locking.
70  *
71  * Returns:
72  *   %-ETIMEDOUT        timeout occurred (for future)
73  *   0                  success
74  */
75 int ssp_write_word(struct ssp_dev *dev, u32 data)
76 {
77         while (!(SSSR_P(dev->port) & SSSR_TNF))
78                 cpu_relax();
79
80         SSDR_P(dev->port) = data;
81
82         return 0;
83 }
84
85 /**
86  * ssp_read_word - read a word from the SSP port
87  *
88  * Wait for a data word in the SSP receive FIFO, and return the
89  * received data.  Data is LSB justified.
90  *
91  * Note: Currently, if data is not expected to be received, this
92  * function will wait for ever.
93  *
94  * The caller is expected to perform the necessary locking.
95  *
96  * Returns:
97  *   %-ETIMEDOUT        timeout occurred (for future)
98  *   32-bit data        success
99  */
100 int ssp_read_word(struct ssp_dev *dev)
101 {
102         while (!(SSSR_P(dev->port) & SSSR_RNE))
103                 cpu_relax();
104
105         return SSDR_P(dev->port);
106 }
107
108 /**
109  * ssp_flush - flush the transmit and receive FIFOs
110  *
111  * Wait for the SSP to idle, and ensure that the receive FIFO
112  * is empty.
113  *
114  * The caller is expected to perform the necessary locking.
115  */
116 void ssp_flush(struct ssp_dev *dev)
117 {
118         do {
119                 while (SSSR_P(dev->port) & SSSR_RNE) {
120                         (void) SSDR_P(dev->port);
121                 }
122         } while (SSSR_P(dev->port) & SSSR_BSY);
123 }
124
125 /**
126  * ssp_enable - enable the SSP port
127  *
128  * Turn on the SSP port.
129  */
130 void ssp_enable(struct ssp_dev *dev)
131 {
132         SSCR0_P(dev->port) |= SSCR0_SSE;
133 }
134
135 /**
136  * ssp_disable - shut down the SSP port
137  *
138  * Turn off the SSP port, optionally powering it down.
139  */
140 void ssp_disable(struct ssp_dev *dev)
141 {
142         SSCR0_P(dev->port) &= ~SSCR0_SSE;
143 }
144
145 /**
146  * ssp_save_state - save the SSP configuration
147  * @ssp: pointer to structure to save SSP configuration
148  *
149  * Save the configured SSP state for suspend.
150  */
151 void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp)
152 {
153         ssp->cr0 = SSCR0_P(dev->port);
154         ssp->cr1 = SSCR1_P(dev->port);
155         ssp->to = SSTO_P(dev->port);
156         ssp->psp = SSPSP_P(dev->port);
157
158         SSCR0_P(dev->port) &= ~SSCR0_SSE;
159 }
160
161 /**
162  * ssp_restore_state - restore a previously saved SSP configuration
163  * @ssp: pointer to configuration saved by ssp_save_state
164  *
165  * Restore the SSP configuration saved previously by ssp_save_state.
166  */
167 void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp)
168 {
169         SSSR_P(dev->port) = SSSR_ROR | SSSR_TUR | SSSR_BCE;
170
171         SSCR0_P(dev->port) = ssp->cr0 & ~SSCR0_SSE;
172         SSCR1_P(dev->port) = ssp->cr1;
173         SSTO_P(dev->port) = ssp->to;
174         SSPSP_P(dev->port) = ssp->psp;
175
176         SSCR0_P(dev->port) = ssp->cr0;
177 }
178
179 /**
180  * ssp_config - configure SSP port settings
181  * @mode: port operating mode
182  * @flags: port config flags
183  * @psp_flags: port PSP config flags
184  * @speed: port speed
185  *
186  * Port MUST be disabled by ssp_disable before making any config changes.
187  */
188 int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed)
189 {
190         dev->mode = mode;
191         dev->flags = flags;
192         dev->psp_flags = psp_flags;
193         dev->speed = speed;
194
195         /* set up port type, speed, port settings */
196         SSCR0_P(dev->port) = (dev->speed | dev->mode);
197         SSCR1_P(dev->port) = dev->flags;
198         SSPSP_P(dev->port) = dev->psp_flags;
199
200         return 0;
201 }
202
203 /**
204  * ssp_init - setup the SSP port
205  *
206  * initialise and claim resources for the SSP port.
207  *
208  * Returns:
209  *   %-ENODEV   if the SSP port is unavailable
210  *   %-EBUSY    if the resources are already in use
211  *   %0         on success
212  */
213 int ssp_init(struct ssp_dev *dev, u32 port)
214 {
215         int ret, irq;
216
217         if (port > PXA_SSP_PORTS || port == 0)
218                 return -ENODEV;
219
220         down(&sem);
221         if (use_count[port - 1]) {
222                 up(&sem);
223                 return -EBUSY;
224         }
225         use_count[port - 1]++;
226
227         if (!request_mem_region(__PREG(SSCR0_P(port)), 0x2c, "SSP")) {
228                 use_count[port - 1]--;
229                 up(&sem);
230                 return -EBUSY;
231         }
232
233         switch (port) {
234                 case 1:
235                         irq = IRQ_SSP;
236                         break;
237 #if defined (CONFIG_PXA27x)
238                 case 2:
239                         irq = IRQ_SSP2;
240                         break;
241                 case 3:
242                         irq = IRQ_SSP3;
243                         break;
244 #else
245                 case 2:
246                         irq = IRQ_NSSP;
247                         break;
248                 case 3:
249                         irq = IRQ_ASSP;
250                         break;
251 #endif
252                 default:
253                         return -ENODEV;
254         }
255
256         dev->port = port;
257
258         ret = request_irq(irq, ssp_interrupt, 0, "SSP", dev);
259         if (ret)
260                 goto out_region;
261
262         /* turn on SSP port clock */
263         switch (dev->port) {
264 #if defined (CONFIG_PXA27x)
265                 case 1:
266                         pxa_set_cken(CKEN23_SSP1, 1);
267                         break;
268                 case 2:
269                         pxa_set_cken(CKEN3_SSP2, 1);
270                         break;
271                 case 3:
272                         pxa_set_cken(CKEN4_SSP3, 1);
273                         break;
274 #else
275                 case 1:
276                         pxa_set_cken(CKEN3_SSP, 1);
277                         break;
278                 case 2:
279                         pxa_set_cken(CKEN9_NSSP, 1);
280                         break;
281                 case 3:
282                         pxa_set_cken(CKEN10_ASSP, 1);
283                         break;
284 #endif
285         }
286
287         up(&sem);
288         return 0;
289
290 out_region:
291         release_mem_region(__PREG(SSCR0_P(port)), 0x2c);
292         use_count[port - 1]--;
293         up(&sem);
294         return ret;
295 }
296
297 /**
298  * ssp_exit - undo the effects of ssp_init
299  *
300  * release and free resources for the SSP port.
301  */
302 void ssp_exit(struct ssp_dev *dev)
303 {
304         int irq;
305
306         down(&sem);
307         SSCR0_P(dev->port) &= ~SSCR0_SSE;
308
309         /* find irq, save power and turn off SSP port clock */
310         switch (dev->port) {
311 #if defined (CONFIG_PXA27x)
312                 case 1:
313                         irq = IRQ_SSP;
314                         pxa_set_cken(CKEN23_SSP1, 0);
315                         break;
316                 case 2:
317                         irq = IRQ_SSP2;
318                         pxa_set_cken(CKEN3_SSP2, 0);
319                         break;
320                 case 3:
321                         irq = IRQ_SSP3;
322                         pxa_set_cken(CKEN4_SSP3, 0);
323                         break;
324 #else
325                 case 1:
326                         irq = IRQ_SSP;
327                         pxa_set_cken(CKEN3_SSP, 0);
328                         break;
329                 case 2:
330                         irq = IRQ_NSSP;
331                         pxa_set_cken(CKEN9_NSSP, 0);
332                         break;
333                 case 3:
334                         irq = IRQ_ASSP;
335                         pxa_set_cken(CKEN10_ASSP, 0);
336                         break;
337 #endif
338                 default:
339                         printk(KERN_WARNING "SSP: tried to close invalid port\n");
340                         return;
341         }
342
343         free_irq(irq, dev);
344         release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c);
345         use_count[dev->port - 1]--;
346         up(&sem);
347 }
348
349 EXPORT_SYMBOL(ssp_write_word);
350 EXPORT_SYMBOL(ssp_read_word);
351 EXPORT_SYMBOL(ssp_flush);
352 EXPORT_SYMBOL(ssp_enable);
353 EXPORT_SYMBOL(ssp_disable);
354 EXPORT_SYMBOL(ssp_save_state);
355 EXPORT_SYMBOL(ssp_restore_state);
356 EXPORT_SYMBOL(ssp_init);
357 EXPORT_SYMBOL(ssp_exit);
358 EXPORT_SYMBOL(ssp_config);
359
360 MODULE_DESCRIPTION("PXA SSP driver");
361 MODULE_AUTHOR("Liam Girdwood");
362 MODULE_LICENSE("GPL");
363