2010-02-16 11:10:58

by Samu Onkalo

[permalink] [raw]
Subject: [PATCH V2 0/6] lis3lv02d: click and threshold interrupts

This patch set replaces my previous one.
(see http://www.spinics.net/lists/kernel/msg994446.html)

Power control of the chip is dropped out since it requires more work.
Runtime-pm support was requested and that takes some time to implement
and test. I'll send it as a separate patch.

patches 1 - 3 are not touched compared to patch set 1 and they
are marked as tested-by Daniel Mack <[email protected]> and
acked-by ?ric Piel <[email protected]>.
Patch 4 is marked as tested-by Daniel Mack <[email protected]>.

lis3: Add skeletons for interrupt handlers
No functional changes. Changed due to rebasing and power control
removal.

lis3: Interrupt handlers for 8bit wakeup and click events
As requested, BTN_ events are enabled only for 8 bit device and
when click event is configured to the HW.
Remapping of the BTN_ axis done according to platform data.

lis3: Setup poll interval limits
Poll interval can now be set from 1 - 2000 ms and also to stopped state
via input-dev sysfs.

Tested in 2.6.32 based environment. Applies to 2.6.33-RC8


Samu Onkalo (6):
lis3: Add missing constants for 8bit device
lis3: Separate configuration function for 8 bit device
lis3: Introduce platform data for second ff / wu unit
lis3: Add skeletons for interrupt handlers
lis3: Interrupt handlers for 8bit wakeup and click events
lis3: Setup poll interval limits

drivers/hwmon/lis3lv02d.c | 245 +++++++++++++++++++++++++++++++++++----------
drivers/hwmon/lis3lv02d.h | 11 ++
include/linux/lis3lv02d.h | 12 ++
3 files changed, 213 insertions(+), 55 deletions(-)


2010-02-16 11:10:33

by Samu Onkalo

[permalink] [raw]
Subject: [PATCH V2 1/6] lis3: Add missing constants for 8bit device

Definitions for click were missing.

Signed-off-by: Samu Onkalo <[email protected]>
Acked-by: Éric Piel <[email protected]>
Tested-by: Daniel Mack <[email protected]>
---
drivers/hwmon/lis3lv02d.h | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
index e6a01f4..692e244 100644
--- a/drivers/hwmon/lis3lv02d.h
+++ b/drivers/hwmon/lis3lv02d.h
@@ -196,6 +196,16 @@ enum lis3lv02d_dd_src {
DD_SRC_IA = 0x40,
};

+enum lis3lv02d_click_src_8b {
+ CLICK_SINGLE_X = 0x01,
+ CLICK_DOUBLE_X = 0x02,
+ CLICK_SINGLE_Y = 0x04,
+ CLICK_DOUBLE_Y = 0x08,
+ CLICK_SINGLE_Z = 0x10,
+ CLICK_DOUBLE_Z = 0x20,
+ CLICK_IA = 0x40,
+};
+
struct axis_conversion {
s8 x;
s8 y;
--
1.6.0.4

2010-02-16 11:10:40

by Samu Onkalo

[permalink] [raw]
Subject: [PATCH V2 5/6] lis3: Interrupt handlers for 8bit wakeup and click events

Content for the 8bit device threaded interrupt handlers.
Depending on the interrupt line and chip configuration,
either click or wakeup / freefall handler is called.
In case of click, BTN_ event is sent via input device.
In case of wakeup or freefall, input device ABS_ events
are updated immediatelly.

It is still possible to configure interrupt line 1 for fast freefall
detection and use the second line either for click or threshold
based interrupts. Or both lines can be used for click / threshold
interrupts.

Polled input device can be set to stopped state and still
get coordinate updates via input device using interrupt
based method. Polled mode and interrupt mode can also be used parallel.

BTN_ events are remapped based on existing axis remapping information.

Signed-off-by: Samu Onkalo <[email protected]>
---
drivers/hwmon/lis3lv02d.c | 98 +++++++++++++++++++++++++++++++++++++++------
drivers/hwmon/lis3lv02d.h | 1 +
include/linux/lis3lv02d.h | 2 +
3 files changed, 88 insertions(+), 13 deletions(-)

diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 3c06350..56a1d34 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -121,11 +121,9 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
int position[3];
int i;

- mutex_lock(&lis3->mutex);
position[0] = lis3->read_data(lis3, OUTX);
position[1] = lis3->read_data(lis3, OUTY);
position[2] = lis3->read_data(lis3, OUTZ);
- mutex_unlock(&lis3->mutex);

for (i = 0; i < 3; i++)
position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
@@ -249,6 +247,19 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3)
EXPORT_SYMBOL_GPL(lis3lv02d_poweron);


+static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
+{
+ int x, y, z;
+
+ mutex_lock(&lis3_dev.mutex);
+ lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+ input_report_abs(pidev->input, ABS_X, x);
+ input_report_abs(pidev->input, ABS_Y, y);
+ input_report_abs(pidev->input, ABS_Z, z);
+ input_sync(pidev->input);
+ mutex_unlock(&lis3_dev.mutex);
+}
+
static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
{
if (!test_bit(0, &lis3_dev.misc_opened))
@@ -270,13 +281,71 @@ out:
return IRQ_HANDLED;
}

+static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
+{
+ struct input_dev *dev = lis3->idev->input;
+ u8 click_src;
+
+ mutex_lock(&lis3->mutex);
+ lis3->read(lis3, CLICK_SRC, &click_src);
+
+ if (click_src & CLICK_SINGLE_X) {
+ input_report_key(dev, lis3->mapped_btns[0], 1);
+ input_report_key(dev, lis3->mapped_btns[0], 0);
+ }
+
+ if (click_src & CLICK_SINGLE_Y) {
+ input_report_key(dev, lis3->mapped_btns[1], 1);
+ input_report_key(dev, lis3->mapped_btns[1], 0);
+ }
+
+ if (click_src & CLICK_SINGLE_Z) {
+ input_report_key(dev, lis3->mapped_btns[2], 1);
+ input_report_key(dev, lis3->mapped_btns[2], 0);
+ }
+ input_sync(dev);
+ mutex_unlock(&lis3->mutex);
+}
+
+static void lis302dl_interrupt_handle_ff_wu(struct lis3lv02d *lis3)
+{
+ u8 wu1_src;
+ u8 wu2_src;
+
+ lis3->read(lis3, FF_WU_SRC_1, &wu1_src);
+ lis3->read(lis3, FF_WU_SRC_2, &wu2_src);
+
+ wu1_src = wu1_src & FF_WU_SRC_IA ? wu1_src : 0;
+ wu2_src = wu2_src & FF_WU_SRC_IA ? wu2_src : 0;
+
+ /* joystick poll is internally protected by the lis3->mutex. */
+ if (wu1_src || wu2_src)
+ lis3lv02d_joystick_poll(lis3_dev.idev);
+}
+
static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
{
+
+ struct lis3lv02d *lis3 = data;
+
+ if ((lis3->pdata->irq_cfg & LIS3_IRQ1_MASK) == LIS3_IRQ1_CLICK)
+ lis302dl_interrupt_handle_click(lis3);
+ else
+ lis302dl_interrupt_handle_ff_wu(lis3);
+
return IRQ_HANDLED;
}

static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
{
+
+ struct lis3lv02d *lis3 = data;
+
+ if ((lis3->pdata->irq_cfg & LIS3_IRQ2_MASK) == LIS3_IRQ2_CLICK)
+ lis302dl_interrupt_handle_click(lis3);
+ else
+ lis302dl_interrupt_handle_ff_wu(lis3);
+
return IRQ_HANDLED;
}

@@ -374,22 +443,12 @@ static struct miscdevice lis3lv02d_misc_device = {
.fops = &lis3lv02d_misc_fops,
};

-static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
-{
- int x, y, z;
-
- lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
- input_report_abs(pidev->input, ABS_X, x);
- input_report_abs(pidev->input, ABS_Y, y);
- input_report_abs(pidev->input, ABS_Z, z);
- input_sync(pidev->input);
-}
-
int lis3lv02d_joystick_enable(void)
{
struct input_dev *input_dev;
int err;
int max_val, fuzz, flat;
+ int btns[] = {BTN_X, BTN_Y, BTN_Z};

if (lis3_dev.idev)
return -EINVAL;
@@ -416,6 +475,10 @@ int lis3lv02d_joystick_enable(void)
input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);

+ lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
+ lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
+ lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
+
err = input_register_polled_device(lis3_dev.idev);
if (err) {
input_free_polled_device(lis3_dev.idev);
@@ -461,7 +524,9 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
{
int x, y, z;

+ mutex_lock(&lis3_dev.mutex);
lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+ mutex_unlock(&lis3_dev.mutex);
return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
}

@@ -535,6 +600,13 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
dev->write(dev, CLICK_THSY_X,
(p->click_thresh_x & 0xf) |
(p->click_thresh_y << 4));
+
+ if (dev->idev) {
+ struct input_dev *input_dev = lis3_dev.idev->input;
+ input_set_capability(input_dev, EV_KEY, BTN_X);
+ input_set_capability(input_dev, EV_KEY, BTN_Y);
+ input_set_capability(input_dev, EV_KEY, BTN_Z);
+ }
}

if (p->wakeup_flags) {
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
index 692e244..8540913 100644
--- a/drivers/hwmon/lis3lv02d.h
+++ b/drivers/hwmon/lis3lv02d.h
@@ -233,6 +233,7 @@ struct lis3lv02d {
struct platform_device *pdev; /* platform device */
atomic_t count; /* interrupt count after last read */
struct axis_conversion ac; /* hw -> logical axis */
+ int mapped_btns[3];

u32 irq; /* IRQ number */
struct fasync_struct *async_queue; /* queue for the misc device */
diff --git a/include/linux/lis3lv02d.h b/include/linux/lis3lv02d.h
index fd289b1..0e8a346 100644
--- a/include/linux/lis3lv02d.h
+++ b/include/linux/lis3lv02d.h
@@ -25,12 +25,14 @@ struct lis3lv02d_platform_data {
#define LIS3_IRQ1_FF_WU_12 (3 << 0)
#define LIS3_IRQ1_DATA_READY (4 << 0)
#define LIS3_IRQ1_CLICK (7 << 0)
+#define LIS3_IRQ1_MASK (7 << 0)
#define LIS3_IRQ2_DISABLE (0 << 3)
#define LIS3_IRQ2_FF_WU_1 (1 << 3)
#define LIS3_IRQ2_FF_WU_2 (2 << 3)
#define LIS3_IRQ2_FF_WU_12 (3 << 3)
#define LIS3_IRQ2_DATA_READY (4 << 3)
#define LIS3_IRQ2_CLICK (7 << 3)
+#define LIS3_IRQ2_MASK (7 << 3)
#define LIS3_IRQ_OPEN_DRAIN (1 << 6)
#define LIS3_IRQ_ACTIVE_LOW (1 << 7)
unsigned char irq_cfg;
--
1.6.0.4

2010-02-16 11:10:43

by Samu Onkalo

[permalink] [raw]
Subject: [PATCH V2 6/6] lis3: Setup poll interval limits

Set valid adjustment window (0 - 2000ms).

Signed-off-by: Samu Onkalo <[email protected]>
---
drivers/hwmon/lis3lv02d.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 56a1d34..6138f03 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -41,6 +41,8 @@

/* joystick device poll interval in milliseconds */
#define MDPS_POLL_INTERVAL 50
+#define MDPS_POLL_MIN 0
+#define MDPS_POLL_MAX 2000
/*
* The sensor can also generate interrupts (DRDY) but it's pretty pointless
* because they are generated even if the data do not change. So it's better
@@ -459,6 +461,8 @@ int lis3lv02d_joystick_enable(void)

lis3_dev.idev->poll = lis3lv02d_joystick_poll;
lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
+ lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
+ lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
input_dev = lis3_dev.idev->input;

input_dev->name = "ST LIS3LV02DL Accelerometer";
--
1.6.0.4

2010-02-16 11:10:50

by Samu Onkalo

[permalink] [raw]
Subject: [PATCH V2 2/6] lis3: Separate configuration function for 8 bit device

Separate configuration function for 8 bit version of the chip.
This way generic part of the init function stays little bit
more readable.

Signed-off-by: Samu Onkalo <[email protected]>
Acked-by: Éric Piel <[email protected]>
Tested-by: Daniel Mack <[email protected]>
---
drivers/hwmon/lis3lv02d.c | 45 ++++++++++++++++++++++++++-------------------
1 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index b2f2277..99fd45d 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -521,6 +521,30 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
}
EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);

+static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
+ struct lis3lv02d_platform_data *p)
+{
+ if (p->click_flags) {
+ dev->write(dev, CLICK_CFG, p->click_flags);
+ dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
+ dev->write(dev, CLICK_LATENCY, p->click_latency);
+ dev->write(dev, CLICK_WINDOW, p->click_window);
+ dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
+ dev->write(dev, CLICK_THSY_X,
+ (p->click_thresh_x & 0xf) |
+ (p->click_thresh_y << 4));
+ }
+
+ if (p->wakeup_flags) {
+ dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
+ dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
+ /* default to 2.5ms for now */
+ dev->write(dev, FF_WU_DURATION_1, 1);
+ /* enable high pass filter for both free-fall units */
+ dev->write(dev, CTRL_REG2, HP_FF_WU1 | HP_FF_WU2);
+ }
+}
+
/*
* Initialise the accelerometer and the various subsystems.
* Should be rather independent of the bus system.
@@ -567,25 +591,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
if (dev->pdata) {
struct lis3lv02d_platform_data *p = dev->pdata;

- if (p->click_flags && (dev->whoami == WAI_8B)) {
- dev->write(dev, CLICK_CFG, p->click_flags);
- dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
- dev->write(dev, CLICK_LATENCY, p->click_latency);
- dev->write(dev, CLICK_WINDOW, p->click_window);
- dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
- dev->write(dev, CLICK_THSY_X,
- (p->click_thresh_x & 0xf) |
- (p->click_thresh_y << 4));
- }
-
- if (p->wakeup_flags && (dev->whoami == WAI_8B)) {
- dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
- dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
- /* default to 2.5ms for now */
- dev->write(dev, FF_WU_DURATION_1, 1);
- /* enable high pass filter for both free-fall units */
- dev->write(dev, CTRL_REG2, HP_FF_WU1 | HP_FF_WU2);
- }
+ if (dev->whoami == WAI_8B)
+ lis3lv02d_8b_configure(dev, p);

if (p->irq_cfg)
dev->write(dev, CTRL_REG3, p->irq_cfg);
--
1.6.0.4

2010-02-16 11:11:26

by Samu Onkalo

[permalink] [raw]
Subject: [PATCH V2 4/6] lis3: Add skeletons for interrupt handlers

Original lis3 driver didn't provide interrupt handler(s) for
click or threshold event handling. This patch adds threaded handlers
for one or two interrupt lines for 8 bit device.
Actual content for interrupt handling is provided in the
separate patch.

Signed-off-by: Samu Onkalo <[email protected]>
Tested-by: Daniel Mack <[email protected]>
---
drivers/hwmon/lis3lv02d.c | 87 +++++++++++++++++++++++++++++++++------------
include/linux/lis3lv02d.h | 1 +
2 files changed, 65 insertions(+), 23 deletions(-)

diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 50f3123..3c06350 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -251,6 +251,9 @@ EXPORT_SYMBOL_GPL(lis3lv02d_poweron);

static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
{
+ if (!test_bit(0, &lis3_dev.misc_opened))
+ goto out;
+
/*
* Be careful: on some HP laptops the bios force DD when on battery and
* the lid is closed. This leads to interrupts as soon as a little move
@@ -260,44 +263,35 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy)

wake_up_interruptible(&lis3_dev.misc_wait);
kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
+out:
+ if (lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
+ lis3_dev.idev->input->users)
+ return IRQ_WAKE_THREAD;
return IRQ_HANDLED;
}

-static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
+static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
{
- int ret;
+ return IRQ_HANDLED;
+}

+static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
+{
+ return IRQ_HANDLED;
+}
+
+static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
+{
if (test_and_set_bit(0, &lis3_dev.misc_opened))
return -EBUSY; /* already open */

atomic_set(&lis3_dev.count, 0);
-
- /*
- * The sensor can generate interrupts for free-fall and direction
- * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
- * the things simple and _fast_ we activate it only for free-fall, so
- * no need to read register (very slow with ACPI). For the same reason,
- * we forbid shared interrupts.
- *
- * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
- * io-apic is not configurable (and generates a warning) but I keep it
- * in case of support for other hardware.
- */
- ret = request_irq(lis3_dev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING,
- DRIVER_NAME, &lis3_dev);
-
- if (ret) {
- clear_bit(0, &lis3_dev.misc_opened);
- printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", lis3_dev.irq);
- return -EBUSY;
- }
return 0;
}

static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
{
fasync_helper(-1, file, 0, &lis3_dev.async_queue);
- free_irq(lis3_dev.irq, &lis3_dev);
clear_bit(0, &lis3_dev.misc_opened); /* release the device */
return 0;
}
@@ -434,6 +428,11 @@ EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);

