aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiam Girdwood <Liam.Girdwood@wolfsonmicro.com>2005-11-10 12:45:39 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-11-10 12:45:39 -0500
commitb216c01829d0b73a468204e2e763c0a818b77a46 (patch)
treeaac48ff212d96243a8101f3217882d13be30fe07
parent078abcf95cdb95c78d786dbc61ae3c22ee70fb61 (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>
-rw-r--r--arch/arm/mach-pxa/Kconfig7
-rw-r--r--arch/arm/mach-pxa/Makefile5
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c2
-rw-r--r--arch/arm/mach-pxa/ssp.c128
-rw-r--r--include/asm-arm/arch-pxa/ssp.h8
5 files changed, 58 insertions, 92 deletions
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index b380a438e68f..e201aa9765b9 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -60,6 +60,7 @@ config MACH_CORGI
60 bool "Enable Sharp SL-C700 (Corgi) Support" 60 bool "Enable Sharp SL-C700 (Corgi) Support"
61 depends PXA_SHARPSL_25x 61 depends PXA_SHARPSL_25x
62 select PXA_SHARP_C7xx 62 select PXA_SHARP_C7xx
63 select PXA_SSP
63 64
64config MACH_SHEPHERD 65config MACH_SHEPHERD
65 bool "Enable Sharp SL-C750 (Shepherd) Support" 66 bool "Enable Sharp SL-C750 (Shepherd) Support"
@@ -102,12 +103,18 @@ config IWMMXT
102 103
103config PXA_SHARP_C7xx 104config PXA_SHARP_C7xx
104 bool 105 bool
106 select PXA_SSP
105 help 107 help
106 Enable support for all Sharp C7xx models 108 Enable support for all Sharp C7xx models
107 109
108config PXA_SHARP_Cxx00 110config PXA_SHARP_Cxx00
109 bool 111 bool
112 select PXA_SSP
110 help 113 help
111 Enable common support for Sharp Cxx00 models 114 Enable common support for Sharp Cxx00 models
112 115
116config PXA_SSP
117 tristate
118 help
119 Enable support for PXA2xx SSP ports
113endif 120endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 8bc72d07cea8..d210bd5032ce 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -11,8 +11,8 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
11obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o 11obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
12obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o 12obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
13obj-$(CONFIG_ARCH_PXA_IDP) += idp.o 13obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
14obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o ssp.o 14obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o
15obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o ssp.o 15obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o
16obj-$(CONFIG_MACH_POODLE) += poodle.o 16obj-$(CONFIG_MACH_POODLE) += poodle.o
17obj-$(CONFIG_MACH_TOSA) += tosa.o 17obj-$(CONFIG_MACH_TOSA) += tosa.o
18 18
@@ -26,6 +26,7 @@ obj-$(CONFIG_LEDS) += $(led-y)
26 26
27# Misc features 27# Misc features
28obj-$(CONFIG_PM) += pm.o sleep.o 28obj-$(CONFIG_PM) += pm.o sleep.o
29obj-$(CONFIG_PXA_SSP) += ssp.o
29 30
30ifeq ($(CONFIG_PXA27x),y) 31ifeq ($(CONFIG_PXA27x),y)
31obj-$(CONFIG_PM) += standby.o 32obj-$(CONFIG_PM) += standby.o
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index 591e5f32dbec..bdf10cfa9440 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -203,7 +203,7 @@ static int __init corgi_ssp_probe(struct device *dev)
203 GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */ 203 GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */
204 GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ 204 GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
205 205
206 ret = ssp_init(&corgi_ssp_dev,ssp_machinfo->port); 206 ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
207 207
208 if (ret) 208 if (ret)
209 printk(KERN_ERR "Unable to register SSP handler!\n"); 209 printk(KERN_ERR "Unable to register SSP handler!\n");
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);
diff --git a/include/asm-arm/arch-pxa/ssp.h b/include/asm-arm/arch-pxa/ssp.h
index 6ec67b018c09..949878c0d908 100644
--- a/include/asm-arm/arch-pxa/ssp.h
+++ b/include/asm-arm/arch-pxa/ssp.h
@@ -18,6 +18,11 @@
18#ifndef SSP_H 18#ifndef SSP_H
19#define SSP_H 19#define SSP_H
20 20
21/*
22 * SSP initialisation flags
23 */
24#define SSP_NO_IRQ 0x1 /* don't register an irq handler in SSP driver */
25
21struct ssp_state { 26struct ssp_state {
22 u32 cr0; 27 u32 cr0;
23 u32 cr1; 28 u32 cr1;
@@ -31,6 +36,7 @@ struct ssp_dev {
31 u32 flags; 36 u32 flags;
32 u32 psp_flags; 37 u32 psp_flags;
33 u32 speed; 38 u32 speed;
39 int irq;
34}; 40};
35 41
36int ssp_write_word(struct ssp_dev *dev, u32 data); 42int ssp_write_word(struct ssp_dev *dev, u32 data);
@@ -40,7 +46,7 @@ void ssp_enable(struct ssp_dev *dev);
40void ssp_disable(struct ssp_dev *dev); 46void ssp_disable(struct ssp_dev *dev);
41void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp); 47void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp);
42void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp); 48void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp);
43int ssp_init(struct ssp_dev *dev, u32 port); 49int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags);
44int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed); 50int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed);
45void ssp_exit(struct ssp_dev *dev); 51void ssp_exit(struct ssp_dev *dev);
46 52