Root/
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 <asm/irq.h> |
23 | #include <mach/hardware.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 | |
35 | Ser4SSSR = SSSR_ROR; |
36 | |
37 | return status ? IRQ_HANDLED : IRQ_NONE; |
38 | } |
39 | |
40 | /** |
41 | * ssp_write_word - write a word to the SSP port |
42 | * @data: 16-bit, MSB justified data to write. |
43 | * |
44 | * Wait for a free entry in the SSP transmit FIFO, and write a data |
45 | * word to the SSP port. Wait for the SSP port to start sending |
46 | * the data. |
47 | * |
48 | * The caller is expected to perform the necessary locking. |
49 | * |
50 | * Returns: |
51 | * %-ETIMEDOUT timeout occurred |
52 | * 0 success |
53 | */ |
54 | int ssp_write_word(u16 data) |
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 | |
76 | /** |
77 | * ssp_read_word - read a word from the SSP port |
78 | * |
79 | * Wait for a data word in the SSP receive FIFO, and return the |
80 | * received data. Data is LSB justified. |
81 | * |
82 | * Note: Currently, if data is not expected to be received, this |
83 | * function will wait for ever. |
84 | * |
85 | * The caller is expected to perform the necessary locking. |
86 | * |
87 | * Returns: |
88 | * %-ETIMEDOUT timeout occurred |
89 | * 16-bit data success |
90 | */ |
91 | int ssp_read_word(u16 *data) |
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 | |
106 | /** |
107 | * ssp_flush - flush the transmit and receive FIFOs |
108 | * |
109 | * Wait for the SSP to idle, and ensure that the receive FIFO |
110 | * is empty. |
111 | * |
112 | * The caller is expected to perform the necessary locking. |
113 | * |
114 | * Returns: |
115 | * %-ETIMEDOUT timeout occurred |
116 | * 0 success |
117 | */ |
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 | |
135 | /** |
136 | * ssp_enable - enable the SSP port |
137 | * |
138 | * Turn on the SSP port. |
139 | */ |
140 | void ssp_enable(void) |
141 | { |
142 | Ser4SSCR0 |= SSCR0_SSE; |
143 | } |
144 | |
145 | /** |
146 | * ssp_disable - shut down the SSP port |
147 | * |
148 | * Turn off the SSP port, optionally powering it down. |
149 | */ |
150 | void ssp_disable(void) |
151 | { |
152 | Ser4SSCR0 &= ~SSCR0_SSE; |
153 | } |
154 | |
155 | /** |
156 | * ssp_save_state - save the SSP configuration |
157 | * @ssp: pointer to structure to save SSP configuration |
158 | * |
159 | * Save the configured SSP state for suspend. |
160 | */ |
161 | void ssp_save_state(struct ssp_state *ssp) |
162 | { |
163 | ssp->cr0 = Ser4SSCR0; |
164 | ssp->cr1 = Ser4SSCR1; |
165 | |
166 | Ser4SSCR0 &= ~SSCR0_SSE; |
167 | } |
168 | |
169 | /** |
170 | * ssp_restore_state - restore a previously saved SSP configuration |
171 | * @ssp: pointer to configuration saved by ssp_save_state |
172 | * |
173 | * Restore the SSP configuration saved previously by ssp_save_state. |
174 | */ |
175 | void ssp_restore_state(struct ssp_state *ssp) |
176 | { |
177 | Ser4SSSR = SSSR_ROR; |
178 | |
179 | Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE; |
180 | Ser4SSCR1 = ssp->cr1; |
181 | Ser4SSCR0 = ssp->cr0; |
182 | } |
183 | |
184 | /** |
185 | * ssp_init - setup the SSP port |
186 | * |
187 | * initialise and claim resources for the SSP port. |
188 | * |
189 | * Returns: |
190 | * %-ENODEV if the SSP port is unavailable |
191 | * %-EBUSY if the resources are already in use |
192 | * %0 on success |
193 | */ |
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: |
214 | release_mem_region(__PREG(Ser4SSCR0), 0x18); |
215 | return ret; |
216 | } |
217 | |
218 | /** |
219 | * ssp_exit - undo the effects of ssp_init |
220 | * |
221 | * release and free resources for the SSP port. |
222 | */ |
223 | void ssp_exit(void) |
224 | { |
225 | Ser4SSCR0 &= ~SSCR0_SSE; |
226 | |
227 | free_irq(IRQ_Ser4SSP, NULL); |
228 | release_mem_region(__PREG(Ser4SSCR0), 0x18); |
229 | } |
230 | |
231 | MODULE_AUTHOR("Russell King"); |
232 | MODULE_DESCRIPTION("SA11x0 SSP PIO driver"); |
233 | MODULE_LICENSE("GPL"); |
234 | |
235 | EXPORT_SYMBOL(ssp_write_word); |
236 | EXPORT_SYMBOL(ssp_read_word); |
237 | EXPORT_SYMBOL(ssp_flush); |
238 | EXPORT_SYMBOL(ssp_enable); |
239 | EXPORT_SYMBOL(ssp_disable); |
240 | EXPORT_SYMBOL(ssp_save_state); |
241 | EXPORT_SYMBOL(ssp_restore_state); |
242 | EXPORT_SYMBOL(ssp_init); |
243 | EXPORT_SYMBOL(ssp_exit); |
244 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9