void lis3lv02d_joystick_disable(void)
{
+ if (lis3_dev.irq)
+ free_irq(lis3_dev.irq, &lis3_dev);
+ if (lis3_dev.pdata && lis3_dev.pdata->irq2)
+ free_irq(lis3_dev.pdata->irq2, &lis3_dev);
+
if (!lis3_dev.idev)
return;

@@ -524,6 +523,7 @@ EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
struct lis3lv02d_platform_data *p)
{
+ int err;
int ctrl2 = p->hipass_ctrl;

if (p->click_flags) {
@@ -554,6 +554,18 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
}
/* Configure hipass filters */
dev->write(dev, CTRL_REG2, ctrl2);
+
+ if (p->irq2) {
+ err = request_threaded_irq(p->irq2,
+ NULL,
+ lis302dl_interrupt_thread2_8b,
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT,
+ DRIVER_NAME, &lis3_dev);
+ if (err < 0)
+ printk(KERN_ERR DRIVER_NAME
+ "No second IRQ. Limited functionality\n");
+ }
}

/*
@@ -562,6 +574,9 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
*/
int lis3lv02d_init_device(struct lis3lv02d *dev)
{
+ int err;
+ irq_handler_t thread_fn;
+
dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);

switch (dev->whoami) {
@@ -616,6 +631,32 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
goto out;
}

