aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Kurtz <djkurtz@chromium.org>2012-03-27 14:36:10 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-03-28 03:23:37 -0400
commit924a93edc96b7f7e08a0af7a2f9afe4827bab103 (patch)
tree929ff22346337429f61291b0e910dc6186298f9f
parente7e58eb5c0d1d7d1a42fcb2b5a247d28ec08b47e (diff)
drm/i915/intel_i2c: refactor gmbus_xfer
Split out gmbus_xfer_read/write() helper functions. Signed-off-by: Daniel Kurtz <djkurtz@chromium.org> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c151
1 files changed, 92 insertions, 59 deletions
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 0713cc289119..30675ce18056 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -198,6 +198,82 @@ intel_i2c_quirk_xfer(struct intel_gmbus *bus,
198} 198}
199 199
200static int 200static int
201gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
202 bool last)
203{
204 int reg_offset = dev_priv->gpio_mmio_base;
205 u16 len = msg->len;
206 u8 *buf = msg->buf;
207
208 I915_WRITE(GMBUS1 + reg_offset,
209 GMBUS_CYCLE_WAIT |
210 (last ? GMBUS_CYCLE_STOP : 0) |
211 (len << GMBUS_BYTE_COUNT_SHIFT) |
212 (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
213 GMBUS_SLAVE_READ | GMBUS_SW_RDY);
214 POSTING_READ(GMBUS2 + reg_offset);
215 do {
216 u32 val, loop = 0;
217
218 if (wait_for(I915_READ(GMBUS2 + reg_offset) &
219 (GMBUS_SATOER | GMBUS_HW_RDY),
220 50))
221 return -ETIMEDOUT;
222 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
223 return -ENXIO;
224
225 val = I915_READ(GMBUS3 + reg_offset);
226 do {
227 *buf++ = val & 0xff;
228 val >>= 8;
229 } while (--len && ++loop < 4);
230 } while (len);
231
232 return 0;
233}
234
235static int
236gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
237 bool last)
238{
239 int reg_offset = dev_priv->gpio_mmio_base;
240 u16 len = msg->len;
241 u8 *buf = msg->buf;
242 u32 val, loop;
243
244 val = loop = 0;
245 do {
246 val |= *buf++ << (8 * loop);
247 } while (--len && ++loop < 4);
248
249 I915_WRITE(GMBUS3 + reg_offset, val);
250 I915_WRITE(GMBUS1 + reg_offset,
251 GMBUS_CYCLE_WAIT |
252 (last ? GMBUS_CYCLE_STOP : 0) |
253 (msg->len << GMBUS_BYTE_COUNT_SHIFT) |
254 (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
255 GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
256 POSTING_READ(GMBUS2 + reg_offset);
257 while (len) {
258 if (wait_for(I915_READ(GMBUS2 + reg_offset) &
259 (GMBUS_SATOER | GMBUS_HW_RDY),
260 50))
261 return -ETIMEDOUT;
262 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
263 return -ENXIO;
264
265 val = loop = 0;
266 do {
267 val |= *buf++ << (8 * loop);
268 } while (--len && ++loop < 4);
269
270 I915_WRITE(GMBUS3 + reg_offset, val);
271 POSTING_READ(GMBUS2 + reg_offset);
272 }
273 return 0;
274}
275
276static int
201gmbus_xfer(struct i2c_adapter *adapter, 277gmbus_xfer(struct i2c_adapter *adapter,
202 struct i2c_msg *msgs, 278 struct i2c_msg *msgs,
203 int num) 279 int num)
@@ -220,65 +296,22 @@ gmbus_xfer(struct i2c_adapter *adapter,
220 I915_WRITE(GMBUS0 + reg_offset, bus->reg0); 296 I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
221 297
222 for (i = 0; i < num; i++) { 298 for (i = 0; i < num; i++) {
223 u16 len = msgs[i].len; 299 bool last = i + 1 == num;
224 u8 *buf = msgs[i].buf; 300
225 301 if (msgs[i].flags & I2C_M_RD)
226 if (msgs[i].flags & I2C_M_RD) { 302 ret = gmbus_xfer_read(dev_priv, &msgs[i], last);
227 I915_WRITE(GMBUS1 + reg_offset, 303 else
228 GMBUS_CYCLE_WAIT | 304 ret = gmbus_xfer_write(dev_priv, &msgs[i], last);
229 (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | 305
230 (len << GMBUS_BYTE_COUNT_SHIFT) | 306 if (ret == -ETIMEDOUT)
231 (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | 307 goto timeout;
232 GMBUS_SLAVE_READ | GMBUS_SW_RDY); 308 if (ret == -ENXIO)
233 POSTING_READ(GMBUS2+reg_offset); 309 goto clear_err;
234 do { 310
235 u32 val, loop = 0; 311 if (!last &&
236 312 wait_for(I915_READ(GMBUS2 + reg_offset) &
237 if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) 313 (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE),
238 goto timeout; 314 50))
239 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
240 goto clear_err;
241
242 val = I915_READ(GMBUS3 + reg_offset);
243 do {
244 *buf++ = val & 0xff;
245 val >>= 8;
246 } while (--len && ++loop < 4);
247 } while (len);
248 } else {
249 u32 val, loop;
250
251 val = loop = 0;
252 do {
253 val |= *buf++ << (8 * loop);
254 } while (--len && ++loop < 4);
255
256 I915_WRITE(GMBUS3 + reg_offset, val);
257 I915_WRITE(GMBUS1 + reg_offset,
258 GMBUS_CYCLE_WAIT |
259 (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
260 (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) |
261 (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
262 GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
263 POSTING_READ(GMBUS2+reg_offset);
264
265 while (len) {
266 if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
267 goto timeout;
268 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
269 goto clear_err;
270
271 val = loop = 0;
272 do {
273 val |= *buf++ << (8 * loop);
274 } while (--len && ++loop < 4);
275
276 I915_WRITE(GMBUS3 + reg_offset, val);
277 POSTING_READ(GMBUS2+reg_offset);
278 }
279 }
280
281 if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50))
282 goto timeout; 315 goto timeout;
283 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) 316 if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
284 goto clear_err; 317 goto clear_err;