changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.26 / 0190-fix-lis302dl-resume-and-init-reload-boot-coefficient.patch
1 From d0c3a8bdfe2722f00b5ec7812500fbf1f6229b9f Mon Sep 17 00:00:00 2001
2 From: Andy Green <andy@openmoko.com>
3 Date: Fri, 25 Jul 2008 23:06:16 +0100
4 Subject: [PATCH] fix-lis302dl-resume-and-init-reload-boot-coefficients.patch
5  Reported-by: John Lee <john_lee@openmoko.com>
6
7 We don't reset the devices either at init or resume, where init
8 means use the BOOT bit to reload device calibration coefficients
9 from internal EEPROM.  John Lee saw brain-damaged behaviour after
10 resume and sometimes after boot (since it may not have lost power
11 to force a BOOT itself that makes sense).
12
13 This patch
14
15  - adds a diagnostic dump feature down /sys
16  - forces BOOT action on init and resume, and waits for
17    completion
18  - makes sure XYZ capture is enabled on resume
19  - adds some constants in the .h and removes some magic numbers
20    in the code by using them
21
22 Signed-off-by: Andy Green <andy@openmoko.com>
23 ---
24  drivers/input/misc/lis302dl.c |   78 +++++++++++++++++++++++++++++++++++++++--
25  include/linux/lis302dl.h      |    9 +++++
26  2 files changed, 84 insertions(+), 3 deletions(-)
27
28 diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
29 index 1d19418..553a731 100644
30 --- a/drivers/input/misc/lis302dl.c
31 +++ b/drivers/input/misc/lis302dl.c
32 @@ -221,9 +221,37 @@ static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
33  
34  static DEVICE_ATTR(full_scale, S_IRUGO | S_IWUSR, show_scale, set_scale);
35  
36 +static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr,
37 +                         char *buf)
38 +{
39 +       struct lis302dl_info *lis = dev_get_drvdata(dev);
40 +       int n = 0;
41 +       u8 reg[0x40];
42 +       char *end = buf;
43 +       unsigned long flags;
44 +
45 +       local_save_flags(flags);
46 +
47 +       for (n = 0; n < sizeof(reg); n++)
48 +               reg[n] = reg_read(lis, n);
49 +
50 +       local_irq_restore(flags);
51 +
52 +       for (n = 0; n < sizeof(reg); n += 16) {
53 +               hex_dump_to_buffer(reg + n, 16, 16, 1, end, 128, 0);
54 +               end += strlen(end);
55 +               *end++ = '\n';
56 +               *end++ = '\0';
57 +       }
58 +
59 +       return end - buf;
60 +}
61 +static DEVICE_ATTR(dump, S_IRUGO, lis302dl_dump, NULL);
62 +
63  static struct attribute *lis302dl_sysfs_entries[] = {
64         &dev_attr_sample_rate.attr,
65         &dev_attr_full_scale.attr,
66 +       &dev_attr_dump.attr,
67         NULL
68  };
69  
70 @@ -276,6 +304,24 @@ static void lis302dl_input_close(struct input_dev *inp)
71         local_irq_restore(flags);
72  }
73  
74 +/* get the device to reload its coefficients from EEPROM and wait for it
75 + * to complete
76 + */
77 +
78 +static int __lis302dl_reset_device(struct lis302dl_info *lis)
79 +{
80 +       int timeout = 10;
81 +
82 +       reg_write(lis, LIS302DL_REG_CTRL2, LIS302DL_CTRL2_BOOT |
83 +                                                           LIS302DL_CTRL2_FDS);
84 +
85 +       while ((reg_read(lis, LIS302DL_REG_CTRL2) & LIS302DL_CTRL2_BOOT) &&
86 +                                                                   (timeout--))
87 +               mdelay(1);
88 +
89 +       return !!(timeout < 0);
90 +}
91 +
92  static int __devinit lis302dl_probe(struct spi_device *spi)
93  {
94         int rc;
95 @@ -347,12 +393,24 @@ static int __devinit lis302dl_probe(struct spi_device *spi)
96                 goto bail_inp_dev;
97         }
98  
99 -       reg_write(lis, LIS302DL_REG_CTRL1, 0x47);
100 -       reg_write(lis, LIS302DL_REG_CTRL3, 0xc0);
101 +       if (__lis302dl_reset_device(lis))
102 +               dev_err(&spi->dev, "device BOOT reload failed\n");
103 +
104 +       /* force us powered */
105 +       reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD |
106 +                                          LIS302DL_CTRL1_Xen |
107 +                                          LIS302DL_CTRL1_Yen |
108 +                                          LIS302DL_CTRL1_Zen);
109 +       mdelay(1);
110 +
111 +       reg_write(lis, LIS302DL_REG_CTRL2, 0);
112 +       reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_PP_OD |
113 +                                                           LIS302DL_CTRL3_IHL);
114         reg_write(lis, LIS302DL_REG_FF_WU_THS_1, 0x14);
115         reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1, 0x00);
116         reg_write(lis, LIS302DL_REG_FF_WU_CFG_1, 0x95);
117  
118 +       /* start off in powered down mode; we power up when someone opens us */
119         reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_Xen |
120                                            LIS302DL_CTRL1_Yen |
121                                            LIS302DL_CTRL1_Zen);
122 @@ -494,8 +552,22 @@ static int lis302dl_resume(struct spi_device *spi)
123         /* get our IO to the device back in operational states */
124         (lis->pdata->lis302dl_suspend_io)(lis, 1);
125  
126 +       /* resume from powerdown first! */
127 +       reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD |
128 +                                          LIS302DL_CTRL1_Xen |
129 +                                          LIS302DL_CTRL1_Yen |
130 +                                          LIS302DL_CTRL1_Zen);
131 +       mdelay(1);
132 +
133 +       if (__lis302dl_reset_device(lis))
134 +               dev_err(&spi->dev, "device BOOT reload failed\n");
135 +
136         /* restore registers after resume */
137 -       reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1]);
138 +       reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1] |
139 +                                               LIS302DL_CTRL1_PD |
140 +                                               LIS302DL_CTRL1_Xen |
141 +                                               LIS302DL_CTRL1_Yen |
142 +                                               LIS302DL_CTRL1_Zen);
143         reg_write(lis, LIS302DL_REG_CTRL2, lis->regs[LIS302DL_REG_CTRL2]);
144         reg_write(lis, LIS302DL_REG_CTRL3, lis->regs[LIS302DL_REG_CTRL3]);
145         reg_write(lis, LIS302DL_REG_FF_WU_CFG_1,
146 diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
147 index 0d6b4c4..4d8ded9 100644
148 --- a/include/linux/lis302dl.h
149 +++ b/include/linux/lis302dl.h
150 @@ -66,6 +66,15 @@ enum lis302dl_reg_ctrl1 {
151         LIS302DL_CTRL1_DR               = 0x80,
152  };
153  
154 +enum lis302dl_reg_ctrl2 {
155 +       LIS302DL_CTRL2_HPC1             = 0x01,
156 +       LIS302DL_CTRL2_HPC2             = 0x02,
157 +       LIS302DL_CTRL2_HPFF1            = 0x04,
158 +       LIS302DL_CTRL2_HPFF2            = 0x08,
159 +       LIS302DL_CTRL2_FDS              = 0x10,
160 +       LIS302DL_CTRL2_BOOT             = 0x40,
161 +       LIS302DL_CTRL2_SIM              = 0x80,
162 +};
163  enum lis302dl_reg_ctrl3 {
164         LIS302DL_CTRL3_PP_OD            = 0x40,
165         LIS302DL_CTRL3_IHL              = 0x80,
166 -- 
167 1.5.6.3
168