+ /*
+ * The sensor can generate interrupts for free-fall and direction
+ * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
+ * the things simple and _fast_ we activate it only for free-fall, so
+ * no need to read register (very slow with ACPI). For the same reason,
+ * we forbid shared interrupts.
+ *
+ * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
+ * io-apic is not configurable (and generates a warning) but I keep it
+ * in case of support for other hardware.
+ */
+ if (dev->whoami == WAI_8B)
+ thread_fn = lis302dl_interrupt_thread1_8b;
+ else
+ thread_fn = NULL;
+
+ err = request_threaded_irq(dev->irq, lis302dl_interrupt,
+ thread_fn,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ DRIVER_NAME, &lis3_dev);
+
+ if (err < 0) {
+ printk(KERN_ERR DRIVER_NAME "Cannot get IRQ\n");
+ goto out;
+ }
+
if (misc_register(&lis3lv02d_misc_device))
printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
out:
diff --git a/include/linux/lis3lv02d.h b/include/linux/lis3lv02d.h
index d625199..fd289b1 100644
--- a/include/linux/lis3lv02d.h
+++ b/include/linux/lis3lv02d.h
@@ -67,6 +67,7 @@ struct lis3lv02d_platform_data {
/* Limits for selftest are specified in chip data sheet */
s16 st_min_limits[3]; /* min pass limit x, y, z */
s16 st_max_limits[3]; /* max pass limit x, y, z */
+ int irq2;
};

