[ARM] 3098/1: pxa2xx disable ssp irq
authorLiam Girdwood <Liam.Girdwood@wolfsonmicro.com>
Thu, 10 Nov 2005 17:45:39 +0000 (17:45 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 10 Nov 2005 17:45:39 +0000 (17:45 +0000)
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>
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/corgi_ssp.c
arch/arm/mach-pxa/ssp.c
include/asm-arm/arch-pxa/ssp.h

index b380a438e68f0b02f7b68c8fc0b65c1fea09ed72..e201aa9765b9c0bc8ee15e87d45bd80393a4075d 100644 (file)
@@ -60,6 +60,7 @@ config MACH_CORGI
        bool "Enable Sharp SL-C700 (Corgi) Support"
        depends PXA_SHARPSL_25x
        select PXA_SHARP_C7xx
+       select PXA_SSP
 
 config MACH_SHEPHERD
        bool "Enable Sharp SL-C750 (Shepherd) Support"
@@ -102,12 +103,18 @@ config IWMMXT
 
 config PXA_SHARP_C7xx
        bool
+       select PXA_SSP
        help
          Enable support for all Sharp C7xx models
 
 config PXA_SHARP_Cxx00
        bool
+       select PXA_SSP
        help
          Enable common support for Sharp Cxx00 models
 
+config PXA_SSP
+       tristate
+       help
+         Enable support for PXA2xx SSP ports
 endif
index 8bc72d07cea8cca432a635e077cb50a84bf23514..d210bd5032ced956d0eed5da63e2be025e857d15 100644 (file)
@@ -11,8 +11,8 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
 obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
 obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
 obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
-obj-$(CONFIG_PXA_SHARP_C7xx)   += corgi.o corgi_ssp.o corgi_lcd.o ssp.o
-obj-$(CONFIG_PXA_SHARP_Cxx00)  += spitz.o corgi_ssp.o corgi_lcd.o ssp.o
+obj-$(CONFIG_PXA_SHARP_C7xx)   += corgi.o corgi_ssp.o corgi_lcd.o
+obj-$(CONFIG_PXA_SHARP_Cxx00)  += spitz.o corgi_ssp.o corgi_lcd.o
 obj-$(CONFIG_MACH_POODLE)      += poodle.o
 obj-$(CONFIG_MACH_TOSA)         += tosa.o
 
@@ -26,6 +26,7 @@ obj-$(CONFIG_LEDS) += $(led-y)
 
 # Misc features
 obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_PXA_SSP) += ssp.o
 
 ifeq ($(CONFIG_PXA27x),y)
 obj-$(CONFIG_PM) += standby.o
index 591e5f32dbeccdb726ab491b31d080f60376b54b..bdf10cfa94407763b2c46a99d71dc31d7fcaf159 100644 (file)
@@ -203,7 +203,7 @@ static int __init corgi_ssp_probe(struct device *dev)
        GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846);  /* output */
        GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);   /* High - Disable ADS7846*/
 
-       ret = ssp_init(&corgi_ssp_dev,ssp_machinfo->port);
+       ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
 
        if (ret)
                printk(KERN_ERR "Unable to register SSP handler!\n");
index 4d826c02131521b78a97cf022514e7c6c7e5db3e..a68b30eff4d26180c24e4ed44545980f04188d64 100644 (file)
@@ -19,6 +19,8 @@
  *   22nd Aug 2003 Initial version.
  *   20th Dec 2004 Added ssp_config for changing port config without
  *                 closing the port.
+ *    4th Aug 2005 Added option to disable irq handler registration and
+ *                 cleaned up irq and clock detection.
  */
 
 #include <linux/module.h>
 
 #define PXA_SSP_PORTS  3
 
+struct ssp_info_ {
+       int irq;
+       u32 clock;
+};
+
+/*
+ * SSP port clock and IRQ settings
+ */
+static const struct ssp_info_ ssp_info[PXA_SSP_PORTS] = {
+#if defined (CONFIG_PXA27x)
+       {IRQ_SSP,       CKEN23_SSP1},
+       {IRQ_SSP2,      CKEN3_SSP2},
+       {IRQ_SSP3,      CKEN4_SSP3},
+#else
+       {IRQ_SSP,       CKEN3_SSP},
+       {IRQ_NSSP,      CKEN9_NSSP},
+       {IRQ_ASSP,      CKEN10_ASSP},
+#endif
+};
+
 static DECLARE_MUTEX(sem);
 static int use_count[PXA_SSP_PORTS] = {0, 0, 0};
 
@@ -210,9 +232,9 @@ int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 spee
  *   %-EBUSY   if the resources are already in use
  *   %0                on success
  */
-int ssp_init(struct ssp_dev *dev, u32 port)
+int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags)
 {
-       int ret, irq;
+       int ret;
 
        if (port > PXA_SSP_PORTS || port == 0)
                return -ENODEV;
@@ -229,61 +251,20 @@ int ssp_init(struct ssp_dev *dev, u32 port)
                up(&sem);
                return -EBUSY;
        }
