changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1055-introduce-fiq-migrate-vibrator-gta02-only.patch.patch
diff --git a/target/linux/s3c24xx/patches-2.6.24/1055-introduce-fiq-migrate-vibrator-gta02-only.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1055-introduce-fiq-migrate-vibrator-gta02-only.patch.patch
new file mode 100644 (file)
index 0000000..399da0f
--- /dev/null
@@ -0,0 +1,243 @@
+From b1b2748dd58ae925df4b4e98921db373a7777e9b Mon Sep 17 00:00:00 2001
+From: mokopatches <mokopatches@openmoko.org>
+Date: Sun, 13 Apr 2008 07:23:52 +0100
+Subject: [PATCH] introduce-fiq-migrate-vibrator-gta02-only.patch
+
+On GTA02 we use FIQ to manage the vibrator IO now.  That
+is necessary because we stole timer3 from doing hw pwm
+for vibrator.  This keeps the same UI in /sys but does
+"bitbang pwm" on the same vibrator GPIO
+
+From: Andy Green <andy@openmoko.com>
+Signed-off-by: Andy Green <andy@openmoko.com>
+---
+ arch/arm/mach-s3c2440/fiq_c_isr.c            |   13 +++++---
+ arch/arm/mach-s3c2440/mach-gta02.c           |   38 ++++++++++++++++++++++++++
+ drivers/leds/Kconfig                         |    1 +
+ drivers/leds/leds-neo1973-vibrator.c         |   24 +++++++++++++++-
+ include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h |    9 +++++-
+ 5 files changed, 77 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.c b/arch/arm/mach-s3c2440/fiq_c_isr.c
+index a71a234..38692fc 100644
+--- a/arch/arm/mach-s3c2440/fiq_c_isr.c
++++ b/arch/arm/mach-s3c2440/fiq_c_isr.c
+@@ -79,6 +79,7 @@ u16 _fiq_timer_divisor;
+  */
+ 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)
+@@ -128,7 +129,7 @@ static int fiq_init_irq_source(int irq_index_fiq)
+       _fiq_irq = irq_index_fiq;
+       _fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
+-      timer_index = (irq_index_fiq - IRQ_TIMER0);
++      _fiq_timer_index = (irq_index_fiq - IRQ_TIMER0);
+       /* set up the timer to operate as a pwm device */
+@@ -136,12 +137,11 @@ static int fiq_init_irq_source(int irq_index_fiq)
+       if (rc)
+               goto bail;
+-      pwm_timer_fiq.timerid = PWM0 + timer_index;
++      pwm_timer_fiq.timerid = PWM0 + _fiq_timer_index;
+       pwm_timer_fiq.prescaler = (6 - 1) / 2;
+       pwm_timer_fiq.divider = S3C2410_TCFG1_MUX3_DIV2;
+       /* default rate == ~32us */
+-      pwm_timer_fiq.counter = pwm_timer_fiq.comparer =
+-                                      timer_divisor = 64;
++      pwm_timer_fiq.counter = pwm_timer_fiq.comparer = 3000;
+       rc = s3c2410_pwm_enable(&pwm_timer_fiq);
+       if (rc)
+@@ -149,6 +149,8 @@ static int fiq_init_irq_source(int irq_index_fiq)
+       s3c2410_pwm_start(&pwm_timer_fiq);
++      _fiq_timer_divisor = 0xffff; /* so kick will work initially */
++
+       /* let our selected interrupt be a magic FIQ interrupt */
+       __raw_writel(_fiq_ack_mask, S3C2410_INTMOD);
+@@ -189,7 +191,7 @@ void fiq_kick(void)
+                    S3C2410_INTMSK);
+       tcon = __raw_readl(S3C2410_TCON) & ~S3C2410_TCON_T3START;
+       /* fake the timer to a count of 1 */
+-      __raw_writel(1, S3C2410_TCNTB(timer_index));
++      __raw_writel(1, S3C2410_TCNTB(_fiq_timer_index));
+       __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD, S3C2410_TCON);
+       __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD | S3C2410_TCON_T3START,
+                    S3C2410_TCON);
+@@ -207,6 +209,7 @@ static int __init sc32440_fiq_probe(struct platform_device *pdev)
+       if (!r)
+               return -EIO;
++
+       /* configure for the interrupt we are meant to use */
+       printk(KERN_INFO"Enabling FIQ using irq %d\n", r->start);
+diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
+index cb839b2..8c7bbe7 100644
+--- a/arch/arm/mach-s3c2440/mach-gta02.c
++++ b/arch/arm/mach-s3c2440/mach-gta02.c
+@@ -95,12 +95,50 @@ static spinlock_t motion_irq_lock;
+ struct fiq_ipc fiq_ipc;
+ EXPORT_SYMBOL(fiq_ipc);
++#define DIVISOR_FROM_US(x) ((x) << 1)
++
++#define FIQ_DIVISOR_VIBRATOR DIVISOR_FROM_US(100)
++
+ /* define FIQ ISR */
+ FIQ_HANDLER_START()
+ /* define your locals here -- no initializers though */
++      u16 divisor;
+ FIQ_HANDLER_ENTRY(256, 512)
+ /* Your ISR here :-) */
++      divisor = 0xffff;
++
++      /* Vibrator servicing */
++
++      if (fiq_ipc.vib_pwm_latched || fiq_ipc.vib_pwm) { /* not idle */
++              if (((u8)_fiq_count_fiqs) == fiq_ipc.vib_pwm_latched)
++                      s3c2410_gpio_setpin(fiq_ipc.vib_gpio_pin, 0);
++              if (((u8)_fiq_count_fiqs) == 0) {
++                      fiq_ipc.vib_pwm_latched = fiq_ipc.vib_pwm;
++                      if (fiq_ipc.vib_pwm_latched)
++                              s3c2410_gpio_setpin(fiq_ipc.vib_gpio_pin, 1);
++              }
++              divisor = FIQ_DIVISOR_VIBRATOR;
++      }
++
++      /* TODO: HDQ servicing */
++
++
++
++      /* disable further timer interrupts if nobody has any work
++       * or adjust rate according to who still has work
++       *
++       * CAUTION: it means forground code must disable FIQ around
++       * its own non-atomic S3C2410_INTMSK changes... not common
++       * thankfully and taken care of by the fiq-basis patch
++       */
++      if (divisor == 0xffff) /* mask the fiq irq source */
++              __raw_writel(__raw_readl(S3C2410_INTMSK) | _fiq_ack_mask,
++                           S3C2410_INTMSK);
++      else /* still working, maybe at a different rate */
++              __raw_writel(divisor, S3C2410_TCNTB(_fiq_timer_index));
++      _fiq_timer_divisor = divisor;
++
+ FIQ_HANDLER_END()
+diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
+index 2f95707..77aa3bd 100644
+--- a/drivers/leds/Kconfig
++++ b/drivers/leds/Kconfig
+@@ -117,6 +117,7 @@ config LEDS_CM_X270
+ config LEDS_NEO1973_VIBRATOR
+       tristate "Vibrator Support for the FIC Neo1973 GSM phone"
+       depends on LEDS_CLASS && MACH_NEO1973
++      select S3C2440_C_FIQ
+       help
+         This option enables support for the vibrator on the FIC Neo1973.
+diff --git a/drivers/leds/leds-neo1973-vibrator.c b/drivers/leds/leds-neo1973-vibrator.c
+index c943a6a..36ed216 100644
+--- a/drivers/leds/leds-neo1973-vibrator.c
++++ b/drivers/leds/leds-neo1973-vibrator.c
+@@ -23,6 +23,8 @@
+ #include <asm/arch/gta01.h>
+ #include <asm/plat-s3c/regs-timer.h>
++#include <asm/arch-s3c2410/fiq_ipc_gta02.h>
++
+ #define COUNTER 64
+ struct neo1973_vib_priv {
+@@ -39,6 +41,11 @@ static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
+       struct neo1973_vib_priv *vp =
+               container_of(led_cdev, struct neo1973_vib_priv, cdev);
++      if (machine_is_neo1973_gta02()) { /* use FIQ to control GPIO */
++              fiq_ipc.vib_pwm = value; /* set it for FIQ */
++              fiq_kick(); /* start up FIQs if not already going */
++              return;
++      }
+       /*
+        * value == 255 -> 99% duty cycle (full power)
+        * value == 128 -> 50% duty cycle (medium power)
+@@ -46,7 +53,7 @@ static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
+        */
+       mutex_lock(&vp->mutex);
+       if (vp->has_pwm)
+-              s3c2410_pwm_duty_cycle(value/4, &vp->pwm);
++              s3c2410_pwm_duty_cycle(value / 4, &vp->pwm);
+       else {
+               if (value)
+                       s3c2410_gpio_setpin(vp->gpio, 1);
+@@ -123,6 +130,15 @@ static int __init neo1973_vib_probe(struct platform_device *pdev)
+       neo1973_vib_led.gpio = r->start;
+       platform_set_drvdata(pdev, &neo1973_vib_led);
++      if (machine_is_neo1973_gta02()) { /* use FIQ to control GPIO */
++              s3c2410_gpio_setpin(neo1973_vib_led.gpio, 0); /* off */
++              s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPIO_OUTPUT);
++              /* safe, kmalloc'd copy needed for FIQ ISR */
++              fiq_ipc.vib_gpio_pin = neo1973_vib_led.gpio;
++              fiq_ipc.vib_pwm = 0; /* off */
++              goto configured;
++      }
++
+       /* TOUT3 */
+       if (neo1973_vib_led.gpio == S3C2410_GPB3) {
+               rc = neo1973_vib_init_hw(&neo1973_vib_led);
+@@ -133,7 +149,7 @@ static int __init neo1973_vib_probe(struct platform_device *pdev)
+               s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPB3_TOUT3);
+               neo1973_vib_led.has_pwm = 1;
+       }
+-
++configured:
+       mutex_init(&neo1973_vib_led.mutex);
+       return led_classdev_register(&pdev->dev, &neo1973_vib_led.cdev);
+@@ -141,6 +157,10 @@ static int __init neo1973_vib_probe(struct platform_device *pdev)
+ static int neo1973_vib_remove(struct platform_device *pdev)
+ {
++      if (machine_is_neo1973_gta02()) /* use FIQ to control GPIO */
++              fiq_ipc.vib_pwm = 0; /* off */
++      /* would only need kick if already off so no kick needed */
++
+       if (neo1973_vib_led.has_pwm)
+               s3c2410_pwm_disable(&neo1973_vib_led.pwm);
+diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
+index 6cbd8e4..507d235 100644
+--- a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
++++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
+@@ -16,8 +16,15 @@
+  * for testing
+  */
++#include <asm/arch/pwm.h>
++#include <asm/plat-s3c/regs-timer.h>
++
++
+ struct fiq_ipc {
+-      u8 u8a[0]; /* placeholder */
++      /* vibrator */
++      unsigned long vib_gpio_pin; /* which pin to meddle with */
++      u8 vib_pwm; /* 0 = OFF -- will ensure GPIO deasserted and stop FIQ */
++      u8 vib_pwm_latched;
+ };
+ /* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
+-- 
+1.5.6.5
+