#endif /* __LIS3LV02D_H_ */
--
1.6.0.4

2010-02-16 11:11:40

by Samu Onkalo

[permalink] [raw]
Subject: [PATCH V2 3/6] lis3: Introduce platform data for second ff / wu unit

8 bit device has two wakeup / free fall units. It was not possible
to configure the second unit. This patch introduces configuration
entry to the platform data and also corresponding changes to the
8 bit setup function.

High pass filters were enabled by default. Patch introduces configuration
option for high pass filter cut off frequency and also possibility to
disable or enable the filter via platform data.
Since the control is a new one and default state was filter enabled,
new option is used to disable the filter. This way old platform data
is still compatible with the change.

Signed-off-by: Samu Onkalo <[email protected]>
Acked-by: Éric Piel <[email protected]>
Tested-by: Daniel Mack <[email protected]>
---
drivers/hwmon/lis3lv02d.c | 15 +++++++++++++--
include/linux/lis3lv02d.h | 9 +++++++++
2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 99fd45d..50f3123 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -524,6 +524,8 @@ EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
struct lis3lv02d_platform_data *p)
{
+ int ctrl2 = p->hipass_ctrl;
+
if (p->click_flags) {
dev->write(dev, CLICK_CFG, p->click_flags);
dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
@@ -540,9 +542,18 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
/* default to 2.5ms for now */
dev->write(dev, FF_WU_DURATION_1, 1);
- /* enable high pass filter for both free-fall units */
- dev->write(dev, CTRL_REG2, HP_FF_WU1 | HP_FF_WU2);
+ ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
+ }
+
+ if (p->wakeup_flags2) {
+ dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
+ dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
+ /* default to 2.5ms for now */
+ dev->write(dev, FF_WU_DURATION_2, 1);
+ ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
}
+ /* Configure hipass filters */
+ dev->write(dev, CTRL_REG2, ctrl2);
}

