diff options
author | Liam Girdwood <Liam.Girdwood@wolfsonmicro.com> | 2005-11-10 12:45:39 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-11-10 12:45:39 -0500 |
commit | b216c01829d0b73a468204e2e763c0a818b77a46 (patch) | |
tree | aac48ff212d96243a8101f3217882d13be30fe07 /arch/arm/mach-pxa/ssp.c | |
parent | 078abcf95cdb95c78d786dbc61ae3c22ee70fb61 (diff) |
[ARM] 3098/1: pxa2xx disable ssp irq
Patch from Liam Girdwood
This patch allows users of the pxa SSP driver to register their own irq
handlers instead of using the default SSP handler. It also cleans up the
CKEN clock and irq detection as the values are now stored in a table.
This patch replaces 2845/1
Changes:-
o Added flags parameter to ssp_init()
o Added SSP_NO_IRQ flag to disable registering of ssp irq handler (for
drivers that want to register their own handler)
o Cleaned up clock and irq detection, values are now stored in table.
o Added build changes to allow other drivers (e.g audio) to select the
ssp driver.
o corgi_ssp.c changed to use new interface.
Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-pxa/ssp.c')
-rw-r--r-- | arch/arm/mach-pxa/ssp.c | 128 |
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 | ||
42 | struct ssp_info_ { | ||
43 | int irq; | ||
44 | u32 clock; | ||
45 | }; | ||
46 | |||
47 | /* | ||
48 | * SSP port clock and IRQ settings | ||
49 | */ | ||
50 | static 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 | |||
40 | static DECLARE_MUTEX(sem); | 62 | static DECLARE_MUTEX(sem); |
41 | static int use_count[PXA_SSP_PORTS] = {0, 0, 0}; | 63 | static 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 | */ |
213 | int ssp_init(struct ssp_dev *dev, u32 port) | 235 | int 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 | */ |
302 | void ssp_exit(struct ssp_dev *dev) | 283 | void 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); |