-
-       switch (port) {
-               case 1:
-                       irq = IRQ_SSP;
-                       break;
-#if defined (CONFIG_PXA27x)
-               case 2:
-                       irq = IRQ_SSP2;
-                       break;
-               case 3:
-                       irq = IRQ_SSP3;
-                       break;
-#else
-               case 2:
-                       irq = IRQ_NSSP;
-                       break;
-               case 3:
-                       irq = IRQ_ASSP;
-                       break;
-#endif
-               default:
-                       return -ENODEV;
-       }
-
        dev->port = port;
 
-       ret = request_irq(irq, ssp_interrupt, 0, "SSP", dev);
-       if (ret)
-               goto out_region;
+       /* do we need to get irq */
+       if (!(init_flags & SSP_NO_IRQ)) {
+               ret = request_irq(ssp_info[port-1].irq, ssp_interrupt,
+                               0, "SSP", dev);
+               if (ret)
+                       goto out_region;
+               dev->irq = ssp_info[port-1].irq;
+       } else
+               dev->irq = 0;
 
        /* turn on SSP port clock */
-       switch (dev->port) {
-#if defined (CONFIG_PXA27x)
-               case 1:
-                       pxa_set_cken(CKEN23_SSP1, 1);
-                       break;
-               case 2:
-                       pxa_set_cken(CKEN3_SSP2, 1);
-                       break;
-               case 3:
-                       pxa_set_cken(CKEN4_SSP3, 1);
-                       break;
-#else
-               case 1:
-                       pxa_set_cken(CKEN3_SSP, 1);
-                       break;
-               case 2:
-                       pxa_set_cken(CKEN9_NSSP, 1);
-                       break;
-               case 3:
-                       pxa_set_cken(CKEN10_ASSP, 1);
-                       break;
-#endif
-       }
-
+       pxa_set_cken(ssp_info[port-1].clock, 1);
        up(&sem);
        return 0;
 
@@ -301,46 +282,17 @@ out_region:
  */
 void ssp_exit(struct ssp_dev *dev)
 {
-       int irq;
-
        down(&sem);
        SSCR0_P(dev->port) &= ~SSCR0_SSE;
 
-       /* find irq, save power and turn off SSP port clock */
-       switch (dev->port) {
-#if defined (CONFIG_PXA27x)
-               case 1:
-                       irq = IRQ_SSP;
-                       pxa_set_cken(CKEN23_SSP1, 0);
-                       break;
-               case 2:
-                       irq = IRQ_SSP2;
-                       pxa_set_cken(CKEN3_SSP2, 0);
-                       break;
-               case 3:
-                       irq = IRQ_SSP3;
-                       pxa_set_cken(CKEN4_SSP3, 0);
-                       break;
-#else
-               case 1:
-                       irq = IRQ_SSP;
-                       pxa_set_cken(CKEN3_SSP, 0);
-                       break;
-               case 2:
-                       irq = IRQ_NSSP;
-                       pxa_set_cken(CKEN9_NSSP, 0);
-                       break;
-               case 3:
-                       irq = IRQ_ASSP;
-                       pxa_set_cken(CKEN10_ASSP, 0);
-                       break;
-#endif
-               default:
-                       printk(KERN_WARNING "SSP: tried to close invalid port\n");
-                       return;
+       if (dev->port > PXA_SSP_PORTS || dev->port == 0) {
+               printk(KERN_WARNING "SSP: tried to close invalid port\n");
+               return;
        }
 
-       free_irq(irq, dev);
+       pxa_set_cken(ssp_info[dev->port-1].clock, 0);
+       if (dev->irq)
+               free_irq(dev->irq, dev);
        release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c);
        use_count[dev->port - 1]--;
        up(&sem);
index 6ec67b018c09d20928da60610111a447f65adb26..949878c0d9082754f76847b9da221bbbba91a70c 100644 (file)
 #ifndef SSP_H
 #define SSP_H
 
+/*
+ * SSP initialisation flags
+ */
+#define SSP_NO_IRQ     0x1             /* don't register an irq handler in SSP driver */
+
 struct ssp_state {
        u32     cr0;
        u32 cr1;
@@ -31,6 +36,7 @@ struct ssp_dev {
        u32 flags;
        u32 psp_flags;
        u32 speed;
+       int irq;
 };
 
 int ssp_write_word(struct ssp_dev *dev, u32 data);
@@ -40,7 +46,7 @@ void ssp_enable(struct ssp_dev *dev);
 void ssp_disable(struct ssp_dev *dev);
 void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp);
 void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp);
-int ssp_init(struct ssp_dev *dev, u32 port);
+int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags);
 int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed);
 void ssp_exit(struct ssp_dev *dev);