/*
diff --git a/include/linux/lis3lv02d.h b/include/linux/lis3lv02d.h
index f1ca0dc..d625199 100644
--- a/include/linux/lis3lv02d.h
+++ b/include/linux/lis3lv02d.h
@@ -43,6 +43,15 @@ struct lis3lv02d_platform_data {
#define LIS3_WAKEUP_Z_HI (1 << 5)
unsigned char wakeup_flags;
unsigned char wakeup_thresh;
+ unsigned char wakeup_flags2;
+ unsigned char wakeup_thresh2;
+#define LIS3_HIPASS_CUTFF_8HZ 0
+#define LIS3_HIPASS_CUTFF_4HZ 1
+#define LIS3_HIPASS_CUTFF_2HZ 2
+#define LIS3_HIPASS_CUTFF_1HZ 3
+#define LIS3_HIPASS1_DISABLE (1 << 2)
+#define LIS3_HIPASS2_DISABLE (1 << 3)
+ unsigned char hipass_ctrl;
#define LIS3_NO_MAP 0
#define LIS3_DEV_X 1
#define LIS3_DEV_Y 2
--
1.6.0.4

2010-02-25 07:27:23

by Samu Onkalo

[permalink] [raw]
Subject: RE: [PATCH V2 0/6] lis3lv02d: click and threshold interrupts


Hi

>-----Original Message-----
>From: Onkalo Samu.P (Nokia-D/Tampere)
>Sent: 16 February, 2010 13:09
>To: [email protected]
>Cc: [email protected]; [email protected]; [email protected]; linux-
>[email protected]; Onkalo Samu.P (Nokia-D/Tampere)
>Subject: [PATCH V2 0/6] lis3lv02d: click and threshold interrupts
>
>This patch set replaces my previous one.
>(see http://www.spinics.net/lists/kernel/msg994446.html)
>
>Power control of the chip is dropped out since it requires more work.
>Runtime-pm support was requested and that takes some time to implement
>and test. I'll send it as a separate patch.
>
>patches 1 - 3 are not touched compared to patch set 1 and they
>are marked as tested-by Daniel Mack <[email protected]> and
>acked-by ?ric Piel <[email protected]>.
>Patch 4 is marked as tested-by Daniel Mack <[email protected]>.
>
> lis3: Add skeletons for interrupt handlers
>No functional changes. Changed due to rebasing and power control
>removal.
>
> lis3: Interrupt handlers for 8bit wakeup and click events
>As requested, BTN_ events are enabled only for 8 bit device and
>when click event is configured to the HW.
>Remapping of the BTN_ axis done according to platform data.
>
> lis3: Setup poll interval limits
>Poll interval can now be set from 1 - 2000 ms and also to stopped state
>via input-dev sysfs.
>
>Tested in 2.6.32 based environment. Applies to 2.6.33-RC8
>
>
>Samu Onkalo (6):
> lis3: Add missing constants for 8bit device
> lis3: Separate configuration function for 8 bit device
> lis3: Introduce platform data for second ff / wu unit
> lis3: Add skeletons for interrupt handlers
> lis3: Interrupt handlers for 8bit wakeup and click events
> lis3: Setup poll interval limits
>
> drivers/hwmon/lis3lv02d.c | 245 +++++++++++++++++++++++++++++++++++---
>-------
> drivers/hwmon/lis3lv02d.h | 11 ++
> include/linux/lis3lv02d.h | 12 ++
> 3 files changed, 213 insertions(+), 55 deletions(-)

Any comments to these ones?

One thing which I just noticed. Now interrupts are configured all the time
so even if there is no device file open, interrupts are handled by the CPU.
However, there should not be that much interrupts that it causes problems.
This would be corrected by the power management patch (which I dropped),
but is not using runtime PM feature. I'm not sure if I have possibility to
implement and test runtime PM version in our environment.

-Samu