Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 217114
b: refs/heads/master
c: 029756d
h: refs/heads/master
v: v3
  • Loading branch information
Samu Onkalo authored and Guenter Roeck committed Oct 25, 2010
1 parent 344bbc7 commit 47d80f8
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f10a5407b58603fb3b084d7fbdbd50f47d010c82
refs/heads/master: 029756d0b8856f52d83dee81c01dd3af786cadff
88 changes: 80 additions & 8 deletions trunk/drivers/hwmon/lis3lv02d.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@

#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */

#define SELFTEST_OK 0
#define SELFTEST_FAIL -1
#define SELFTEST_IRQ -2

#define IRQ_LINE0 0
#define IRQ_LINE1 1

/*
* 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
Expand Down Expand Up @@ -226,8 +233,25 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
s16 x, y, z;
u8 selftest;
int ret;
u8 ctrl_reg_data;
unsigned char irq_cfg;

mutex_lock(&lis3->mutex);

irq_cfg = lis3->irq_cfg;
if (lis3_dev.whoami == WAI_8B) {
lis3->data_ready_count[IRQ_LINE0] = 0;
lis3->data_ready_count[IRQ_LINE1] = 0;

/* Change interrupt cfg to data ready for selftest */
atomic_inc(&lis3_dev.wake_thread);
lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
}

if (lis3_dev.whoami == WAI_3DC) {
ctlreg = CTRL_REG4;
selftest = CTRL4_ST0;
Expand Down Expand Up @@ -257,13 +281,33 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
results[2] = z - lis3->read_data(lis3, OUTZ);

ret = 0;

if (lis3_dev.whoami == WAI_8B) {
/* Restore original interrupt configuration */
atomic_dec(&lis3_dev.wake_thread);
lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
lis3->irq_cfg = irq_cfg;

if ((irq_cfg & LIS3_IRQ1_MASK) &&
lis3->data_ready_count[IRQ_LINE0] < 2) {
ret = SELFTEST_IRQ;
goto fail;
}

if ((irq_cfg & LIS3_IRQ2_MASK) &&
lis3->data_ready_count[IRQ_LINE1] < 2) {
ret = SELFTEST_IRQ;
goto fail;
}
}

if (lis3->pdata) {
int i;
for (i = 0; i < 3; i++) {
/* Check against selftest acceptance limits */
if ((results[i] < lis3->pdata->st_min_limits[i]) ||
(results[i] > lis3->pdata->st_max_limits[i])) {
ret = -EIO;
ret = SELFTEST_FAIL;
goto fail;
}
}
Expand Down Expand Up @@ -426,13 +470,24 @@ static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
mutex_unlock(&lis3->mutex);
}

static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
{
int dummy;

/* Dummy read to ack interrupt */
lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
lis3->data_ready_count[index]++;
}

static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
{
struct lis3lv02d *lis3 = data;
u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;

if ((lis3->irq_cfg & LIS3_IRQ1_MASK) == LIS3_IRQ1_CLICK)
if (irq_cfg == LIS3_IRQ1_CLICK)
lis302dl_interrupt_handle_click(lis3);
else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
lis302dl_data_ready(lis3, IRQ_LINE0);
else
lis3lv02d_joystick_poll(lis3->idev);

Expand All @@ -441,11 +496,13 @@ static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)

static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
{

struct lis3lv02d *lis3 = data;
u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;

if ((lis3->irq_cfg & LIS3_IRQ2_MASK) == LIS3_IRQ2_CLICK)
if (irq_cfg == LIS3_IRQ2_CLICK)
lis302dl_interrupt_handle_click(lis3);
else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
lis302dl_data_ready(lis3, IRQ_LINE1);
else
lis3lv02d_joystick_poll(lis3->idev);

Expand Down Expand Up @@ -648,12 +705,27 @@ static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
static ssize_t lis3lv02d_selftest_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int result;
s16 values[3];

static const char ok[] = "OK";
static const char fail[] = "FAIL";
static const char irq[] = "FAIL_IRQ";
const char *res;

lis3lv02d_sysfs_poweron(&lis3_dev);
result = lis3lv02d_selftest(&lis3_dev, values);
return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL",
switch (lis3lv02d_selftest(&lis3_dev, values)) {
case SELFTEST_FAIL:
res = fail;
break;
case SELFTEST_IRQ:
res = irq;
break;
case SELFTEST_OK:
default:
res = ok;
break;
}
return sprintf(buf, "%s %d %d %d\n", res,
values[0], values[1], values[2]);
}

Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/hwmon/lis3lv02d.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ struct lis3lv02d {
struct fasync_struct *async_queue; /* queue for the misc device */
wait_queue_head_t misc_wait; /* Wait queue for the misc device */
unsigned long misc_opened; /* bit0: whether the device is open */
atomic_t wake_thread;
int data_ready_count[2];
atomic_t wake_thread;
unsigned char irq_cfg;

struct lis3lv02d_platform_data *pdata; /* for passing board config */
Expand Down

0 comments on commit 47d80f8

Please sign in to comment.