aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.24/1280-interface-for-configuring-freefall-wakeup-interrupts.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.24/1280-interface-for-configuring-freefall-wakeup-interrupts.patch')
-rw-r--r--target/linux/s3c24xx/patches-2.6.24/1280-interface-for-configuring-freefall-wakeup-interrupts.patch372
1 files changed, 0 insertions, 372 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.24/1280-interface-for-configuring-freefall-wakeup-interrupts.patch b/target/linux/s3c24xx/patches-2.6.24/1280-interface-for-configuring-freefall-wakeup-interrupts.patch
deleted file mode 100644
index 38318315c4..0000000000
--- a/target/linux/s3c24xx/patches-2.6.24/1280-interface-for-configuring-freefall-wakeup-interrupts.patch
+++ /dev/null
@@ -1,372 +0,0 @@
-From 69acbd477fb7024d2cfa3702036b92ecb6c8e7b5 Mon Sep 17 00:00:00 2001
-From: Simon Kagstrom <simon.kagstrom@gmail.com>
-Date: Fri, 15 Aug 2008 11:50:56 +0100
-Subject: [PATCH] interface for configuring freefall/wakeup interrupts for the accelerometers
-
-Hi!
-
-First: Unfortunately, the freerunner currently wakes up immediately on
-suspend when the accelerometer IRQ is selected as a wakeup source. I'm
-posting this for comments and if someone else wants to have a look at
-this problem.
-
-The patch should be safe to apply even though the sleep portion doesn't
-work - as long as it's configured it will not disturb anything.
-
-// Simon
---
-lis302dl-configure-wakeup-interrupts.patch
-
-From: simon.kagstrom <simon.kagstrom@gmail.com>
-
-First: Unfortunately, the freerunner currently wakes up immediately on
-suspend when the accelerometer IRQ is selected as a wakeup source.
-
-
-Add configuration of wakeup/freefall interrupts through a sysfs
-interface. Configuration is done through echoing a value of the
-form
-
- X Y Z THRESHOLD DURATION SPEC
-
-to freefall_wakeup_1/2. X, Y and Z are threshold values, given as a
-value > 0, < 0 or 0 to specify if an interrupt should be generated for
-high or low thresholds or neither (off). THRESHOLD specifies the
-threshold that must be exceeded. DURATION specifies the time in
-milliseconds for which the acceleration should be measured. SPEC is
-either '1' or '0' and specifies if the thresholds should be taken all
-together or one at a time ('and' or 'or' mode).
-
-Echoing '0' to the file turns off the interrupts.
-
-Example:
-
- echo "1 1 1 60 60 0" > freefall_wakeup_1 # Turn on x,y,z, 60ms/60 threshold, or-mode
- echo "0" > freefall_wakeup_1 # Turn off interrupt
-
-The hardware supports two simulataneous wakeup sources to be configured,
-but the freerunner only connects one of the interrupt outputs. The patch
-exports both. Similarly, only the "top" accelerometer can be used as a
-wake-up source, and it's not possible to generate DATA_READY interrupts
-while the wakeup interrupts are active.
-
-Signed-off-by: Simon Kagstrom <simon.kagstrom@gmail.com>
----
- drivers/input/misc/lis302dl.c | 232 +++++++++++++++++++++++++++++++++++++++--
- include/linux/lis302dl.h | 8 +-
- 2 files changed, 227 insertions(+), 13 deletions(-)
-
-diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
-index b97cae7..3f6d0eb 100644
---- a/drivers/input/misc/lis302dl.c
-+++ b/drivers/input/misc/lis302dl.c
-@@ -248,10 +248,212 @@ static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr,
- }
- static DEVICE_ATTR(dump, S_IRUGO, lis302dl_dump, NULL);
-
-+static int freefall_ms_to_duration(struct lis302dl_info *lis, int ms)
-+{
-+ u_int8_t r = reg_read(lis, LIS302DL_REG_CTRL1);
-+
-+ /* If we have 400 ms sampling rate, the stepping is 2.5 ms,
-+ * on 100 ms the stepping is 10ms */
-+ if ( r & LIS302DL_CTRL1_DR ) {
-+ /* Too large */
-+ if (ms > 637)
-+ return -1;
-+
-+ return (ms * 10) / 25;
-+ }
-+
-+ /* Too large value */
-+ if (ms > 2550)
-+ return -1;
-+ return ms / 10;
-+}
-+
-+static int freefall_duration_to_ms(struct lis302dl_info *lis, int duration)
-+{
-+ u_int8_t r = reg_read(lis, LIS302DL_REG_CTRL1);
-+
-+ if ( r & LIS302DL_CTRL1_DR )
-+ return (duration * 25) / 10;
-+
-+ return duration * 10;
-+}
-+
-+/* Configure freefall/wakeup interrupts */
-+static ssize_t set_freefall_common(int which, struct device *dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct lis302dl_info *lis = dev_get_drvdata(dev);
-+ u_int8_t x_lo, y_lo, z_lo;
-+ u_int8_t x_hi, y_hi, z_hi;
-+ int duration;
-+ int threshold;
-+ int and_events;
-+ int r_ths = LIS302DL_REG_FF_WU_THS_1; /* registers, assume first pin */
-+ int r_duration = LIS302DL_REG_FF_WU_DURATION_1;
-+ int r_cfg = LIS302DL_REG_FF_WU_CFG_1;
-+ int flag_mask = LIS302DL_F_WUP_FF_1;
-+ int intmode = LIS302DL_INTMODE_FF_WU_1;
-+ int x, y, z;
-+ int ms;
-+ unsigned long flags;
-+
-+ /* Configure for second freefall/wakeup pin */
-+ if (which == 2) {
-+ r_ths = LIS302DL_REG_FF_WU_THS_2;
-+ r_duration = LIS302DL_REG_FF_WU_DURATION_2;
-+ r_cfg = LIS302DL_REG_FF_WU_CFG_2;
-+ flag_mask = LIS302DL_F_WUP_FF_2;
-+ intmode = LIS302DL_INTMODE_FF_WU_2;
-+
-+ printk(KERN_WARNING "Configuring second freefall / wakeup interrupt\n");
-+ }
-+
-+ /* Parse the input */
-+ if (strcmp(buf, "0\n") == 0)
-+ {
-+ /* Turn off the interrupt */
-+ local_save_flags(flags);
-+ if ( (lis->flags & LIS302DL_F_IRQ_WAKE) != 0 )
-+ disable_irq_wake(lis->spi_dev->irq);
-+ lis302dl_int_mode(lis->spi_dev, which, LIS302DL_INTMODE_DATA_READY);
-+ lis->flags &= ~(flag_mask | LIS302DL_F_IRQ_WAKE);
-+
-+ reg_write(lis, r_cfg, 0);
-+ reg_write(lis, r_ths, 0);
-+ reg_write(lis, r_duration, 0);
-+
-+ /* Power off unless the input subsystem is using the device */
-+ if ( (lis->flags & LIS302DL_F_INPUT_OPEN) == 0 )
-+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD, 0);
-+
-+ local_irq_restore(flags);
-+
-+ return count;
-+ }
-+
-+ if (sscanf(buf, "%d %d %d %d %d %d", &x, &y, &z, &threshold, &ms, &and_events) != 6)
-+ return -EINVAL;
-+
-+ duration = freefall_ms_to_duration(lis, ms);
-+ if (duration < 0)
-+ return -ERANGE;
-+
-+ /* 7 bits */
-+ if (threshold < 0 || threshold > 127)
-+ return -ERANGE;
-+
-+ /* Interrupt flags */
-+ x_lo = x < 0 ? LIS302DL_FFWUCFG_XLIE : 0;
-+ y_lo = y < 0 ? LIS302DL_FFWUCFG_YLIE : 0;
-+ z_lo = z < 0 ? LIS302DL_FFWUCFG_ZLIE : 0;
-+ x_hi = x > 0 ? LIS302DL_FFWUCFG_XHIE : 0;
-+ y_hi = y > 0 ? LIS302DL_FFWUCFG_YHIE : 0;
-+ z_hi = z > 0 ? LIS302DL_FFWUCFG_ZHIE : 0;
-+
-+ /* Setup the configuration registers */
-+ local_save_flags(flags);
-+ reg_write(lis, r_cfg, 0); /* First zero to get to a known state */
-+ reg_write(lis, r_cfg,
-+ (and_events ? LIS302DL_FFWUCFG_AOI : 0) |
-+ x_lo | x_hi | y_lo | y_hi | z_lo | z_hi);
-+ reg_write(lis, r_ths, threshold & ~LIS302DL_FFWUTHS_DCRM);
-+ reg_write(lis, r_duration, duration);
-+
-+ /* Route the interrupt for wakeup */
-+ lis302dl_int_mode(lis->spi_dev, which, intmode);
-+
-+ /* Power up the device and note that we want to wake up from
-+ * this interrupt */
-+ if ( (lis->flags & LIS302DL_F_IRQ_WAKE) == 0 )
-+ enable_irq_wake(lis->spi_dev->irq);
-+
-+ lis->flags |= flag_mask | LIS302DL_F_IRQ_WAKE;
-+ reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD,
-+ LIS302DL_CTRL1_PD);
-+ local_irq_restore(flags);
-+
-+ return count;
-+}
-+
-+static ssize_t set_freefall_1(struct device *dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ return set_freefall_common(1, dev, attr, buf, count);
-+}
-+static ssize_t set_freefall_2(struct device *dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ return set_freefall_common(2, dev, attr, buf, count);
-+}
-+
-+
-+static ssize_t show_freefall_common(int which, struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ struct lis302dl_info *lis = dev_get_drvdata(dev);
-+ u_int8_t duration;
-+ u_int8_t threshold;
-+ u_int8_t config;
-+ u_int8_t r4;
-+ u_int8_t r5;
-+ int r_ths = LIS302DL_REG_FF_WU_THS_1; /* registers, assume first pin */
-+ int r_duration = LIS302DL_REG_FF_WU_DURATION_1;
-+ int r_cfg = LIS302DL_REG_FF_WU_CFG_1;
-+ int r_src = LIS302DL_REG_FF_WU_SRC_1;
-+
-+ /* Configure second freefall/wakeup pin */
-+ if (which == 2) {
-+ r_ths = LIS302DL_REG_FF_WU_THS_2;
-+ r_duration = LIS302DL_REG_FF_WU_DURATION_2;
-+ r_cfg = LIS302DL_REG_FF_WU_CFG_2;
-+ r_src = LIS302DL_REG_FF_WU_SRC_2;
-+ }
-+ config = reg_read(lis, r_cfg);
-+ threshold = reg_read(lis, r_ths);
-+ duration = reg_read(lis, r_duration);
-+ r4 = reg_read(lis, r_src);
-+ r5 = reg_read(lis, LIS302DL_REG_CTRL3);
-+
-+ /* All events off? */
-+ if ((config & (LIS302DL_FFWUCFG_XLIE | LIS302DL_FFWUCFG_XHIE |
-+ LIS302DL_FFWUCFG_YLIE | LIS302DL_FFWUCFG_YHIE |
-+ LIS302DL_FFWUCFG_ZLIE | LIS302DL_FFWUCFG_ZHIE)) == 0)
-+ return sprintf(buf, "off\n");
-+
-+ return sprintf(buf,"%s events, %s interrupt, duration %d, threshold %d, "
-+ "enabled: %s %s %s %s %s %s\n",
-+ (config & LIS302DL_FFWUCFG_AOI) == 0 ? "or" : "and",
-+ (config & LIS302DL_FFWUCFG_LIR) == 0 ? "don't latch" : "latch",
-+ freefall_duration_to_ms(lis, duration), threshold,
-+ (config & LIS302DL_FFWUCFG_XLIE) == 0 ? "---" : "xlo",
-+ (config & LIS302DL_FFWUCFG_XHIE) == 0 ? "---" : "xhi",
-+ (config & LIS302DL_FFWUCFG_YLIE) == 0 ? "---" : "ylo",
-+ (config & LIS302DL_FFWUCFG_YHIE) == 0 ? "---" : "yhi",
-+ (config & LIS302DL_FFWUCFG_ZLIE) == 0 ? "---" : "zlo",
-+ (config & LIS302DL_FFWUCFG_ZHIE) == 0 ? "---" : "zhi");
-+}
-+
-+static ssize_t show_freefall_1(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ return show_freefall_common(1, dev, attr, buf);
-+}
-+
-+static ssize_t show_freefall_2(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ return show_freefall_common(2, dev, attr, buf);
-+}
-+
-+static DEVICE_ATTR(freefall_wakeup_1, S_IRUGO | S_IWUSR, show_freefall_1, set_freefall_1);
-+static DEVICE_ATTR(freefall_wakeup_2, S_IRUGO | S_IWUSR, show_freefall_2, set_freefall_2);
-+
- static struct attribute *lis302dl_sysfs_entries[] = {
- &dev_attr_sample_rate.attr,
- &dev_attr_full_scale.attr,
- &dev_attr_dump.attr,
-+ &dev_attr_freefall_wakeup_1.attr,
-+ &dev_attr_freefall_wakeup_2.attr,
- NULL
- };
-
-@@ -274,6 +476,8 @@ static int lis302dl_input_open(struct input_dev *inp)
- reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1);
- local_irq_restore(flags);
-
-+ lis->flags |= LIS302DL_F_INPUT_OPEN;
-+
- /* kick it off -- since we are edge triggered, if we missed the edge
- * permanent low interrupt is death for us */
- (lis->pdata->lis302dl_bitbang_read)(lis);
-@@ -294,6 +498,7 @@ static void lis302dl_input_close(struct input_dev *inp)
- * only see close() for the close of the last user, we can safely
- * disable the data ready events */
- reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, 0x00);
-+ lis->flags &= ~LIS302DL_F_INPUT_OPEN;
-
- /* however, don't power down the whole device if still needed */
- if (!(lis->flags & LIS302DL_F_WUP_FF ||
-@@ -406,9 +611,9 @@ static int __devinit lis302dl_probe(struct spi_device *spi)
- reg_write(lis, LIS302DL_REG_CTRL2, 0);
- reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_PP_OD |
- LIS302DL_CTRL3_IHL);
-- reg_write(lis, LIS302DL_REG_FF_WU_THS_1, 0x14);
-+ reg_write(lis, LIS302DL_REG_FF_WU_THS_1, 0x0);
- reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1, 0x00);
-- reg_write(lis, LIS302DL_REG_FF_WU_CFG_1, 0x95);
-+ reg_write(lis, LIS302DL_REG_FF_WU_CFG_1, 0x0);
-
- /* start off in powered down mode; we power up when someone opens us */
- reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_Xen |
-@@ -486,6 +691,12 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
- {
- struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
- unsigned long flags;
-+ u_int8_t tmp;
-+
-+ /* determine if we want to wake up from the accel. */
-+ if (lis->flags & LIS302DL_F_WUP_FF ||
-+ lis->flags & LIS302DL_F_WUP_CLICK)
-+ return 0;
-
- disable_irq(lis->spi_dev->irq);
- local_save_flags(flags);
-@@ -528,15 +739,10 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
- lis->regs[LIS302DL_REG_CLICK_WINDOW] =
- reg_read(lis, LIS302DL_REG_CLICK_WINDOW);
-
-- /* determine if we want to wake up from the accel. */
-- if (!(lis->flags & LIS302DL_F_WUP_FF ||
-- lis->flags & LIS302DL_F_WUP_CLICK)) {
-- /* power down */
-- u_int8_t tmp;
-- tmp = reg_read(lis, LIS302DL_REG_CTRL1);
-- tmp &= ~LIS302DL_CTRL1_PD;
-- reg_write(lis, LIS302DL_REG_CTRL1, tmp);
-- }
-+ /* power down */
-+ tmp = reg_read(lis, LIS302DL_REG_CTRL1);
-+ tmp &= ~LIS302DL_CTRL1_PD;
-+ reg_write(lis, LIS302DL_REG_CTRL1, tmp);
-
- /* place our IO to the device in sleep-compatible states */
- (lis->pdata->lis302dl_suspend_io)(lis, 0);
-@@ -551,6 +757,10 @@ static int lis302dl_resume(struct spi_device *spi)
- struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
- unsigned long flags;
-
-+ if (lis->flags & LIS302DL_F_WUP_FF ||
-+ lis->flags & LIS302DL_F_WUP_CLICK)
-+ return 0;
-+
- local_save_flags(flags);
-
- /* get our IO to the device back in operational states */
-diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
-index e4a44f5..7daa8b3 100644
---- a/include/linux/lis302dl.h
-+++ b/include/linux/lis302dl.h
-@@ -129,10 +129,14 @@ enum lis302dl_reg_cloik_src {
-
- #define LIS302DL_WHO_AM_I_MAGIC 0x3b
-
--#define LIS302DL_F_WUP_FF 0x0001 /* wake up from free fall */
--#define LIS302DL_F_WUP_CLICK 0x0002
-+#define LIS302DL_F_WUP_FF_1 0x0001 /* wake up from free fall */
-+#define LIS302DL_F_WUP_FF_2 0x0002
-+#define LIS302DL_F_WUP_FF 0x0003
-+#define LIS302DL_F_WUP_CLICK 0x0004
- #define LIS302DL_F_POWER 0x0010
- #define LIS302DL_F_FS 0x0020 /* ADC full scale */
-+#define LIS302DL_F_INPUT_OPEN 0x0040 /* Set if input device is opened */
-+#define LIS302DL_F_IRQ_WAKE 0x0080 /* IRQ is setup in wake mode */
-
-
- #endif /* _LINUX_LIS302DL_H */
---
-1.5.6.5
-