aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/ssp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-pxa/ssp.c')
-rw-r--r--arch/arm/mach-pxa/ssp.c128
1 files changed, 40 insertions, 88 deletions
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index 4d826c021315..a68b30eff4d2 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -19,6 +19,8 @@
19 * 22nd Aug 2003 Initial version. 19 * 22nd Aug 2003 Initial version.
20 * 20th Dec 2004 Added ssp_config for changing port config without 20 * 20th Dec 2004 Added ssp_config for changing port config without
21 * closing the port. 21 * closing the port.
22 * 4th Aug 2005 Added option to disable irq handler registration and
23 * cleaned up irq and clock detection.
22 */ 24 */
23 25
24#include <linux/module.h> 26#include <linux/module.h>
@@ -37,6 +39,26 @@
37 39
38#define PXA_SSP_PORTS 3 40#define PXA_SSP_PORTS 3
39 41
42struct ssp_info_ {
43 int irq;
44 u32 clock;
45};
46
47/*
48 * SSP port clock and IRQ settings
49 */
50static const struct ssp_info_ ssp_info[PXA_SSP_PORTS] = {
51#if defined (CONFIG_PXA27x)
52 {IRQ_SSP, CKEN23_SSP1},
53 {IRQ_SSP2, CKEN3_SSP2},
54 {IRQ_SSP3, CKEN4_SSP3},
55#else
56 {IRQ_SSP, CKEN3_SSP},
57 {IRQ_NSSP, CKEN9_NSSP},
58 {IRQ_ASSP, CKEN10_ASSP},
59#endif
60};
61
40static DECLARE_MUTEX(sem); 62static DECLARE_MUTEX(sem);
41static int use_count[PXA_SSP_PORTS] = {0, 0, 0}; 63static int use_count[PXA_SSP_PORTS] = {0, 0, 0};
42 64
@@ -210,9 +232,9 @@ int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 spee
210 * %-EBUSY if the resources are already in use 232 * %-EBUSY if the resources are already in use
211 * %0 on success 233 * %0 on success
212 */ 234 */
213int ssp_init(struct ssp_dev *dev, u32 port) 235int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags)
214{ 236{
215 int ret, irq; 237 int ret;
216 238
217 if (port > PXA_SSP_PORTS || port == 0) 239 if (port > PXA_SSP_PORTS || port == 0)
218 return -ENODEV; 240 return -ENODEV;
@@ -229,61 +251,20 @@ int ssp_init(struct ssp_dev *dev, u32 port)
229 up(&sem); 251 up(&sem);
230 return -EBUSY; 252 return -EBUSY;
231 } 253 }
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; 254 dev->port = port;
257 255
258 ret = request_irq(irq, ssp_interrupt, 0, "SSP", dev); 256 /* do we need to get irq */
259 if (ret) 257 if (!(init_flags & SSP_NO_IRQ)) {
260 goto out_region; 258 ret = request_irq(ssp_info[port-1].irq, ssp_interrupt,
259 0, "SSP", dev);
260 if (ret)
261 goto out_region;
262 dev->irq = ssp_info[port-1].irq;
263 } else
264 dev->irq = 0;
261 265
262 /* turn on SSP port clock */ 266 /* turn on SSP port clock */
263 switch (dev->port) { 267 pxa_set_cken(ssp_info[port-1].clock, 1);
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); 268 up(&sem);
288 return 0; 269 return 0;
289 270
@@ -301,46 +282,17 @@ out_region:
301 */ 282 */
302void ssp_exit(struct ssp_dev *dev) 283void ssp_exit(struct ssp_dev *dev)
303{ 284{
304 int irq;
305
306 down(&sem); 285 down(&sem);
307 SSCR0_P(dev->port) &= ~SSCR0_SSE; 286 SSCR0_P(dev->port) &= ~SSCR0_SSE;
308 287
309 /* find irq, save power and turn off SSP port clock */ 288 if (dev->port > PXA_SSP_PORTS || dev->port == 0) {
310 switch (dev->port) { 289 printk(KERN_WARNING "SSP: tried to close invalid port\n");
311#if defined (CONFIG_PXA27x) 290 return;
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 } 291 }
342 292
343 free_irq(irq, dev); 293 pxa_set_cken(ssp_info[dev->port-1].clock, 0);
294 if (dev->irq)
295 free_irq(dev->irq, dev);
344 release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c); 296 release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c);
345 use_count[dev->port - 1]--; 297 use_count[dev->port - 1]--;
346 up(&sem); 298 up(&sem);