summaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.26/1190-fix-lis302dl-resume-and-init-reload-boot-coefficient.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.26/1190-fix-lis302dl-resume-and-init-reload-boot-coefficient.patch')
-rwxr-xr-xtarget/linux/s3c24xx/patches-2.6.26/1190-fix-lis302dl-resume-and-init-reload-boot-coefficient.patch168
1 files changed, 168 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.26/1190-fix-lis302dl-resume-and-init-reload-boot-coefficient.patch b/target/linux/s3c24xx/patches-2.6.26/1190-fix-lis302dl-resume-and-init-reload-boot-coefficient.patch
new file mode 100755
index 0000000000..cec5985a9b
--- /dev/null
+++ b/target/linux/s3c24xx/patches-2.6.26/1190-fix-lis302dl-resume-and-init-reload-boot-coefficient.patch
@@ -0,0 +1,168 @@
+From d0c3a8bdfe2722f00b5ec7812500fbf1f6229b9f Mon Sep 17 00:00:00 2001
+From: Andy Green <andy@openmoko.com>
+Date: Fri, 25 Jul 2008 23:06:16 +0100
+Subject: [PATCH] fix-lis302dl-resume-and-init-reload-boot-coefficients.patch
+ Reported-by: John Lee <john_lee@openmoko.com>
+
+We don't reset the devices either at init or resume, where init
+means use the BOOT bit to reload device calibration coefficients
+from internal EEPROM. John Lee saw brain-damaged behaviour after
+resume and sometimes after boot (since it may not have lost power
+to force a BOOT itself that makes sense).
+
+This patch
+
+ - adds a diagnostic dump feature down /sys
+ - forces BOOT action on init and resume, and waits for
+ completion
+ - makes sure XYZ capture is enabled on resume
+ - adds some constants in the .h and removes some magic numbers
+ in the code by using them
+
+Signed-off-by: Andy Green <andy@openmoko.com>
+---
+ drivers/input/misc/lis302dl.c | 78 +++++++++++++++++++++++++++++++++++++++--
+ include/linux/lis302dl.h | 9 +++++
+ 2 files changed, 84 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
+index 1d19418..553a731 100644
+--- a/drivers/input/misc/lis302dl.c
++++ b/drivers/input/misc/lis302dl.c
+@@ -221,9 +221,37 @@ static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
+
+ static DEVICE_ATTR(full_scale, S_IRUGO | S_IWUSR, show_scale, set_scale);
+
++static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct lis302dl_info *lis = dev_get_drvdata(dev);
++ int n = 0;
++ u8 reg[0x40];
++ char *end = buf;
++ unsigned long flags;
++
++ local_save_flags(flags);
++
++ for (n = 0; n < sizeof(reg); n++)
++ reg[n] = reg_read(lis, n);
++
++ local_irq_restore(flags);
++
++ for (n = 0; n < sizeof(reg); n += 16) {
++ hex_dump_to_buffer(reg + n, 16, 16, 1, end, 128, 0);
++ end += strlen(end);
++ *end++ = '\n';
++ *end++ = '\0';
++ }
++
++ return end - buf;
++}
++static DEVICE_ATTR(dump, S_IRUGO, lis302dl_dump, NULL);
++
+ static struct attribute *lis302dl_sysfs_entries[] = {
+ &dev_attr_sample_rate.attr,
+ &dev_attr_full_scale.attr,
++ &dev_attr_dump.attr,
+ NULL
+ };
+
+@@ -276,6 +304,24 @@ static void lis302dl_input_close(struct input_dev *inp)
+ local_irq_restore(flags);
+ }
+
++/* get the device to reload its coefficients from EEPROM and wait for it
++ * to complete
++ */
++
++static int __lis302dl_reset_device(struct lis302dl_info *lis)
++{
++ int timeout = 10;
++
++ reg_write(lis, LIS302DL_REG_CTRL2, LIS302DL_CTRL2_BOOT |
++ LIS302DL_CTRL2_FDS);
++
++ while ((reg_read(lis, LIS302DL_REG_CTRL2) & LIS302DL_CTRL2_BOOT) &&
++ (timeout--))
++ mdelay(1);
++
++ return !!(timeout < 0);
++}
++
+ static int __devinit lis302dl_probe(struct spi_device *spi)
+ {
+ int rc;
+@@ -347,12 +393,24 @@ static int __devinit lis302dl_probe(struct spi_device *spi)
+ goto bail_inp_dev;
+ }
+
+- reg_write(lis, LIS302DL_REG_CTRL1, 0x47);
+- reg_write(lis, LIS302DL_REG_CTRL3, 0xc0);
++ if (__lis302dl_reset_device(lis))
++ dev_err(&spi->dev, "device BOOT reload failed\n");
++
++ /* force us powered */
++ reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD |
++ LIS302DL_CTRL1_Xen |
++ LIS302DL_CTRL1_Yen |
++ LIS302DL_CTRL1_Zen);
++ mdelay(1);
++
++ 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_DURATION_1, 0x00);
+ reg_write(lis, LIS302DL_REG_FF_WU_CFG_1, 0x95);
+
++ /* start off in powered down mode; we power up when someone opens us */
+ reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_Xen |
+ LIS302DL_CTRL1_Yen |
+ LIS302DL_CTRL1_Zen);
+@@ -494,8 +552,22 @@ static int lis302dl_resume(struct spi_device *spi)
+ /* get our IO to the device back in operational states */
+ (lis->pdata->lis302dl_suspend_io)(lis, 1);
+
++ /* resume from powerdown first! */
++ reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD |
++ LIS302DL_CTRL1_Xen |
++ LIS302DL_CTRL1_Yen |
++ LIS302DL_CTRL1_Zen);
++ mdelay(1);
++
++ if (__lis302dl_reset_device(lis))
++ dev_err(&spi->dev, "device BOOT reload failed\n");
++
+ /* restore registers after resume */
+- reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1]);
++ reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1] |
++ LIS302DL_CTRL1_PD |
++ LIS302DL_CTRL1_Xen |
++ LIS302DL_CTRL1_Yen |
++ LIS302DL_CTRL1_Zen);
+ reg_write(lis, LIS302DL_REG_CTRL2, lis->regs[LIS302DL_REG_CTRL2]);
+ reg_write(lis, LIS302DL_REG_CTRL3, lis->regs[LIS302DL_REG_CTRL3]);
+ reg_write(lis, LIS302DL_REG_FF_WU_CFG_1,
+diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
+index 0d6b4c4..4d8ded9 100644
+--- a/include/linux/lis302dl.h
++++ b/include/linux/lis302dl.h
+@@ -66,6 +66,15 @@ enum lis302dl_reg_ctrl1 {
+ LIS302DL_CTRL1_DR = 0x80,
+ };
+
++enum lis302dl_reg_ctrl2 {
++ LIS302DL_CTRL2_HPC1 = 0x01,
++ LIS302DL_CTRL2_HPC2 = 0x02,
++ LIS302DL_CTRL2_HPFF1 = 0x04,
++ LIS302DL_CTRL2_HPFF2 = 0x08,
++ LIS302DL_CTRL2_FDS = 0x10,
++ LIS302DL_CTRL2_BOOT = 0x40,
++ LIS302DL_CTRL2_SIM = 0x80,
++};
+ enum lis302dl_reg_ctrl3 {
+ LIS302DL_CTRL3_PP_OD = 0x40,
+ LIS302DL_CTRL3_IHL = 0x80,
+--
+1.5.6.3
+