Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ssp.c
Go to the documentation of this file.
1 /*
2  * linux/arch/arm/mach-sa1100/ssp.c
3  *
4  * Copyright (C) 2003 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 version 2 as
8  * published by the Free Software Foundation.
9  *
10  * Generic SSP driver. This provides the generic core for simple
11  * IO-based SSP applications.
12  */
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/sched.h>
16 #include <linux/errno.h>
17 #include <linux/interrupt.h>
18 #include <linux/ioport.h>
19 #include <linux/init.h>
20 #include <linux/io.h>
21 
22 #include <mach/hardware.h>
23 #include <mach/irqs.h>
24 #include <asm/hardware/ssp.h>
25 
26 #define TIMEOUT 100000
27 
28 static irqreturn_t ssp_interrupt(int irq, void *dev_id)
29 {
30  unsigned int status = Ser4SSSR;
31 
32  if (status & SSSR_ROR)
33  printk(KERN_WARNING "SSP: receiver overrun\n");
34 
36 
37  return status ? IRQ_HANDLED : IRQ_NONE;
38 }
39 
55 {
56  int timeout = TIMEOUT;
57 
58  while (!(Ser4SSSR & SSSR_TNF)) {
59  if (!--timeout)
60  return -ETIMEDOUT;
61  cpu_relax();
62  }
63 
64  Ser4SSDR = data;
65 
66  timeout = TIMEOUT;
67  while (!(Ser4SSSR & SSSR_BSY)) {
68  if (!--timeout)
69  return -ETIMEDOUT;
70  cpu_relax();
71  }
72 
73  return 0;
74 }
75 
92 {
93  int timeout = TIMEOUT;
94 
95  while (!(Ser4SSSR & SSSR_RNE)) {
96  if (!--timeout)
97  return -ETIMEDOUT;
98  cpu_relax();
99  }
100 
101  *data = (u16)Ser4SSDR;
102 
103  return 0;
104 }
105 
118 int ssp_flush(void)
119 {
120  int timeout = TIMEOUT * 2;
121 
122  do {
123  while (Ser4SSSR & SSSR_RNE) {
124  if (!--timeout)
125  return -ETIMEDOUT;
126  (void) Ser4SSDR;
127  }
128  if (!--timeout)
129  return -ETIMEDOUT;
130  } while (Ser4SSSR & SSSR_BSY);
131 
132  return 0;
133 }
134 
140 void ssp_enable(void)
141 {
142  Ser4SSCR0 |= SSCR0_SSE;
143 }
144 
150 void ssp_disable(void)
151 {
152  Ser4SSCR0 &= ~SSCR0_SSE;
153 }
154 
162 {
163  ssp->cr0 = Ser4SSCR0;
164  ssp->cr1 = Ser4SSCR1;
165 
166  Ser4SSCR0 &= ~SSCR0_SSE;
167 }
168 
176 {
177  Ser4SSSR = SSSR_ROR;
178 
179  Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE;
180  Ser4SSCR1 = ssp->cr1;
181  Ser4SSCR0 = ssp->cr0;
182 }
183 
194 int ssp_init(void)
195 {
196  int ret;
197 
198  if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE))
199  return -ENODEV;
200 
201  if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) {
202  return -EBUSY;
203  }
204 
205  Ser4SSSR = SSSR_ROR;
206 
207  ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL);
208  if (ret)
209  goto out_region;
210 
211  return 0;
212 
213  out_region:
215  return ret;
216 }
217 
223 void ssp_exit(void)
224 {
225  Ser4SSCR0 &= ~SSCR0_SSE;
226 
229 }
230 
231 MODULE_AUTHOR("Russell King");
232 MODULE_DESCRIPTION("SA11x0 SSP PIO driver");
233 MODULE_LICENSE("GPL");
234