Commit | Line | Data |
---|---|---|
79e53945 JB |
1 | /* |
2 | * Copyright (c) 2006 Dave Airlie <airlied@linux.ie> | |
f899fc64 | 3 | * Copyright © 2006-2008,2010 Intel Corporation |
79e53945 JB |
4 | * Jesse Barnes <jesse.barnes@intel.com> |
5 | * | |
6 | * Permission is hereby granted, free of charge, to any person obtaining a | |
7 | * copy of this software and associated documentation files (the "Software"), | |
8 | * to deal in the Software without restriction, including without limitation | |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
10 | * and/or sell copies of the Software, and to permit persons to whom the | |
11 | * Software is furnished to do so, subject to the following conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice (including the next | |
14 | * paragraph) shall be included in all copies or substantial portions of the | |
15 | * Software. | |
16 | * | |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
23 | * DEALINGS IN THE SOFTWARE. | |
24 | * | |
25 | * Authors: | |
26 | * Eric Anholt <eric@anholt.net> | |
f899fc64 | 27 | * Chris Wilson <chris@chris-wilson.co.uk> |
79e53945 JB |
28 | */ |
29 | #include <linux/i2c.h> | |
79e53945 | 30 | #include <linux/i2c-algo-bit.h> |
2d1a8a48 | 31 | #include <linux/export.h> |
79e53945 JB |
32 | #include "drmP.h" |
33 | #include "drm.h" | |
34 | #include "intel_drv.h" | |
35 | #include "i915_drm.h" | |
36 | #include "i915_drv.h" | |
37 | ||
f899fc64 CW |
38 | /* Intel GPIO access functions */ |
39 | ||
1849ecb2 | 40 | #define I2C_RISEFALL_TIME 10 |
f899fc64 | 41 | |
e957d772 CW |
42 | static inline struct intel_gmbus * |
43 | to_intel_gmbus(struct i2c_adapter *i2c) | |
44 | { | |
45 | return container_of(i2c, struct intel_gmbus, adapter); | |
46 | } | |
47 | ||
f899fc64 CW |
48 | void |
49 | intel_i2c_reset(struct drm_device *dev) | |
0ba0e9e1 SL |
50 | { |
51 | struct drm_i915_private *dev_priv = dev->dev_private; | |
110447fc | 52 | I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0); |
f899fc64 CW |
53 | } |
54 | ||
55 | static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) | |
56 | { | |
b222f267 | 57 | u32 val; |
0ba0e9e1 SL |
58 | |
59 | /* When using bit bashing for I2C, this bit needs to be set to 1 */ | |
f899fc64 | 60 | if (!IS_PINEVIEW(dev_priv->dev)) |
0ba0e9e1 | 61 | return; |
b222f267 CW |
62 | |
63 | val = I915_READ(DSPCLK_GATE_D); | |
0ba0e9e1 | 64 | if (enable) |
b222f267 | 65 | val |= DPCUNIT_CLOCK_GATE_DISABLE; |
0ba0e9e1 | 66 | else |
b222f267 CW |
67 | val &= ~DPCUNIT_CLOCK_GATE_DISABLE; |
68 | I915_WRITE(DSPCLK_GATE_D, val); | |
0ba0e9e1 SL |
69 | } |
70 | ||
36c785f0 | 71 | static u32 get_reserved(struct intel_gmbus *bus) |
e957d772 | 72 | { |
36c785f0 | 73 | struct drm_i915_private *dev_priv = bus->dev_priv; |
e957d772 CW |
74 | struct drm_device *dev = dev_priv->dev; |
75 | u32 reserved = 0; | |
76 | ||
77 | /* On most chips, these bits must be preserved in software. */ | |
78 | if (!IS_I830(dev) && !IS_845G(dev)) | |
36c785f0 | 79 | reserved = I915_READ_NOTRACE(bus->gpio_reg) & |
db5e4172 YL |
80 | (GPIO_DATA_PULLUP_DISABLE | |
81 | GPIO_CLOCK_PULLUP_DISABLE); | |
e957d772 CW |
82 | |
83 | return reserved; | |
84 | } | |
85 | ||
79e53945 JB |
86 | static int get_clock(void *data) |
87 | { | |
36c785f0 DV |
88 | struct intel_gmbus *bus = data; |
89 | struct drm_i915_private *dev_priv = bus->dev_priv; | |
90 | u32 reserved = get_reserved(bus); | |
91 | I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK); | |
92 | I915_WRITE_NOTRACE(bus->gpio_reg, reserved); | |
93 | return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0; | |
79e53945 JB |
94 | } |
95 | ||
96 | static int get_data(void *data) | |
97 | { | |
36c785f0 DV |
98 | struct intel_gmbus *bus = data; |
99 | struct drm_i915_private *dev_priv = bus->dev_priv; | |
100 | u32 reserved = get_reserved(bus); | |
101 | I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK); | |
102 | I915_WRITE_NOTRACE(bus->gpio_reg, reserved); | |
103 | return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0; | |
79e53945 JB |
104 | } |
105 | ||
106 | static void set_clock(void *data, int state_high) | |
107 | { | |
36c785f0 DV |
108 | struct intel_gmbus *bus = data; |
109 | struct drm_i915_private *dev_priv = bus->dev_priv; | |
110 | u32 reserved = get_reserved(bus); | |
e957d772 | 111 | u32 clock_bits; |
79e53945 JB |
112 | |
113 | if (state_high) | |
114 | clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; | |
115 | else | |
116 | clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | | |
117 | GPIO_CLOCK_VAL_MASK; | |
f899fc64 | 118 | |
36c785f0 DV |
119 | I915_WRITE_NOTRACE(bus->gpio_reg, reserved | clock_bits); |
120 | POSTING_READ(bus->gpio_reg); | |
79e53945 JB |
121 | } |
122 | ||
123 | static void set_data(void *data, int state_high) | |
124 | { | |
36c785f0 DV |
125 | struct intel_gmbus *bus = data; |
126 | struct drm_i915_private *dev_priv = bus->dev_priv; | |
127 | u32 reserved = get_reserved(bus); | |
e957d772 | 128 | u32 data_bits; |
79e53945 JB |
129 | |
130 | if (state_high) | |
131 | data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; | |
132 | else | |
133 | data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | | |
134 | GPIO_DATA_VAL_MASK; | |
135 | ||
36c785f0 DV |
136 | I915_WRITE_NOTRACE(bus->gpio_reg, reserved | data_bits); |
137 | POSTING_READ(bus->gpio_reg); | |
79e53945 JB |
138 | } |
139 | ||
f6f808c8 DV |
140 | static bool |
141 | intel_gpio_setup(struct intel_gmbus *bus, u32 pin) | |
f0217c42 | 142 | { |
36c785f0 | 143 | struct drm_i915_private *dev_priv = bus->dev_priv; |
f899fc64 CW |
144 | static const int map_pin_to_reg[] = { |
145 | 0, | |
146 | GPIOB, | |
147 | GPIOA, | |
148 | GPIOC, | |
149 | GPIOD, | |
150 | GPIOE, | |
151 | GPIOF, | |
e4fd17af | 152 | 0, |
f899fc64 | 153 | }; |
36c785f0 | 154 | struct i2c_algo_bit_data *algo; |
f0217c42 | 155 | |
69669455 | 156 | if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin]) |
f6f808c8 | 157 | return false; |
f0217c42 | 158 | |
c167a6fc | 159 | algo = &bus->bit_algo; |
36c785f0 DV |
160 | |
161 | bus->gpio_reg = map_pin_to_reg[pin]; | |
110447fc | 162 | bus->gpio_reg += dev_priv->gpio_mmio_base; |
79e53945 | 163 | |
c167a6fc | 164 | bus->adapter.algo_data = algo; |
36c785f0 DV |
165 | algo->setsda = set_data; |
166 | algo->setscl = set_clock; | |
167 | algo->getsda = get_data; | |
168 | algo->getscl = get_clock; | |
169 | algo->udelay = I2C_RISEFALL_TIME; | |
170 | algo->timeout = usecs_to_jiffies(2200); | |
171 | algo->data = bus; | |
172 | ||
f6f808c8 | 173 | return true; |
79e53945 JB |
174 | } |
175 | ||
f899fc64 | 176 | static int |
36c785f0 | 177 | intel_i2c_quirk_xfer(struct intel_gmbus *bus, |
e957d772 CW |
178 | struct i2c_msg *msgs, |
179 | int num) | |
f899fc64 | 180 | { |
36c785f0 | 181 | struct drm_i915_private *dev_priv = bus->dev_priv; |
f899fc64 CW |
182 | int ret; |
183 | ||
184 | intel_i2c_reset(dev_priv->dev); | |
185 | ||
186 | intel_i2c_quirk_set(dev_priv, true); | |
36c785f0 DV |
187 | set_data(bus, 1); |
188 | set_clock(bus, 1); | |
e957d772 CW |
189 | udelay(I2C_RISEFALL_TIME); |
190 | ||
f6f808c8 | 191 | ret = i2c_bit_algo.master_xfer(&bus->adapter, msgs, num); |
e957d772 | 192 | |
36c785f0 DV |
193 | set_data(bus, 1); |
194 | set_clock(bus, 1); | |
f899fc64 CW |
195 | intel_i2c_quirk_set(dev_priv, false); |
196 | ||
197 | return ret; | |
198 | } | |
199 | ||
924a93ed DK |
200 | static int |
201 | gmbus_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 | ||
235 | static int | |
236 | gmbus_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 | ||
f899fc64 CW |
276 | static int |
277 | gmbus_xfer(struct i2c_adapter *adapter, | |
278 | struct i2c_msg *msgs, | |
279 | int num) | |
280 | { | |
281 | struct intel_gmbus *bus = container_of(adapter, | |
282 | struct intel_gmbus, | |
283 | adapter); | |
c2b9152f | 284 | struct drm_i915_private *dev_priv = bus->dev_priv; |
8a8ed1f5 | 285 | int i, reg_offset, ret; |
f899fc64 | 286 | |
8a8ed1f5 YS |
287 | mutex_lock(&dev_priv->gmbus_mutex); |
288 | ||
289 | if (bus->force_bit) { | |
f6f808c8 | 290 | ret = intel_i2c_quirk_xfer(bus, msgs, num); |
8a8ed1f5 YS |
291 | goto out; |
292 | } | |
f899fc64 | 293 | |
110447fc | 294 | reg_offset = dev_priv->gpio_mmio_base; |
f899fc64 | 295 | |
e957d772 | 296 | I915_WRITE(GMBUS0 + reg_offset, bus->reg0); |
f899fc64 CW |
297 | |
298 | for (i = 0; i < num; i++) { | |
924a93ed DK |
299 | bool last = i + 1 == num; |
300 | ||
301 | if (msgs[i].flags & I2C_M_RD) | |
302 | ret = gmbus_xfer_read(dev_priv, &msgs[i], last); | |
303 | else | |
304 | ret = gmbus_xfer_write(dev_priv, &msgs[i], last); | |
305 | ||
306 | if (ret == -ETIMEDOUT) | |
307 | goto timeout; | |
308 | if (ret == -ENXIO) | |
309 | goto clear_err; | |
310 | ||
311 | if (!last && | |
312 | wait_for(I915_READ(GMBUS2 + reg_offset) & | |
313 | (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), | |
314 | 50)) | |
f899fc64 CW |
315 | goto timeout; |
316 | if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) | |
7f58aabc | 317 | goto clear_err; |
f899fc64 CW |
318 | } |
319 | ||
7f58aabc CW |
320 | goto done; |
321 | ||
322 | clear_err: | |
323 | /* Toggle the Software Clear Interrupt bit. This has the effect | |
324 | * of resetting the GMBUS controller and so clearing the | |
325 | * BUS_ERROR raised by the slave's NAK. | |
326 | */ | |
327 | I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT); | |
328 | I915_WRITE(GMBUS1 + reg_offset, 0); | |
329 | ||
330 | done: | |
caae745a BL |
331 | /* Mark the GMBUS interface as disabled after waiting for idle. |
332 | * We will re-enable it at the start of the next xfer, | |
333 | * till then let it sleep. | |
7f58aabc | 334 | */ |
caae745a | 335 | if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10)) |
874e3cc9 DK |
336 | DRM_INFO("GMBUS [%s] timed out waiting for idle\n", |
337 | bus->adapter.name); | |
7f58aabc | 338 | I915_WRITE(GMBUS0 + reg_offset, 0); |
8a8ed1f5 YS |
339 | ret = i; |
340 | goto out; | |
f899fc64 CW |
341 | |
342 | timeout: | |
874e3cc9 DK |
343 | DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n", |
344 | bus->adapter.name, bus->reg0 & 0xff); | |
7f58aabc CW |
345 | I915_WRITE(GMBUS0 + reg_offset, 0); |
346 | ||
874e3cc9 DK |
347 | /* Hardware may not support GMBUS over these pins? |
348 | * Try GPIO bitbanging instead. | |
349 | */ | |
f6f808c8 DV |
350 | if (!bus->has_gpio) { |
351 | ret = -EIO; | |
352 | } else { | |
353 | bus->force_bit = true; | |
354 | ret = intel_i2c_quirk_xfer(bus, msgs, num); | |
355 | } | |
8a8ed1f5 YS |
356 | out: |
357 | mutex_unlock(&dev_priv->gmbus_mutex); | |
358 | return ret; | |
f899fc64 CW |
359 | } |
360 | ||
361 | static u32 gmbus_func(struct i2c_adapter *adapter) | |
362 | { | |
f6f808c8 DV |
363 | return i2c_bit_algo.functionality(adapter) & |
364 | (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | | |
f899fc64 CW |
365 | /* I2C_FUNC_10BIT_ADDR | */ |
366 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | | |
367 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL); | |
368 | } | |
369 | ||
370 | static const struct i2c_algorithm gmbus_algorithm = { | |
371 | .master_xfer = gmbus_xfer, | |
372 | .functionality = gmbus_func | |
373 | }; | |
374 | ||
79e53945 | 375 | /** |
f899fc64 CW |
376 | * intel_gmbus_setup - instantiate all Intel i2c GMBuses |
377 | * @dev: DRM device | |
79e53945 | 378 | */ |
f899fc64 CW |
379 | int intel_setup_gmbus(struct drm_device *dev) |
380 | { | |
e957d772 | 381 | static const char *names[GMBUS_NUM_PORTS] = { |
f899fc64 CW |
382 | "disabled", |
383 | "ssc", | |
384 | "vga", | |
385 | "panel", | |
386 | "dpc", | |
387 | "dpb", | |
e957d772 | 388 | "dpd", |
e4fd17af | 389 | "reserved", |
f899fc64 CW |
390 | }; |
391 | struct drm_i915_private *dev_priv = dev->dev_private; | |
392 | int ret, i; | |
393 | ||
110447fc DV |
394 | if (HAS_PCH_SPLIT(dev)) |
395 | dev_priv->gpio_mmio_base = PCH_GPIOA - GPIOA; | |
396 | else | |
397 | dev_priv->gpio_mmio_base = 0; | |
398 | ||
51a59ac8 | 399 | dev_priv->gmbus = kcalloc(GMBUS_NUM_PORTS, sizeof(struct intel_gmbus), |
f899fc64 CW |
400 | GFP_KERNEL); |
401 | if (dev_priv->gmbus == NULL) | |
402 | return -ENOMEM; | |
403 | ||
8a8ed1f5 YS |
404 | mutex_init(&dev_priv->gmbus_mutex); |
405 | ||
f899fc64 CW |
406 | for (i = 0; i < GMBUS_NUM_PORTS; i++) { |
407 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; | |
408 | ||
409 | bus->adapter.owner = THIS_MODULE; | |
410 | bus->adapter.class = I2C_CLASS_DDC; | |
411 | snprintf(bus->adapter.name, | |
69669455 JD |
412 | sizeof(bus->adapter.name), |
413 | "i915 gmbus %s", | |
f899fc64 CW |
414 | names[i]); |
415 | ||
416 | bus->adapter.dev.parent = &dev->pdev->dev; | |
c2b9152f | 417 | bus->dev_priv = dev_priv; |
f899fc64 CW |
418 | |
419 | bus->adapter.algo = &gmbus_algorithm; | |
420 | ret = i2c_add_adapter(&bus->adapter); | |
421 | if (ret) | |
422 | goto err; | |
423 | ||
e957d772 CW |
424 | /* By default use a conservative clock rate */ |
425 | bus->reg0 = i | GMBUS_RATE_100KHZ; | |
cb8ea752 | 426 | |
f6f808c8 | 427 | bus->has_gpio = intel_gpio_setup(bus, i); |
f899fc64 CW |
428 | } |
429 | ||
430 | intel_i2c_reset(dev_priv->dev); | |
431 | ||
432 | return 0; | |
433 | ||
434 | err: | |
435 | while (--i) { | |
436 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; | |
437 | i2c_del_adapter(&bus->adapter); | |
438 | } | |
439 | kfree(dev_priv->gmbus); | |
440 | dev_priv->gmbus = NULL; | |
441 | return ret; | |
442 | } | |
443 | ||
e957d772 CW |
444 | void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) |
445 | { | |
446 | struct intel_gmbus *bus = to_intel_gmbus(adapter); | |
447 | ||
d5090b96 | 448 | bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | speed; |
e957d772 CW |
449 | } |
450 | ||
451 | void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) | |
452 | { | |
453 | struct intel_gmbus *bus = to_intel_gmbus(adapter); | |
454 | ||
f6f808c8 DV |
455 | if (bus->has_gpio) |
456 | bus->force_bit = force_bit; | |
e957d772 CW |
457 | } |
458 | ||
f899fc64 | 459 | void intel_teardown_gmbus(struct drm_device *dev) |
79e53945 | 460 | { |
f899fc64 CW |
461 | struct drm_i915_private *dev_priv = dev->dev_private; |
462 | int i; | |
f9c10a9b | 463 | |
f899fc64 | 464 | if (dev_priv->gmbus == NULL) |
79e53945 JB |
465 | return; |
466 | ||
f899fc64 CW |
467 | for (i = 0; i < GMBUS_NUM_PORTS; i++) { |
468 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; | |
f899fc64 CW |
469 | i2c_del_adapter(&bus->adapter); |
470 | } | |
471 | ||
472 | kfree(dev_priv->gmbus); | |
473 | dev_priv->gmbus = NULL; | |
79e53945 | 474 | } |