[ar71xx] fix GPIO function select bit definitions (based on a patch by Jonas <jmajau...
[openwrt.git] / target / linux / s3c24xx / patches-2.6.26 / 1166-fix-pcf50633-use-i2c-bulk-autoincrement.patch.patch
1 From cc770a67d483a63e98be55c15f08d97ed5599230 Mon Sep 17 00:00:00 2001
2 From: Andy Green <andy@openmoko.com>
3 Date: Fri, 25 Jul 2008 23:06:12 +0100
4 Subject: [PATCH] fix-pcf50633-use-i2c-bulk-autoincrement.patch
5
6 Simplify and speed up bulk sequential I2C actions in pcf50633
7 the time savings are pretty considerable and so is the simplification
8
9 Signed-off-by: Andy Green <andy@openmoko.com>
10 ---
11 drivers/i2c/chips/pcf50633.c | 125 +++++++++++++++++++++++++-----------------
12 1 files changed, 75 insertions(+), 50 deletions(-)
13
14 diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
15 index 0406767..645cbbb 100644
16 --- a/drivers/i2c/chips/pcf50633.c
17 +++ b/drivers/i2c/chips/pcf50633.c
18 @@ -156,14 +156,14 @@ struct pcf50633_data {
19
20 #ifdef CONFIG_PM
21 struct {
22 - u_int8_t int1m, int2m, int3m, int4m, int5m;
23 u_int8_t ooctim2;
24 - u_int8_t autoout, autoena, automxc;
25 - u_int8_t down1out, down1mxc;
26 - u_int8_t down2out, down2ena;
27 - u_int8_t memldoout, memldoena;
28 - u_int8_t ledout, ledena, leddim;
29 - u_int8_t ldo[__NUM_PCF50633_REGS][2];
30 + /* enables are always [1] below
31 + * I2C has limit of 32 sequential regs, so done in two lumps
32 + * because it covers 33 register extent otherwise
33 + */
34 + u_int8_t misc[PCF50633_REG_LEDDIM - PCF50633_REG_AUTOOUT + 1];
35 + /* skip 1 reserved reg here */
36 + u_int8_t ldo[PCF50633_REG_HCLDOENA - PCF50633_REG_LDO1OUT + 1];
37 } standby_regs;
38
39 struct resume_dependency resume_dependency;
40 @@ -1734,9 +1734,13 @@ static int pcf50633bl_set_intensity(struct backlight_device *bd)
41 u_int8_t ledena = 2;
42 int ret;
43
44 - if (bd->props.power != FB_BLANK_UNBLANK)
45 - intensity = 0;
46 - if (bd->props.fb_blank != FB_BLANK_UNBLANK)
47 + dev_info(&pcf->client.dev, "pcf50633bl_set_intensity\n");
48 +
49 + if (!(reg_read(pcf, PCF50633_REG_LEDENA) & 1))
50 + old_intensity = 0;
51 +
52 + if ((bd->props.power != FB_BLANK_UNBLANK) ||
53 + (bd->props.fb_blank != FB_BLANK_UNBLANK))
54 intensity = 0;
55
56 /* The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
57 @@ -2211,6 +2215,9 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
58 int i;
59 int ret;
60 u_int8_t tmp;
61 + u_int8_t res[5];
62 +
63 + dev_err(dev, "pcf50633_suspend\n");
64
65 /* we suspend once (!) as late as possible in the suspend sequencing */
66
67 @@ -2218,30 +2225,26 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
68 return 0;
69
70 /* The general idea is to power down all unused power supplies,
71 - * and then mask all PCF50606 interrup sources but EXTONR, ONKEYF
72 + * and then mask all PCF50633 interrupt sources but EXTONR, ONKEYF
73 * and ALARM */
74
75 mutex_lock(&pcf->lock);
76
77 /* Save all registers that don't "survive" standby state */
78 pcf->standby_regs.ooctim2 = __reg_read(pcf, PCF50633_REG_OOCTIM2);
79 - pcf->standby_regs.autoout = __reg_read(pcf, PCF50633_REG_AUTOOUT);
80 - pcf->standby_regs.autoena = __reg_read(pcf, PCF50633_REG_AUTOENA);
81 - pcf->standby_regs.automxc = __reg_read(pcf, PCF50633_REG_AUTOMXC);
82 - pcf->standby_regs.down1out = __reg_read(pcf, PCF50633_REG_DOWN1OUT);
83 - pcf->standby_regs.down1mxc = __reg_read(pcf, PCF50633_REG_DOWN1MXC);
84 - pcf->standby_regs.down2out = __reg_read(pcf, PCF50633_REG_DOWN2OUT);
85 - pcf->standby_regs.down2ena = __reg_read(pcf, PCF50633_REG_DOWN2ENA);
86 - pcf->standby_regs.memldoout = __reg_read(pcf, PCF50633_REG_MEMLDOOUT);
87 - pcf->standby_regs.memldoena = __reg_read(pcf, PCF50633_REG_MEMLDOENA);
88 - pcf->standby_regs.ledout = __reg_read(pcf, PCF50633_REG_LEDOUT);
89 - pcf->standby_regs.ledena = __reg_read(pcf, PCF50633_REG_LEDENA);
90 - pcf->standby_regs.leddim = __reg_read(pcf, PCF50633_REG_LEDDIM);
91 +
92 + ret = i2c_smbus_read_i2c_block_data(&pcf->client,
93 + PCF50633_REG_AUTOOUT,
94 + sizeof(pcf->standby_regs.misc),
95 + &pcf->standby_regs.misc[0]);
96 + if (ret != 18)
97 + dev_err(dev, "Failed to save misc levels and enables :-(\n");
98
99 /* regulator voltages and enable states */
100 ret = i2c_smbus_read_i2c_block_data(&pcf->client,
101 - PCF50633_REG_LDO1OUT, 14,
102 - &pcf->standby_regs.ldo[0][0]);
103 + PCF50633_REG_LDO1OUT,
104 + sizeof(pcf->standby_regs.ldo),
105 + &pcf->standby_regs.ldo[0]);
106 if (ret != 14)
107 dev_err(dev, "Failed to save LDO levels and enables :-(\n");
108
109 @@ -2251,11 +2254,16 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
110 continue;
111
112 dev_dbg(dev, "disabling regulator %u\n", i);
113 - /* we cannot use pcf50633_onoff_set() because we're
114 - * already under the mutex */
115 - tmp = __reg_read(pcf, regulator_registers[i]+1);
116 - tmp &= 0xfe;
117 - __reg_write(pcf, regulator_registers[i]+1, tmp);
118 +
119 + /* we can save ourselves the read part of a read-modify-write
120 + * here because we captured all these already
121 + */
122 + if (i < 4)
123 + tmp = pcf->standby_regs.misc[i * 4 + 1];
124 + else
125 + tmp = pcf->standby_regs.ldo[(i - 4) * 2 + 1];
126 +
127 + __reg_write(pcf, regulator_registers[i] + 1, tmp & 0xfe);
128 }
129
130 /* turn off the backlight */
131 @@ -2266,11 +2274,14 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
132 /* set interrupt masks so only those sources we want to wake
133 * us are able to
134 */
135 - __reg_write(pcf, PCF50633_REG_INT1M, ~pcf->pdata->resumers[0]);
136 - __reg_write(pcf, PCF50633_REG_INT2M, ~pcf->pdata->resumers[1]);
137 - __reg_write(pcf, PCF50633_REG_INT3M, ~pcf->pdata->resumers[2]);
138 - __reg_write(pcf, PCF50633_REG_INT4M, ~pcf->pdata->resumers[3]);
139 - __reg_write(pcf, PCF50633_REG_INT5M, ~pcf->pdata->resumers[4]);
140 + for (i = 0; i < 5; i++)
141 + res[i] = ~pcf->pdata->resumers[i];
142 +
143 + ret = i2c_smbus_write_i2c_block_data(&pcf->client,
144 + PCF50633_REG_INT1M,
145 + 5, &res[0]);
146 + if (ret)
147 + dev_err(dev, "Failed to set wake masks :-( %d\n", ret);
148
149 pcf->have_been_suspended = 1;
150
151 @@ -2302,9 +2313,12 @@ EXPORT_SYMBOL_GPL(pcf50633_ready);
152 void pcf50633_backlight_resume(struct pcf50633_data *pcf)
153 {
154 /* we force the backlight on in fact */
155 - __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout);
156 - __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena | 0x01);
157 - __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim);
158 + __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.misc[
159 + PCF50633_REG_LEDOUT - PCF50633_REG_AUTOOUT]);
160 + __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.misc[
161 + PCF50633_REG_LEDENA - PCF50633_REG_AUTOOUT] | 1);
162 + __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.misc[
163 + PCF50633_REG_LEDDIM - PCF50633_REG_AUTOOUT]);
164 }
165 EXPORT_SYMBOL_GPL(pcf50633_backlight_resume);
166
167 @@ -2314,7 +2328,10 @@ static int pcf50633_resume(struct device *dev)
168 struct i2c_client *client = to_i2c_client(dev);
169 struct pcf50633_data *pcf = i2c_get_clientdata(client);
170 int ret;
171 + u8 res[5];
172
173 + dev_info(dev, "pcf50633_resume suspended on entry = %d\n",
174 + pcf->have_been_suspended);
175 mutex_lock(&pcf->lock);
176
177 pcf->have_been_suspended = 2; /* resuming */
178 @@ -2322,14 +2339,14 @@ static int pcf50633_resume(struct device *dev)
179 /* these guys get reset while pcf50633 is suspend state, refresh */
180
181 __reg_write(pcf, PCF50633_REG_OOCTIM2, pcf->standby_regs.ooctim2);
182 - __reg_write(pcf, PCF50633_REG_AUTOOUT, pcf->standby_regs.autoout);
183 - __reg_write(pcf, PCF50633_REG_AUTOMXC, pcf->standby_regs.automxc);
184 - __reg_write(pcf, PCF50633_REG_DOWN1OUT, pcf->standby_regs.down1out);
185 - __reg_write(pcf, PCF50633_REG_DOWN1MXC, pcf->standby_regs.down1mxc);
186 - __reg_write(pcf, PCF50633_REG_DOWN2OUT, pcf->standby_regs.down2out);
187 - __reg_write(pcf, PCF50633_REG_DOWN2ENA, pcf->standby_regs.down2ena);
188 - __reg_write(pcf, PCF50633_REG_MEMLDOOUT, pcf->standby_regs.memldoout);
189 - __reg_write(pcf, PCF50633_REG_MEMLDOENA, pcf->standby_regs.memldoena);
190 +
191 + /* regulator voltages and enable states */
192 + ret = i2c_smbus_write_i2c_block_data(&pcf->client,
193 + PCF50633_REG_AUTOOUT,
194 + sizeof(pcf->standby_regs.misc) - 4,
195 + &pcf->standby_regs.misc[0]);
196 + if (ret)
197 + dev_err(dev, "Failed to restore misc :-( %d\n", ret);
198
199 /* platform can choose to defer backlight bringup */
200 if (!pcf->pdata->defer_resume_backlight)
201 @@ -2337,14 +2354,22 @@ static int pcf50633_resume(struct device *dev)
202
203 /* regulator voltages and enable states */
204 ret = i2c_smbus_write_i2c_block_data(&pcf->client,
205 - PCF50633_REG_LDO1OUT, 14,
206 - &pcf->standby_regs.ldo[0][0]);
207 + PCF50633_REG_LDO1OUT,
208 + sizeof(pcf->standby_regs.ldo),
209 + &pcf->standby_regs.ldo[0]);
210 if (ret)
211 dev_err(dev, "Failed to restore LDOs :-( %d\n", ret);
212
213 - mutex_unlock(&pcf->lock);
214 + memset(res, 0, sizeof(res));
215 + ret = i2c_smbus_write_i2c_block_data(&pcf->client,
216 + PCF50633_REG_INT1M,
217 + 5, &res[0]);
218 + if (ret)
219 + dev_err(dev, "Failed to set int masks :-( %d\n", ret);
220
221 - pcf50633_irq(pcf->irq, pcf);
222 + pcf->have_been_suspended = 3; /* resume completed */
223 +
224 + mutex_unlock(&pcf->lock);
225
226 callback_all_resume_dependencies(&pcf->resume_dependency);
227
228 --
229 1.5.6.3
230
This page took 0.055021 seconds and 5 git commands to generate.