changed Makefile and profiles, added patches for kernel 2.6.24 (stable-branch of...
[openwrt/openwrt.git] / target / linux / s3c24xx / patches / 0045-introduce-fiq-basis.patch.patch
diff --git a/target/linux/s3c24xx/patches/0045-introduce-fiq-basis.patch.patch b/target/linux/s3c24xx/patches/0045-introduce-fiq-basis.patch.patch
deleted file mode 100755 (executable)
index 7b79d8e..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-From 6a2c7de90f47b7eb74f3cb2d181f950ece22b3fb Mon Sep 17 00:00:00 2001
-From: mokopatches <mokopatches@openmoko.org>
-Date: Fri, 25 Jul 2008 22:21:22 +0100
-Subject: [PATCH] introduce-fiq-basis.patch
- Adds a C-based FIQ ISR which is very convenient (and unusual --
- normally you have to do FIQ ISR in assembler only).
- Based on my article:
-
-http://warmcat.com/_wp/2007/09/17/at91rm9200-fiq-faq-and-simple-example-code-patch/
-
-Implemented as a platform device and driver.
-
-Suspend / resume is tested and works.
-
-Signed-off-by: Andy Green <andy@warmcat.com>
----
- arch/arm/mach-s3c2440/Kconfig                |    7 +
- arch/arm/mach-s3c2440/Makefile               |    1 +
- arch/arm/mach-s3c2440/fiq_c_isr.c            |  250 ++++++++++++++++++++++++++
- arch/arm/mach-s3c2440/fiq_c_isr.h            |   64 +++++++
- arch/arm/mach-s3c2440/mach-gta02.c           |   22 +++
- arch/arm/plat-s3c24xx/irq.c                  |   32 +++-
- include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h |   28 +++
- include/asm-arm/plat-s3c24xx/irq.h           |   20 ++
- 8 files changed, 422 insertions(+), 2 deletions(-)
- create mode 100644 arch/arm/mach-s3c2440/fiq_c_isr.c
- create mode 100644 arch/arm/mach-s3c2440/fiq_c_isr.h
- create mode 100644 include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
-
-diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
-index 6b317d1..3015aaf 100644
---- a/arch/arm/mach-s3c2440/Kconfig
-+++ b/arch/arm/mach-s3c2440/Kconfig
-@@ -22,6 +22,13 @@ config S3C2440_DMA
-       help
-         Support for S3C2440 specific DMA code5A
-+config S3C2440_C_FIQ
-+      bool "FIQ ISR support in C"
-+      depends on ARCH_S3C2410
-+      select FIQ
-+      help
-+        Support for S3C2440 FIQ support in C -- see
-+        ./arch/arm/macs3c2440/fiq_c_isr.c
- menu "S3C2440 Machines"
-diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
-index 1a4defd..4932232 100644
---- a/arch/arm/mach-s3c2440/Makefile
-+++ b/arch/arm/mach-s3c2440/Makefile
-@@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_S3C2440)    += s3c2440.o dsc.o
- obj-$(CONFIG_CPU_S3C2440)     += irq.o
- obj-$(CONFIG_CPU_S3C2440)     += clock.o
- obj-$(CONFIG_S3C2440_DMA)     += dma.o
-+obj-$(CONFIG_S3C2440_C_FIQ)   += fiq_c_isr.o
- # Machine support
-diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.c b/arch/arm/mach-s3c2440/fiq_c_isr.c
-new file mode 100644
-index 0000000..12f4527
---- /dev/null
-+++ b/arch/arm/mach-s3c2440/fiq_c_isr.c
-@@ -0,0 +1,250 @@
-+/*
-+ * Copyright 2007  Andy Green <andy@warmcat.com>
-+ * S3C modfifications
-+ * Copyright 2008 Andy Green <andy@openmoko.com>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <asm/hardware.h>
-+#include <asm/fiq.h>
-+#include "fiq_c_isr.h"
-+#include <linux/sysfs.h>
-+#include <linux/device.h>
-+#include <linux/platform_device.h>
-+
-+#include <asm/io.h>
-+
-+#include <asm/plat-s3c24xx/cpu.h>
-+#include <asm/plat-s3c24xx/irq.h>
-+
-+/*
-+ * Major Caveats for using FIQ
-+ * ---------------------------
-+ *
-+ * 1) it CANNOT touch any vmalloc()'d memory, only memory
-+ *    that was kmalloc()'d.  Static allocations in the monolithic kernel
-+ *    are kmalloc()'d so they are okay.  You can touch memory-mapped IO, but
-+ *    the pointer for it has to have been stored in kmalloc'd memory.  The
-+ *    reason for this is simple: every now and then Linux turns off interrupts
-+ *    and reorders the paging tables.  If a FIQ happens during this time, the
-+ *    virtual memory space can be partly or entirely disordered or missing.
-+ *
-+ * 2) Because vmalloc() is used when a module is inserted, THIS FIQ
-+ *    ISR HAS TO BE IN THE MONOLITHIC KERNEL, not a module.  But the way
-+ *    it is set up, you can all to enable and disable it from your module
-+ *    and intercommunicate with it through struct fiq_ipc
-+ *    fiq_ipc which you can define in
-+ *    asm/archfiq_ipc_type.h.  The reason is the same as above, a
-+ *    FIQ could happen while even the ISR is not present in virtual memory
-+ *    space due to pagetables being changed at the time.
-+ *
-+ * 3) You can't call any Linux API code except simple macros
-+ *    - understand that FIQ can come in at any time, no matter what
-+ *      state of undress the kernel may privately be in, thinking it
-+ *      locked the door by turning off interrupts... FIQ is an
-+ *      unstoppable monster force (which is its value)
-+ *    - they are not vmalloc()'d memory safe
-+ *    - they might do crazy stuff like sleep: FIQ pisses fire and
-+ *      is not interested in 'sleep' that the weak seem to need
-+ *    - calling APIs from FIQ can re-enter un-renterable things
-+ *    - summary: you cannot interoperate with linux APIs directly in the FIQ ISR
-+ *
-+ * If you follow these rules, it is fantastic, an extremely powerful, solid,
-+ * genuine hard realtime feature.
-+ *
-+ */
-+
-+/* more than enough to cover our jump instruction to the isr */
-+#define SIZEOF_FIQ_JUMP 8
-+/* more than enough to cover s3c2440_fiq_isr() in 4K blocks */
-+#define SIZEOF_FIQ_ISR 0x2000
-+/* increase the size of the stack that is active during FIQ as needed */
-+static u8 u8aFiqStack[4096];
-+
-+/* only one FIQ ISR possible, okay to do these here */
-+u32 _fiq_ack_mask; /* used by isr exit define */
-+unsigned long _fiq_count_fiqs; /* used by isr exit define */
-+static int _fiq_irq; /* private ; irq index we were started with, or 0 */
-+
-+/* this function must live in the monolithic kernel somewhere!  A module is
-+ * NOT good enough!
-+ */
-+extern void __attribute__ ((naked)) s3c2440_fiq_isr(void);
-+
-+/* this is copied into the hard FIQ vector during init */
-+
-+static void __attribute__ ((naked)) s3c2440_FIQ_Branch(void)
-+{
-+      asm __volatile__ (
-+              "mov pc, r8 ; "
-+      );
-+}
-+
-+/* sysfs */
-+
-+static ssize_t show_count(struct device *dev, struct device_attribute *attr,
-+                       char *buf)
-+{
-+      return sprintf(buf, "%ld\n", _fiq_count_fiqs);
-+}
-+
-+static DEVICE_ATTR(count, 0444, show_count, NULL);
-+
-+static struct attribute *s3c2440_fiq_sysfs_entries[] = {
-+      &dev_attr_count.attr,
-+      NULL
-+};
-+
-+static struct attribute_group s3c2440_fiq_attr_group = {
-+      .name   = "fiq",
-+      .attrs  = s3c2440_fiq_sysfs_entries,
-+};
-+
-+/*
-+ * call this from your kernel module to set up the FIQ ISR to service FIQs,
-+ * You need to have configured your FIQ input pin before anything will happen
-+ *
-+ * call it with, eg, IRQ_TIMER3 from asm-arm/arch-s3c2410/irqs.h
-+ *
-+ * you still need to clear the source interrupt in S3C2410_INTMSK to get
-+ * anything good happening
-+ */
-+static void fiq_init_irq_source(int irq_index_fiq)
-+{
-+      if (!irq_index_fiq) /* no interrupt */
-+              return;
-+
-+      printk(KERN_INFO"Enabling FIQ using int idx %d\n",
-+             irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
-+      local_fiq_disable();
-+
-+      _fiq_irq = irq_index_fiq;
-+      _fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
-+
-+      /* let our selected interrupt be a magic FIQ interrupt */
-+      __raw_writel(_fiq_ack_mask, S3C2410_INTMOD);
-+
-+      /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */
-+      local_fiq_enable();
-+}
-+
-+
-+/* call this from your kernel module to disable generation of FIQ actions */
-+static void fiq_disable_irq_source(void)
-+{
-+      /* nothing makes FIQ any more */
-+      __raw_writel(0, S3C2410_INTMOD);
-+      local_fiq_disable();
-+      _fiq_irq = 0; /* no active source interrupt now either */
-+}
-+
-+/* this starts FIQ timer events... they continue until the FIQ ISR sees that
-+ * its work is done and it turns off the timer.  After setting up the fiq_ipc
-+ * struct with new work, you call this to start FIQ timer actions up again.
-+ * Only the FIQ ISR decides when it is done and controls turning off the
-+ * timer events.
-+ */
-+void fiq_kick(void)
-+{
-+      unsigned long flags;
-+
-+      /* we have to take care about FIQ because this modification is
-+       * non-atomic, FIQ could come in after the read and before the
-+       * writeback and its changes to the register would be lost
-+       * (platform INTMSK mod code is taken care of already)
-+       */
-+      local_save_flags(flags);
-+      local_fiq_disable();
-+      __raw_writel(__raw_readl(S3C2410_INTMSK) &
-+                   ~(1 << (_fiq_irq - S3C2410_CPUIRQ_OFFSET)),
-+                   S3C2410_INTMSK);
-+      local_irq_restore(flags);
-+}
-+EXPORT_SYMBOL_GPL(fiq_kick);
-+
-+
-+
-+static int __init sc32440_fiq_probe(struct platform_device *pdev)
-+{
-+      struct resource *r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+
-+      if (!r)
-+              return -EIO;
-+      /* configure for the interrupt we are meant to use */
-+      fiq_init_irq_source(r->start);
-+
-+      return sysfs_create_group(&pdev->dev.kobj, &s3c2440_fiq_attr_group);
-+}
-+
-+static int sc32440_fiq_remove(struct platform_device *pdev)
-+{
-+      fiq_disable_irq_source();
-+      sysfs_remove_group(&pdev->dev.kobj, &s3c2440_fiq_attr_group);
-+      return 0;
-+}
-+
-+static void fiq_set_vector_and_regs(void)
-+{
-+      struct pt_regs regs;
-+
-+      /* prep the special FIQ mode regs */
-+      memset(&regs, 0, sizeof(regs));
-+      regs.ARM_r8 = (unsigned long)s3c2440_fiq_isr;
-+      regs.ARM_sp = (unsigned long)u8aFiqStack + sizeof(u8aFiqStack) - 4;
-+      /* set up the special FIQ-mode-only registers from our regs */
-+      set_fiq_regs(&regs);
-+      /* copy our jump to the real ISR into the hard vector address */
-+      set_fiq_handler(s3c2440_FIQ_Branch, SIZEOF_FIQ_JUMP);
-+}
-+
-+#ifdef CONFIG_PM
-+static int sc32440_fiq_suspend(struct platform_device *pdev, pm_message_t state)
-+{
-+      /* nothing makes FIQ any more */
-+      __raw_writel(0, S3C2410_INTMOD);
-+      local_fiq_disable();
-+
-+      return 0;
-+}
-+
-+static int sc32440_fiq_resume(struct platform_device *pdev)
-+{
-+      fiq_set_vector_and_regs();
-+      fiq_init_irq_source(_fiq_irq);
-+      return 0;
-+}
-+#else
-+#define sc32440_fiq_suspend   NULL
-+#define sc32440_fiq_resume    NULL
-+#endif
-+
-+static struct platform_driver sc32440_fiq_driver = {
-+      .driver = {
-+              .name   = "sc32440_fiq",
-+              .owner  = THIS_MODULE,
-+      },
-+
-+      .probe   = sc32440_fiq_probe,
-+      .remove  = __devexit_p(sc32440_fiq_remove),
-+      .suspend = sc32440_fiq_suspend,
-+      .resume  = sc32440_fiq_resume,
-+};
-+
-+static int __init sc32440_fiq_init(void)
-+{
-+      fiq_set_vector_and_regs();
-+
-+      return platform_driver_register(&sc32440_fiq_driver);
-+}
-+
-+static void __exit sc32440_fiq_exit(void)
-+{
-+      fiq_disable_irq_source();
-+}
-+
-+MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
-+MODULE_LICENSE("GPL");
-+
-+module_init(sc32440_fiq_init);
-+module_exit(sc32440_fiq_exit);
-diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.h b/arch/arm/mach-s3c2440/fiq_c_isr.h
-new file mode 100644
-index 0000000..f08740e
---- /dev/null
-+++ b/arch/arm/mach-s3c2440/fiq_c_isr.h
-@@ -0,0 +1,64 @@
-+#ifndef _LINUX_FIQ_C_ISR_H
-+#define _LINUX_FIQ_C_ISR_H
-+
-+#include <asm/arch-s3c2410/regs-irq.h>
-+
-+extern unsigned long _fiq_count_fiqs;
-+extern u32 _fiq_ack_mask;
-+
-+/* This CANNOT be implemented in a module -- it has to be used in code
-+ * included in the monolithic kernel
-+ */
-+
-+#define FIQ_HANDLER_START() \
-+void __attribute__ ((naked)) s3c2440_fiq_isr(void) \
-+{\
-+      /*\
-+       * you can declare local vars here, take care to set the frame size\
-+       *  below accordingly if there are more than a few dozen bytes of them\
-+       */\
-+
-+/* stick your locals here :-)
-+ * Do NOT initialize them here!  define them and initialize them after
-+ * FIQ_HANDLER_ENTRY() is done.
-+ */
-+
-+#define FIQ_HANDLER_ENTRY(LOCALS, FRAME) \
-+      const int _FIQ_FRAME_SIZE = FRAME; \
-+      /* entry takes care to store registers we will be treading on here */\
-+      asm __volatile__ (\
-+              "mov     ip, sp ;"\
-+              /* stash FIQ and r0-r8 normal regs */\
-+              "stmdb  sp!, {r0-r12, lr};"\
-+              /* allow SP to get some space */\
-+              "sub     sp, sp, %1 ;"\
-+              /* !! THIS SETS THE FRAME, adjust to > sizeof locals */\
-+              "sub     fp, sp, %0 ;"\
-+              :\
-+              : "rI" (LOCALS), "rI" (FRAME)\
-+              :"r9"\
-+      );
-+
-+/* stick your ISR code here and then end with... */
-+
-+#define FIQ_HANDLER_END() \
-+      _fiq_count_fiqs++;\
-+      __raw_writel(_fiq_ack_mask, S3C2410_SRCPND);\
-+\
-+      /* exit back to normal mode restoring everything */\
-+      asm __volatile__ (\
-+              /* pop our allocation */\
-+              "add     sp, sp, %0 ;"\
-+              /* return FIQ regs back to pristine state\
-+               * and get normal regs back\
-+               */\
-+              "ldmia  sp!, {r0-r12, lr};"\
-+\
-+              /* return */\
-+              "subs   pc, lr, #4;"\
-+              : \
-+              : "rI" (_FIQ_FRAME_SIZE) \
-+      );\
-+}
-+
-+#endif /* _LINUX_FIQ_C_ISR_H */
-diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
-index 46acede..0bdd0e0 100644
---- a/arch/arm/mach-s3c2440/mach-gta02.c
-+++ b/arch/arm/mach-s3c2440/mach-gta02.c
-@@ -78,9 +78,31 @@
- #include <linux/glamofb.h>
-+#include <asm/arch/fiq_ipc_gta02.h>
-+#include "fiq_c_isr.h"
-+
- /* arbitrates which sensor IRQ owns the shared SPI bus */
- static spinlock_t motion_irq_lock;
-+/* define FIQ IPC struct */
-+/*
-+ * contains stuff FIQ ISR modifies and normal kernel code can see and use
-+ * this is defined in <asm/arch/fiq_ipc_gta02.h>, you should customize
-+ * the definition in there and include the same definition in your kernel
-+ * module that wants to interoperate with your FIQ code.
-+ */
-+struct fiq_ipc fiq_ipc;
-+EXPORT_SYMBOL(fiq_ipc);
-+
-+/* define FIQ ISR */
-+
-+FIQ_HANDLER_START()
-+/* define your locals here -- no initializers though */
-+FIQ_HANDLER_ENTRY(256, 512)
-+/* Your ISR here :-) */
-+FIQ_HANDLER_END()
-+
-+
- static struct map_desc gta02_iodesc[] __initdata = {
-       {
-               .virtual        = 0xe0000000,
-diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
-index ae2c5d7..9887db1 100644
---- a/arch/arm/plat-s3c24xx/irq.c
-+++ b/arch/arm/plat-s3c24xx/irq.c
-@@ -133,12 +133,20 @@ static void
- s3c_irq_mask(unsigned int irqno)
- {
-       unsigned long mask;
--
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      unsigned long flags;
-+#endif
-       irqno -= IRQ_EINT0;
--
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_save_flags(flags);
-+      local_fiq_disable();
-+#endif
-       mask = __raw_readl(S3C2410_INTMSK);
-       mask |= 1UL << irqno;
-       __raw_writel(mask, S3C2410_INTMSK);
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_irq_restore(flags);
-+#endif
- }
- static inline void
-@@ -155,9 +163,19 @@ s3c_irq_maskack(unsigned int irqno)
- {
-       unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-       unsigned long mask;
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      unsigned long flags;
-+#endif
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_save_flags(flags);
-+      local_fiq_disable();
-+#endif
-       mask = __raw_readl(S3C2410_INTMSK);
-       __raw_writel(mask|bitval, S3C2410_INTMSK);
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_irq_restore(flags);
-+#endif
-       __raw_writel(bitval, S3C2410_SRCPND);
-       __raw_writel(bitval, S3C2410_INTPND);
-@@ -168,15 +186,25 @@ static void
- s3c_irq_unmask(unsigned int irqno)
- {
-       unsigned long mask;
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      unsigned long flags;
-+#endif
-       if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
-               irqdbf2("s3c_irq_unmask %d\n", irqno);
-       irqno -= IRQ_EINT0;
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_save_flags(flags);
-+      local_fiq_disable();
-+#endif
-       mask = __raw_readl(S3C2410_INTMSK);
-       mask &= ~(1UL << irqno);
-       __raw_writel(mask, S3C2410_INTMSK);
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_irq_restore(flags);
-+#endif
- }
- struct irq_chip s3c_irq_level_chip = {
-diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
-new file mode 100644
-index 0000000..341f2bb
---- /dev/null
-+++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
-@@ -0,0 +1,28 @@
-+#ifndef _LINUX_FIQ_IPC_H
-+#define _LINUX_FIQ_IPC_H
-+
-+/*
-+ * this defines the struct which is used to communicate between the FIQ
-+ * world and the normal linux kernel world.  One of these structs is
-+ * statically defined for you in the monolithic kernel so the FIQ ISR code
-+ * can safely touch it any any time.
-+ *
-+ * You also want to include this file in your kernel module that wants to
-+ * communicate with your FIQ code.  Add any kinds of vars that are used by
-+ * the FIQ ISR and the module in here.
-+ *
-+ * To get you started there is just an int that is incremented every FIQ
-+ * you can remove this when you are ready to customize, but it is useful
-+ * for testing
-+ */
-+
-+struct fiq_ipc {
-+      u8 u8a[0]; /* placeholder */
-+};
-+
-+/* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
-+extern struct fiq_ipc fiq_ipc;
-+
-+extern void fiq_kick(void);  /* provoke a FIQ "immediately" */
-+
-+#endif /* _LINUX_FIQ_IPC_H */
-diff --git a/include/asm-arm/plat-s3c24xx/irq.h b/include/asm-arm/plat-s3c24xx/irq.h
-index 45746a9..bf15e1c 100644
---- a/include/asm-arm/plat-s3c24xx/irq.h
-+++ b/include/asm-arm/plat-s3c24xx/irq.h
-@@ -25,8 +25,15 @@ s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
- {
-       unsigned long mask;
-       unsigned long submask;
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      unsigned long flags;
-+#endif
-       submask = __raw_readl(S3C2410_INTSUBMSK);
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_save_flags(flags);
-+      local_fiq_disable();
-+#endif
-       mask = __raw_readl(S3C2410_INTMSK);
-       submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
-@@ -39,6 +46,9 @@ s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
-       /* write back masks */
-       __raw_writel(submask, S3C2410_INTSUBMSK);
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_irq_restore(flags);
-+#endif
- }
-@@ -47,8 +57,15 @@ s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
- {
-       unsigned long mask;
-       unsigned long submask;
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      unsigned long flags;
-+#endif
-       submask = __raw_readl(S3C2410_INTSUBMSK);
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_save_flags(flags);
-+      local_fiq_disable();
-+#endif
-       mask = __raw_readl(S3C2410_INTMSK);
-       submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
-@@ -57,6 +74,9 @@ s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
-       /* write back masks */
-       __raw_writel(submask, S3C2410_INTSUBMSK);
-       __raw_writel(mask, S3C2410_INTMSK);
-+#ifdef CONFIG_S3C2440_C_FIQ
-+      local_irq_restore(flags);
-+#endif
- }
--- 
-1.5.6.3
-