xref: /dflybsd-src/sys/dev/drm/i915/intel_i2c.c (revision 352ff8bd644eb2f17a1b01fa757342a01f012051)
1bad0eccaSFrançois Tigeot /*
2bad0eccaSFrançois Tigeot  * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
3bad0eccaSFrançois Tigeot  * Copyright © 2006-2008,2010 Intel Corporation
4bad0eccaSFrançois Tigeot  *   Jesse Barnes <jesse.barnes@intel.com>
5bad0eccaSFrançois Tigeot  *
6bad0eccaSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
7bad0eccaSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
8bad0eccaSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
9bad0eccaSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10bad0eccaSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
11bad0eccaSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
12bad0eccaSFrançois Tigeot  *
13bad0eccaSFrançois Tigeot  * The above copyright notice and this permission notice (including the next
14bad0eccaSFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
15bad0eccaSFrançois Tigeot  * Software.
16bad0eccaSFrançois Tigeot  *
17bad0eccaSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18bad0eccaSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19bad0eccaSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20bad0eccaSFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21bad0eccaSFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22bad0eccaSFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23bad0eccaSFrançois Tigeot  * DEALINGS IN THE SOFTWARE.
24bad0eccaSFrançois Tigeot  *
25bad0eccaSFrançois Tigeot  * Authors:
26bad0eccaSFrançois Tigeot  *	Eric Anholt <eric@anholt.net>
27bad0eccaSFrançois Tigeot  *	Chris Wilson <chris@chris-wilson.co.uk>
28bad0eccaSFrançois Tigeot  *
29bad0eccaSFrançois Tigeot  * Copyright (c) 2011 The FreeBSD Foundation
30bad0eccaSFrançois Tigeot  * All rights reserved.
31bad0eccaSFrançois Tigeot  *
32bad0eccaSFrançois Tigeot  * This software was developed by Konstantin Belousov under sponsorship from
33bad0eccaSFrançois Tigeot  * the FreeBSD Foundation.
34bad0eccaSFrançois Tigeot  *
35bad0eccaSFrançois Tigeot  * Redistribution and use in source and binary forms, with or without
36bad0eccaSFrançois Tigeot  * modification, are permitted provided that the following conditions
37bad0eccaSFrançois Tigeot  * are met:
38bad0eccaSFrançois Tigeot  * 1. Redistributions of source code must retain the above copyright
39bad0eccaSFrançois Tigeot  *    notice, this list of conditions and the following disclaimer.
40bad0eccaSFrançois Tigeot  * 2. Redistributions in binary form must reproduce the above copyright
41bad0eccaSFrançois Tigeot  *    notice, this list of conditions and the following disclaimer in the
42bad0eccaSFrançois Tigeot  *    documentation and/or other materials provided with the distribution.
43bad0eccaSFrançois Tigeot  *
44bad0eccaSFrançois Tigeot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
45bad0eccaSFrançois Tigeot  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46bad0eccaSFrançois Tigeot  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47bad0eccaSFrançois Tigeot  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
48bad0eccaSFrançois Tigeot  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49bad0eccaSFrançois Tigeot  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50bad0eccaSFrançois Tigeot  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51bad0eccaSFrançois Tigeot  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52bad0eccaSFrançois Tigeot  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53bad0eccaSFrançois Tigeot  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54bad0eccaSFrançois Tigeot  * SUCH DAMAGE.
55bad0eccaSFrançois Tigeot  */
56bad0eccaSFrançois Tigeot 
57bad0eccaSFrançois Tigeot #include <sys/mplock2.h>
58bad0eccaSFrançois Tigeot 
59a2fdbec6SFrançois Tigeot #include <linux/i2c.h>
60a2fdbec6SFrançois Tigeot #include <linux/export.h>
61bad0eccaSFrançois Tigeot #include <drm/drmP.h>
62a2fdbec6SFrançois Tigeot #include "intel_drv.h"
63bad0eccaSFrançois Tigeot #include <drm/i915_drm.h>
64bad0eccaSFrançois Tigeot #include "i915_drv.h"
65a2fdbec6SFrançois Tigeot 
66bad0eccaSFrançois Tigeot #include <bus/iicbus/iic.h>
67bad0eccaSFrançois Tigeot #include <bus/iicbus/iiconf.h>
68bad0eccaSFrançois Tigeot #include <bus/iicbus/iicbus.h>
69bad0eccaSFrançois Tigeot #include "iicbus_if.h"
70bad0eccaSFrançois Tigeot #include "iicbb_if.h"
71bad0eccaSFrançois Tigeot 
7219c468b4SFrançois Tigeot struct gmbus_pin {
73a2fdbec6SFrançois Tigeot 	const char *name;
74a2fdbec6SFrançois Tigeot 	int reg;
75a2fdbec6SFrançois Tigeot };
76a2fdbec6SFrançois Tigeot 
7719c468b4SFrançois Tigeot /* Map gmbus pin pairs to names and registers. */
7819c468b4SFrançois Tigeot static const struct gmbus_pin gmbus_pins[] = {
7919c468b4SFrançois Tigeot 	[GMBUS_PIN_SSC] = { "ssc", GPIOB },
8019c468b4SFrançois Tigeot 	[GMBUS_PIN_VGADDC] = { "vga", GPIOA },
8119c468b4SFrançois Tigeot 	[GMBUS_PIN_PANEL] = { "panel", GPIOC },
8219c468b4SFrançois Tigeot 	[GMBUS_PIN_DPC] = { "dpc", GPIOD },
8319c468b4SFrançois Tigeot 	[GMBUS_PIN_DPB] = { "dpb", GPIOE },
8419c468b4SFrançois Tigeot 	[GMBUS_PIN_DPD] = { "dpd", GPIOF },
85a2fdbec6SFrançois Tigeot };
86bad0eccaSFrançois Tigeot 
8719c468b4SFrançois Tigeot static const struct gmbus_pin gmbus_pins_bdw[] = {
8819c468b4SFrançois Tigeot 	[GMBUS_PIN_VGADDC] = { "vga", GPIOA },
8919c468b4SFrançois Tigeot 	[GMBUS_PIN_DPC] = { "dpc", GPIOD },
9019c468b4SFrançois Tigeot 	[GMBUS_PIN_DPB] = { "dpb", GPIOE },
9119c468b4SFrançois Tigeot 	[GMBUS_PIN_DPD] = { "dpd", GPIOF },
9219c468b4SFrançois Tigeot };
9319c468b4SFrançois Tigeot 
9419c468b4SFrançois Tigeot static const struct gmbus_pin gmbus_pins_skl[] = {
9519c468b4SFrançois Tigeot 	[GMBUS_PIN_DPC] = { "dpc", GPIOD },
9619c468b4SFrançois Tigeot 	[GMBUS_PIN_DPB] = { "dpb", GPIOE },
9719c468b4SFrançois Tigeot 	[GMBUS_PIN_DPD] = { "dpd", GPIOF },
9819c468b4SFrançois Tigeot };
9919c468b4SFrançois Tigeot 
10019c468b4SFrançois Tigeot static const struct gmbus_pin gmbus_pins_bxt[] = {
10119c468b4SFrançois Tigeot 	[GMBUS_PIN_1_BXT] = { "dpb", PCH_GPIOB },
10219c468b4SFrançois Tigeot 	[GMBUS_PIN_2_BXT] = { "dpc", PCH_GPIOC },
10319c468b4SFrançois Tigeot 	[GMBUS_PIN_3_BXT] = { "misc", PCH_GPIOD },
10419c468b4SFrançois Tigeot };
10519c468b4SFrançois Tigeot 
10619c468b4SFrançois Tigeot /* pin is expected to be valid */
10719c468b4SFrançois Tigeot static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *dev_priv,
10819c468b4SFrançois Tigeot 					     unsigned int pin)
10919c468b4SFrançois Tigeot {
11019c468b4SFrançois Tigeot 	if (IS_BROXTON(dev_priv))
11119c468b4SFrançois Tigeot 		return &gmbus_pins_bxt[pin];
11219c468b4SFrançois Tigeot 	else if (IS_SKYLAKE(dev_priv))
11319c468b4SFrançois Tigeot 		return &gmbus_pins_skl[pin];
11419c468b4SFrançois Tigeot 	else if (IS_BROADWELL(dev_priv))
11519c468b4SFrançois Tigeot 		return &gmbus_pins_bdw[pin];
11619c468b4SFrançois Tigeot 	else
11719c468b4SFrançois Tigeot 		return &gmbus_pins[pin];
11819c468b4SFrançois Tigeot }
11919c468b4SFrançois Tigeot 
12019c468b4SFrançois Tigeot bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
12119c468b4SFrançois Tigeot 			      unsigned int pin)
12219c468b4SFrançois Tigeot {
12319c468b4SFrançois Tigeot 	unsigned int size;
12419c468b4SFrançois Tigeot 
12519c468b4SFrançois Tigeot 	if (IS_BROXTON(dev_priv))
12619c468b4SFrançois Tigeot 		size = ARRAY_SIZE(gmbus_pins_bxt);
12719c468b4SFrançois Tigeot 	else if (IS_SKYLAKE(dev_priv))
12819c468b4SFrançois Tigeot 		size = ARRAY_SIZE(gmbus_pins_skl);
12919c468b4SFrançois Tigeot 	else if (IS_BROADWELL(dev_priv))
13019c468b4SFrançois Tigeot 		size = ARRAY_SIZE(gmbus_pins_bdw);
13119c468b4SFrançois Tigeot 	else
13219c468b4SFrançois Tigeot 		size = ARRAY_SIZE(gmbus_pins);
13319c468b4SFrançois Tigeot 
13419c468b4SFrançois Tigeot 	return pin < size && get_gmbus_pin(dev_priv, pin)->reg;
13519c468b4SFrançois Tigeot }
13619c468b4SFrançois Tigeot 
137bad0eccaSFrançois Tigeot /* Intel GPIO access functions */
138bad0eccaSFrançois Tigeot 
139bad0eccaSFrançois Tigeot #define I2C_RISEFALL_TIME 10
140bad0eccaSFrançois Tigeot 
141a2fdbec6SFrançois Tigeot void
142a2fdbec6SFrançois Tigeot intel_i2c_reset(struct drm_device *dev)
143a2fdbec6SFrançois Tigeot {
144a2fdbec6SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1459edbd4a0SFrançois Tigeot 
146*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS0, 0);
147*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS4, 0);
148a2fdbec6SFrançois Tigeot }
149a2fdbec6SFrançois Tigeot 
150a2fdbec6SFrançois Tigeot static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
151bad0eccaSFrançois Tigeot {
152bad0eccaSFrançois Tigeot 	u32 val;
153bad0eccaSFrançois Tigeot 
154bad0eccaSFrançois Tigeot 	/* When using bit bashing for I2C, this bit needs to be set to 1 */
155bad0eccaSFrançois Tigeot 	if (!IS_PINEVIEW(dev_priv->dev))
156bad0eccaSFrançois Tigeot 		return;
157bad0eccaSFrançois Tigeot 
158bad0eccaSFrançois Tigeot 	val = I915_READ(DSPCLK_GATE_D);
159bad0eccaSFrançois Tigeot 	if (enable)
160bad0eccaSFrançois Tigeot 		val |= DPCUNIT_CLOCK_GATE_DISABLE;
161bad0eccaSFrançois Tigeot 	else
162bad0eccaSFrançois Tigeot 		val &= ~DPCUNIT_CLOCK_GATE_DISABLE;
163bad0eccaSFrançois Tigeot 	I915_WRITE(DSPCLK_GATE_D, val);
164bad0eccaSFrançois Tigeot }
165bad0eccaSFrançois Tigeot 
166a2fdbec6SFrançois Tigeot static u32 get_reserved(device_t idev)
167a2fdbec6SFrançois Tigeot {
168a2fdbec6SFrançois Tigeot 	struct intel_iic_softc *sc = device_get_softc(idev);
169a2fdbec6SFrançois Tigeot 	struct drm_device *dev = sc->drm_dev;
170a2fdbec6SFrançois Tigeot 	struct drm_i915_private *dev_priv;
171a2fdbec6SFrançois Tigeot 	u32 reserved = 0;
172a2fdbec6SFrançois Tigeot 
173a2fdbec6SFrançois Tigeot 	dev_priv = dev->dev_private;
174a2fdbec6SFrançois Tigeot 
175a2fdbec6SFrançois Tigeot 	/* On most chips, these bits must be preserved in software. */
176a2fdbec6SFrançois Tigeot 	if (!IS_I830(dev) && !IS_845G(dev))
177a2fdbec6SFrançois Tigeot 		reserved = I915_READ_NOTRACE(sc->reg) &
178a2fdbec6SFrançois Tigeot 					     (GPIO_DATA_PULLUP_DISABLE |
179a2fdbec6SFrançois Tigeot 					      GPIO_CLOCK_PULLUP_DISABLE);
180a2fdbec6SFrançois Tigeot 
181a2fdbec6SFrançois Tigeot 	return reserved;
182a2fdbec6SFrançois Tigeot }
183a2fdbec6SFrançois Tigeot 
184a2fdbec6SFrançois Tigeot static int get_clock(device_t idev)
185bad0eccaSFrançois Tigeot {
186bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
187bad0eccaSFrançois Tigeot 	struct drm_i915_private *dev_priv;
188bad0eccaSFrançois Tigeot 	u32 reserved;
189bad0eccaSFrançois Tigeot 
190bad0eccaSFrançois Tigeot 	sc = device_get_softc(idev);
191a2fdbec6SFrançois Tigeot 	dev_priv = sc->drm_dev->dev_private;
192bad0eccaSFrançois Tigeot 
193a2fdbec6SFrançois Tigeot 	reserved = get_reserved(idev);
194a2fdbec6SFrançois Tigeot 
195a2fdbec6SFrançois Tigeot 	I915_WRITE_NOTRACE(sc->reg, reserved | GPIO_CLOCK_DIR_MASK);
196a2fdbec6SFrançois Tigeot 	I915_WRITE_NOTRACE(sc->reg, reserved);
197a2fdbec6SFrançois Tigeot 	return ((I915_READ_NOTRACE(sc->reg) & GPIO_CLOCK_VAL_IN) != 0);
198bad0eccaSFrançois Tigeot }
199bad0eccaSFrançois Tigeot 
200a2fdbec6SFrançois Tigeot static int get_data(device_t idev)
201bad0eccaSFrançois Tigeot {
202a2fdbec6SFrançois Tigeot 	struct intel_iic_softc *sc;
203bad0eccaSFrançois Tigeot 	struct drm_i915_private *dev_priv;
204a2fdbec6SFrançois Tigeot 	u32 reserved;
205bad0eccaSFrançois Tigeot 
206a2fdbec6SFrançois Tigeot 	sc = device_get_softc(idev);
207a2fdbec6SFrançois Tigeot 	dev_priv = sc->drm_dev->dev_private;
208a2fdbec6SFrançois Tigeot 
209a2fdbec6SFrançois Tigeot 	reserved = get_reserved(idev);
210a2fdbec6SFrançois Tigeot 
211a2fdbec6SFrançois Tigeot 	I915_WRITE_NOTRACE(sc->reg, reserved | GPIO_DATA_DIR_MASK);
212a2fdbec6SFrançois Tigeot 	I915_WRITE_NOTRACE(sc->reg, reserved);
213a2fdbec6SFrançois Tigeot 	return ((I915_READ_NOTRACE(sc->reg) & GPIO_DATA_VAL_IN) != 0);
214bad0eccaSFrançois Tigeot }
215bad0eccaSFrançois Tigeot 
216bad0eccaSFrançois Tigeot static int
217bad0eccaSFrançois Tigeot intel_iicbus_reset(device_t idev, u_char speed, u_char addr, u_char *oldaddr)
218bad0eccaSFrançois Tigeot {
219bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
220bad0eccaSFrançois Tigeot 	struct drm_device *dev;
221bad0eccaSFrançois Tigeot 
222bad0eccaSFrançois Tigeot 	sc = device_get_softc(idev);
223bad0eccaSFrançois Tigeot 	dev = sc->drm_dev;
224bad0eccaSFrançois Tigeot 
2253f2f609dSFrançois Tigeot 	intel_i2c_reset(dev);
226bad0eccaSFrançois Tigeot 	return (0);
227bad0eccaSFrançois Tigeot }
228bad0eccaSFrançois Tigeot 
229a2fdbec6SFrançois Tigeot static void set_clock(device_t idev, int val)
230bad0eccaSFrançois Tigeot {
231bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
232bad0eccaSFrançois Tigeot 	struct drm_i915_private *dev_priv;
233bad0eccaSFrançois Tigeot 	u32 clock_bits, reserved;
234bad0eccaSFrançois Tigeot 
235bad0eccaSFrançois Tigeot 	sc = device_get_softc(idev);
236bad0eccaSFrançois Tigeot 	dev_priv = sc->drm_dev->dev_private;
237bad0eccaSFrançois Tigeot 
238a2fdbec6SFrançois Tigeot 	reserved = get_reserved(idev);
239bad0eccaSFrançois Tigeot 	if (val)
240bad0eccaSFrançois Tigeot 		clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
241bad0eccaSFrançois Tigeot 	else
242bad0eccaSFrançois Tigeot 		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
243bad0eccaSFrançois Tigeot 		    GPIO_CLOCK_VAL_MASK;
244bad0eccaSFrançois Tigeot 
245bad0eccaSFrançois Tigeot 	I915_WRITE_NOTRACE(sc->reg, reserved | clock_bits);
246bad0eccaSFrançois Tigeot 	POSTING_READ(sc->reg);
247bad0eccaSFrançois Tigeot }
248bad0eccaSFrançois Tigeot 
249a2fdbec6SFrançois Tigeot static void set_data(device_t idev, int val)
250bad0eccaSFrançois Tigeot {
251bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
252bad0eccaSFrançois Tigeot 	struct drm_i915_private *dev_priv;
253bad0eccaSFrançois Tigeot 	u32 reserved;
254a2fdbec6SFrançois Tigeot 	u32 data_bits;
255bad0eccaSFrançois Tigeot 
256bad0eccaSFrançois Tigeot 	sc = device_get_softc(idev);
257bad0eccaSFrançois Tigeot 	dev_priv = sc->drm_dev->dev_private;
258bad0eccaSFrançois Tigeot 
259a2fdbec6SFrançois Tigeot 	reserved = get_reserved(idev);
26027a0f882SMatthew Dillon 
261a2fdbec6SFrançois Tigeot 	if (val)
262a2fdbec6SFrançois Tigeot 		data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
263a2fdbec6SFrançois Tigeot 	else
264a2fdbec6SFrançois Tigeot 		data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
265a2fdbec6SFrançois Tigeot 		    GPIO_DATA_VAL_MASK;
266bad0eccaSFrançois Tigeot 
267a2fdbec6SFrançois Tigeot 	I915_WRITE_NOTRACE(sc->reg, reserved | data_bits);
268a2fdbec6SFrançois Tigeot 	POSTING_READ(sc->reg);
269bad0eccaSFrançois Tigeot }
270bad0eccaSFrançois Tigeot 
27119c468b4SFrançois Tigeot static const char *gpio_names[GMBUS_NUM_PINS] = {
272a2fdbec6SFrançois Tigeot 	"ssc",
273a2fdbec6SFrançois Tigeot 	"vga",
274a2fdbec6SFrançois Tigeot 	"panel",
275a2fdbec6SFrançois Tigeot 	"dpc",
276a2fdbec6SFrançois Tigeot 	"dpb",
277a2fdbec6SFrançois Tigeot 	"dpd",
278a2fdbec6SFrançois Tigeot };
279a2fdbec6SFrançois Tigeot 
280bad0eccaSFrançois Tigeot static int
281a2fdbec6SFrançois Tigeot intel_gpio_setup(device_t idev)
282bad0eccaSFrançois Tigeot {
283a2fdbec6SFrançois Tigeot 	static const int map_pin_to_reg[] = {
284a2fdbec6SFrançois Tigeot 		0,
285a2fdbec6SFrançois Tigeot 		GPIOB,
286a2fdbec6SFrançois Tigeot 		GPIOA,
287a2fdbec6SFrançois Tigeot 		GPIOC,
288a2fdbec6SFrançois Tigeot 		GPIOD,
289a2fdbec6SFrançois Tigeot 		GPIOE,
290a2fdbec6SFrançois Tigeot 		GPIOF,
291a2fdbec6SFrançois Tigeot 		0
292a2fdbec6SFrançois Tigeot 	};
293a2fdbec6SFrançois Tigeot 
294bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
295bad0eccaSFrançois Tigeot 	struct drm_i915_private *dev_priv;
296a2fdbec6SFrançois Tigeot 	int pin;
297bad0eccaSFrançois Tigeot 
298bad0eccaSFrançois Tigeot 	sc = device_get_softc(idev);
299a2fdbec6SFrançois Tigeot 	sc->drm_dev = device_get_softc(device_get_parent(idev));
300bad0eccaSFrançois Tigeot 	dev_priv = sc->drm_dev->dev_private;
301a2fdbec6SFrançois Tigeot 	pin = device_get_unit(idev);
302bad0eccaSFrançois Tigeot 
303a2fdbec6SFrançois Tigeot 	ksnprintf(sc->name, sizeof(sc->name), "i915 iicbb %s", gpio_names[pin]);
304a2fdbec6SFrançois Tigeot 	device_set_desc(idev, sc->name);
305bad0eccaSFrançois Tigeot 
30619c468b4SFrançois Tigeot 	sc->reg0 = pin | GMBUS_RATE_100KHZ;
30719c468b4SFrançois Tigeot 	sc->reg = dev_priv->gpio_mmio_base + map_pin_to_reg[pin];
308a2fdbec6SFrançois Tigeot 
309a2fdbec6SFrançois Tigeot 	/* add generic bit-banging code */
310a2fdbec6SFrançois Tigeot 	sc->iic_dev = device_add_child(idev, "iicbb", -1);
311a2fdbec6SFrançois Tigeot 	if (sc->iic_dev == NULL)
312a2fdbec6SFrançois Tigeot 		return (ENXIO);
313a2fdbec6SFrançois Tigeot 	device_quiet(sc->iic_dev);
314a2fdbec6SFrançois Tigeot 	bus_generic_attach(idev);
315a2fdbec6SFrançois Tigeot 
316a2fdbec6SFrançois Tigeot 	return (0);
317bad0eccaSFrançois Tigeot }
318bad0eccaSFrançois Tigeot 
319bad0eccaSFrançois Tigeot static int
320a2fdbec6SFrançois Tigeot intel_i2c_quirk_xfer(device_t idev, struct iic_msg *msgs, int nmsgs)
321bad0eccaSFrançois Tigeot {
322a2fdbec6SFrançois Tigeot 	device_t bridge_dev;
323bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
324bad0eccaSFrançois Tigeot 	struct drm_i915_private *dev_priv;
325a2fdbec6SFrançois Tigeot 	int ret;
326a2fdbec6SFrançois Tigeot 	int i;
327a2fdbec6SFrançois Tigeot 
328a2fdbec6SFrançois Tigeot 	bridge_dev = device_get_parent(device_get_parent(idev));
329a2fdbec6SFrançois Tigeot 	sc = device_get_softc(bridge_dev);
330a2fdbec6SFrançois Tigeot 	dev_priv = sc->drm_dev->dev_private;
331a2fdbec6SFrançois Tigeot 
332a2fdbec6SFrançois Tigeot 	intel_i2c_reset(sc->drm_dev);
333a2fdbec6SFrançois Tigeot 	intel_i2c_quirk_set(dev_priv, true);
334a2fdbec6SFrançois Tigeot 	IICBB_SETSDA(bridge_dev, 1);
335a2fdbec6SFrançois Tigeot 	IICBB_SETSCL(bridge_dev, 1);
336a2fdbec6SFrançois Tigeot 	DELAY(I2C_RISEFALL_TIME);
337a2fdbec6SFrançois Tigeot 
338a2fdbec6SFrançois Tigeot 	for (i = 0; i < nmsgs - 1; i++) {
339a2fdbec6SFrançois Tigeot 		/* force use of repeated start instead of default stop+start */
340a2fdbec6SFrançois Tigeot 		msgs[i].flags |= IIC_M_NOSTOP;
341a2fdbec6SFrançois Tigeot 	}
342a2fdbec6SFrançois Tigeot 	ret = iicbus_transfer(idev, msgs, nmsgs);
343a2fdbec6SFrançois Tigeot 	IICBB_SETSDA(bridge_dev, 1);
344a2fdbec6SFrançois Tigeot 	IICBB_SETSCL(bridge_dev, 1);
345a2fdbec6SFrançois Tigeot 	intel_i2c_quirk_set(dev_priv, false);
346a2fdbec6SFrançois Tigeot 
347a2fdbec6SFrançois Tigeot 	return (ret);
348a2fdbec6SFrançois Tigeot }
349a2fdbec6SFrançois Tigeot 
350a2fdbec6SFrançois Tigeot static int
351a2fdbec6SFrançois Tigeot gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
352a2fdbec6SFrançois Tigeot 		     u32 gmbus2_status,
353a2fdbec6SFrançois Tigeot 		     u32 gmbus4_irq_en)
354a2fdbec6SFrançois Tigeot {
355a2fdbec6SFrançois Tigeot 	int i;
356a2fdbec6SFrançois Tigeot 	u32 gmbus2 = 0;
357a2fdbec6SFrançois Tigeot 	DEFINE_WAIT(wait);
358a2fdbec6SFrançois Tigeot 
359a2fdbec6SFrançois Tigeot 	if (!HAS_GMBUS_IRQ(dev_priv->dev))
360a2fdbec6SFrançois Tigeot 		gmbus4_irq_en = 0;
361a2fdbec6SFrançois Tigeot 
362a2fdbec6SFrançois Tigeot 	/* Important: The hw handles only the first bit, so set only one! Since
363a2fdbec6SFrançois Tigeot 	 * we also need to check for NAKs besides the hw ready/idle signal, we
364a2fdbec6SFrançois Tigeot 	 * need to wake up periodically and check that ourselves. */
365*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS4, gmbus4_irq_en);
366a2fdbec6SFrançois Tigeot 
3678e26cdf6SFrançois Tigeot 	for (i = 0; i < msecs_to_jiffies_timeout(50); i++) {
368a2fdbec6SFrançois Tigeot 		prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait,
369a2fdbec6SFrançois Tigeot 				TASK_UNINTERRUPTIBLE);
370a2fdbec6SFrançois Tigeot 
371*352ff8bdSFrançois Tigeot 		gmbus2 = I915_READ_NOTRACE(GMBUS2);
372a2fdbec6SFrançois Tigeot 		if (gmbus2 & (GMBUS_SATOER | gmbus2_status))
373a2fdbec6SFrançois Tigeot 			break;
374a2fdbec6SFrançois Tigeot 
375a2fdbec6SFrançois Tigeot 		schedule_timeout(1);
376a2fdbec6SFrançois Tigeot 	}
377a2fdbec6SFrançois Tigeot 	finish_wait(&dev_priv->gmbus_wait_queue, &wait);
378a2fdbec6SFrançois Tigeot 
379*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS4, 0);
380a2fdbec6SFrançois Tigeot 
381a2fdbec6SFrançois Tigeot 	if (gmbus2 & GMBUS_SATOER)
382a2fdbec6SFrançois Tigeot 		return -ENXIO;
383a2fdbec6SFrançois Tigeot 	if (gmbus2 & gmbus2_status)
384a2fdbec6SFrançois Tigeot 		return 0;
385a2fdbec6SFrançois Tigeot 	return -ETIMEDOUT;
386a2fdbec6SFrançois Tigeot }
387a2fdbec6SFrançois Tigeot 
388a2fdbec6SFrançois Tigeot static int
389a2fdbec6SFrançois Tigeot gmbus_wait_idle(struct drm_i915_private *dev_priv)
390a2fdbec6SFrançois Tigeot {
391a2fdbec6SFrançois Tigeot 	int ret;
392a2fdbec6SFrançois Tigeot 
393*352ff8bdSFrançois Tigeot #define C ((I915_READ_NOTRACE(GMBUS2) & GMBUS_ACTIVE) == 0)
394a2fdbec6SFrançois Tigeot 
395a2fdbec6SFrançois Tigeot 	if (!HAS_GMBUS_IRQ(dev_priv->dev))
396a2fdbec6SFrançois Tigeot 		return wait_for(C, 10);
397a2fdbec6SFrançois Tigeot 
398a2fdbec6SFrançois Tigeot 	/* Important: The hw handles only the first bit, so set only one! */
399*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS4, GMBUS_IDLE_EN);
400a2fdbec6SFrançois Tigeot 
4018e26cdf6SFrançois Tigeot 	ret = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
4028e26cdf6SFrançois Tigeot 				 msecs_to_jiffies_timeout(10));
403a2fdbec6SFrançois Tigeot 
404*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS4, 0);
405a2fdbec6SFrançois Tigeot 
406a2fdbec6SFrançois Tigeot 	if (ret)
407a2fdbec6SFrançois Tigeot 		return 0;
408a2fdbec6SFrançois Tigeot 	else
409a2fdbec6SFrançois Tigeot 		return -ETIMEDOUT;
410a2fdbec6SFrançois Tigeot #undef C
411a2fdbec6SFrançois Tigeot }
412a2fdbec6SFrançois Tigeot 
413a2fdbec6SFrançois Tigeot static int
414477eb7f9SFrançois Tigeot gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
415477eb7f9SFrançois Tigeot 		      unsigned short addr, u8 *buf, unsigned int len,
416a2fdbec6SFrançois Tigeot 		      u32 gmbus1_index)
417a2fdbec6SFrançois Tigeot {
418*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS1,
419a2fdbec6SFrançois Tigeot 		   gmbus1_index |
420a2fdbec6SFrançois Tigeot 		   GMBUS_CYCLE_WAIT |
421a2fdbec6SFrançois Tigeot 		   (len << GMBUS_BYTE_COUNT_SHIFT) |
422477eb7f9SFrançois Tigeot 		   (addr << GMBUS_SLAVE_ADDR_SHIFT) |
423a2fdbec6SFrançois Tigeot 		   GMBUS_SLAVE_READ | GMBUS_SW_RDY);
424a2fdbec6SFrançois Tigeot 	while (len) {
425a2fdbec6SFrançois Tigeot 		int ret;
426a2fdbec6SFrançois Tigeot 		u32 val, loop = 0;
427a2fdbec6SFrançois Tigeot 
428a2fdbec6SFrançois Tigeot 		ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY,
429a2fdbec6SFrançois Tigeot 					   GMBUS_HW_RDY_EN);
430a2fdbec6SFrançois Tigeot 		if (ret)
431a2fdbec6SFrançois Tigeot 			return ret;
432a2fdbec6SFrançois Tigeot 
433*352ff8bdSFrançois Tigeot 		val = I915_READ(GMBUS3);
434a2fdbec6SFrançois Tigeot 		do {
435a2fdbec6SFrançois Tigeot 			*buf++ = val & 0xff;
436a2fdbec6SFrançois Tigeot 			val >>= 8;
437a2fdbec6SFrançois Tigeot 		} while (--len && ++loop < 4);
438a2fdbec6SFrançois Tigeot 	}
439a2fdbec6SFrançois Tigeot 
440a2fdbec6SFrançois Tigeot 	return 0;
441a2fdbec6SFrançois Tigeot }
442a2fdbec6SFrançois Tigeot 
443a2fdbec6SFrançois Tigeot static int
444477eb7f9SFrançois Tigeot gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
445477eb7f9SFrançois Tigeot 		u32 gmbus1_index)
446477eb7f9SFrançois Tigeot {
447477eb7f9SFrançois Tigeot 	u8 *buf = msg->buf;
448477eb7f9SFrançois Tigeot 	unsigned int rx_size = msg->len;
449477eb7f9SFrançois Tigeot 	unsigned int len;
450477eb7f9SFrançois Tigeot 	int ret;
451477eb7f9SFrançois Tigeot 
452477eb7f9SFrançois Tigeot 	do {
453477eb7f9SFrançois Tigeot 		len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
454477eb7f9SFrançois Tigeot 
455477eb7f9SFrançois Tigeot 		ret = gmbus_xfer_read_chunk(dev_priv, msg->slave >> 1,
456477eb7f9SFrançois Tigeot 					    buf, len, gmbus1_index);
457477eb7f9SFrançois Tigeot 		if (ret)
458477eb7f9SFrançois Tigeot 			return ret;
459477eb7f9SFrançois Tigeot 
460477eb7f9SFrançois Tigeot 		rx_size -= len;
461477eb7f9SFrançois Tigeot 		buf += len;
462477eb7f9SFrançois Tigeot 	} while (rx_size != 0);
463477eb7f9SFrançois Tigeot 
464477eb7f9SFrançois Tigeot 	return 0;
465477eb7f9SFrançois Tigeot }
466477eb7f9SFrançois Tigeot 
467477eb7f9SFrançois Tigeot static int
468477eb7f9SFrançois Tigeot gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
469477eb7f9SFrançois Tigeot 		       unsigned short addr, u8 *buf, unsigned int len)
470a2fdbec6SFrançois Tigeot {
471477eb7f9SFrançois Tigeot 	unsigned int chunk_size = len;
472bad0eccaSFrançois Tigeot 	u32 val, loop;
473bad0eccaSFrançois Tigeot 
474a2fdbec6SFrançois Tigeot 	val = loop = 0;
475a2fdbec6SFrançois Tigeot 	while (len && loop < 4) {
476a2fdbec6SFrançois Tigeot 		val |= *buf++ << (8 * loop++);
477a2fdbec6SFrançois Tigeot 		len -= 1;
478a2fdbec6SFrançois Tigeot 	}
479a2fdbec6SFrançois Tigeot 
480*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS3, val);
481*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS1,
482a2fdbec6SFrançois Tigeot 		   GMBUS_CYCLE_WAIT |
483477eb7f9SFrançois Tigeot 		   (chunk_size << GMBUS_BYTE_COUNT_SHIFT) |
484477eb7f9SFrançois Tigeot 		   (addr << GMBUS_SLAVE_ADDR_SHIFT) |
485a2fdbec6SFrançois Tigeot 		   GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
486a2fdbec6SFrançois Tigeot 	while (len) {
487a2fdbec6SFrançois Tigeot 		int ret;
488a2fdbec6SFrançois Tigeot 
489a2fdbec6SFrançois Tigeot 		val = loop = 0;
490a2fdbec6SFrançois Tigeot 		do {
491a2fdbec6SFrançois Tigeot 			val |= *buf++ << (8 * loop);
492a2fdbec6SFrançois Tigeot 		} while (--len && ++loop < 4);
493a2fdbec6SFrançois Tigeot 
494*352ff8bdSFrançois Tigeot 		I915_WRITE(GMBUS3, val);
495a2fdbec6SFrançois Tigeot 
496a2fdbec6SFrançois Tigeot 		ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY,
497a2fdbec6SFrançois Tigeot 					   GMBUS_HW_RDY_EN);
498a2fdbec6SFrançois Tigeot 		if (ret)
499a2fdbec6SFrançois Tigeot 			return ret;
500a2fdbec6SFrançois Tigeot 	}
501477eb7f9SFrançois Tigeot 
502477eb7f9SFrançois Tigeot 	return 0;
503477eb7f9SFrançois Tigeot }
504477eb7f9SFrançois Tigeot 
505477eb7f9SFrançois Tigeot static int
506477eb7f9SFrançois Tigeot gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
507477eb7f9SFrançois Tigeot {
508477eb7f9SFrançois Tigeot 	u8 *buf = msg->buf;
509477eb7f9SFrançois Tigeot 	unsigned int tx_size = msg->len;
510477eb7f9SFrançois Tigeot 	unsigned int len;
511477eb7f9SFrançois Tigeot 	int ret;
512477eb7f9SFrançois Tigeot 
513477eb7f9SFrançois Tigeot 	do {
514477eb7f9SFrançois Tigeot 		len = min(tx_size, GMBUS_BYTE_COUNT_MAX);
515477eb7f9SFrançois Tigeot 
516477eb7f9SFrançois Tigeot 		ret = gmbus_xfer_write_chunk(dev_priv, msg->slave >> 1, buf, len);
517477eb7f9SFrançois Tigeot 		if (ret)
518477eb7f9SFrançois Tigeot 			return ret;
519477eb7f9SFrançois Tigeot 
520477eb7f9SFrançois Tigeot 		buf += len;
521477eb7f9SFrançois Tigeot 		tx_size -= len;
522477eb7f9SFrançois Tigeot 	} while (tx_size != 0);
523477eb7f9SFrançois Tigeot 
524a2fdbec6SFrançois Tigeot 	return 0;
525a2fdbec6SFrançois Tigeot }
526a2fdbec6SFrançois Tigeot 
527a2fdbec6SFrançois Tigeot /*
528a2fdbec6SFrançois Tigeot  * The gmbus controller can combine a 1 or 2 byte write with a read that
529a2fdbec6SFrançois Tigeot  * immediately follows it by using an "INDEX" cycle.
530a2fdbec6SFrançois Tigeot  */
531a2fdbec6SFrançois Tigeot static bool
532a2fdbec6SFrançois Tigeot gmbus_is_index_read(struct i2c_msg *msgs, int i, int num)
533a2fdbec6SFrançois Tigeot {
534a2fdbec6SFrançois Tigeot 	return (i + 1 < num &&
535a2fdbec6SFrançois Tigeot 		!(msgs[i].flags & I2C_M_RD) && msgs[i].len <= 2 &&
536a2fdbec6SFrançois Tigeot 		(msgs[i + 1].flags & I2C_M_RD));
537a2fdbec6SFrançois Tigeot }
538a2fdbec6SFrançois Tigeot 
539a2fdbec6SFrançois Tigeot static int
540a2fdbec6SFrançois Tigeot gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
541a2fdbec6SFrançois Tigeot {
542a2fdbec6SFrançois Tigeot 	u32 gmbus1_index = 0;
543a2fdbec6SFrançois Tigeot 	u32 gmbus5 = 0;
544a2fdbec6SFrançois Tigeot 	int ret;
545a2fdbec6SFrançois Tigeot 
546a2fdbec6SFrançois Tigeot 	if (msgs[0].len == 2)
547a2fdbec6SFrançois Tigeot 		gmbus5 = GMBUS_2BYTE_INDEX_EN |
548a2fdbec6SFrançois Tigeot 			 msgs[0].buf[1] | (msgs[0].buf[0] << 8);
549a2fdbec6SFrançois Tigeot 	if (msgs[0].len == 1)
550a2fdbec6SFrançois Tigeot 		gmbus1_index = GMBUS_CYCLE_INDEX |
551a2fdbec6SFrançois Tigeot 			       (msgs[0].buf[0] << GMBUS_SLAVE_INDEX_SHIFT);
552a2fdbec6SFrançois Tigeot 
553a2fdbec6SFrançois Tigeot 	/* GMBUS5 holds 16-bit index */
554a2fdbec6SFrançois Tigeot 	if (gmbus5)
555*352ff8bdSFrançois Tigeot 		I915_WRITE(GMBUS5, gmbus5);
556a2fdbec6SFrançois Tigeot 
557a2fdbec6SFrançois Tigeot 	ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index);
558a2fdbec6SFrançois Tigeot 
559a2fdbec6SFrançois Tigeot 	/* Clear GMBUS5 after each index transfer */
560a2fdbec6SFrançois Tigeot 	if (gmbus5)
561*352ff8bdSFrançois Tigeot 		I915_WRITE(GMBUS5, 0);
562a2fdbec6SFrançois Tigeot 
563a2fdbec6SFrançois Tigeot 	return ret;
564a2fdbec6SFrançois Tigeot }
565a2fdbec6SFrançois Tigeot 
566a2fdbec6SFrançois Tigeot static int
567a2fdbec6SFrançois Tigeot gmbus_xfer(struct device *adapter,
568a2fdbec6SFrançois Tigeot 	   struct i2c_msg *msgs,
569a2fdbec6SFrançois Tigeot 	   int num)
570a2fdbec6SFrançois Tigeot {
571a2fdbec6SFrançois Tigeot 	struct intel_iic_softc *sc;
572a2fdbec6SFrançois Tigeot 	struct drm_i915_private *dev_priv;
573*352ff8bdSFrançois Tigeot 	int i = 0, inc, try = 0;
574477eb7f9SFrançois Tigeot 	int unit;
575a2fdbec6SFrançois Tigeot 	int ret = 0;
576a2fdbec6SFrançois Tigeot 
577a2fdbec6SFrançois Tigeot 	sc = device_get_softc(adapter);
578bad0eccaSFrançois Tigeot 	dev_priv = sc->drm_dev->dev_private;
579a2fdbec6SFrançois Tigeot 	unit = device_get_unit(adapter);
580bad0eccaSFrançois Tigeot 
581*352ff8bdSFrançois Tigeot 	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
582a2fdbec6SFrançois Tigeot 	mutex_lock(&dev_priv->gmbus_mutex);
583a2fdbec6SFrançois Tigeot 
584bad0eccaSFrançois Tigeot 	if (sc->force_bit_dev) {
585a2fdbec6SFrançois Tigeot 		ret = intel_i2c_quirk_xfer(dev_priv->bbbus[unit], msgs, num);
586bad0eccaSFrançois Tigeot 		goto out;
587bad0eccaSFrançois Tigeot 	}
588bad0eccaSFrançois Tigeot 
589477eb7f9SFrançois Tigeot retry:
590*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS0, sc->reg0);
591bad0eccaSFrançois Tigeot 
592477eb7f9SFrançois Tigeot 	for (; i < num; i += inc) {
593477eb7f9SFrançois Tigeot 		inc = 1;
594a2fdbec6SFrançois Tigeot 		if (gmbus_is_index_read(msgs, i, num)) {
595a2fdbec6SFrançois Tigeot 			ret = gmbus_xfer_index_read(dev_priv, &msgs[i]);
596477eb7f9SFrançois Tigeot 			inc = 2; /* an index read is two msgs */
597a2fdbec6SFrançois Tigeot 		} else if (msgs[i].flags & I2C_M_RD) {
598a2fdbec6SFrançois Tigeot 			ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
599bad0eccaSFrançois Tigeot 		} else {
600a2fdbec6SFrançois Tigeot 			ret = gmbus_xfer_write(dev_priv, &msgs[i]);
601a2fdbec6SFrançois Tigeot 		}
602bad0eccaSFrançois Tigeot 
603a2fdbec6SFrançois Tigeot 		if (ret == -ETIMEDOUT)
604bad0eccaSFrançois Tigeot 			goto timeout;
605a2fdbec6SFrançois Tigeot 		if (ret == -ENXIO)
606bad0eccaSFrançois Tigeot 			goto clear_err;
607bad0eccaSFrançois Tigeot 
608a2fdbec6SFrançois Tigeot 		ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE,
609a2fdbec6SFrançois Tigeot 					   GMBUS_HW_WAIT_EN);
610a2fdbec6SFrançois Tigeot 		if (ret == -ENXIO)
611bad0eccaSFrançois Tigeot 			goto clear_err;
612a2fdbec6SFrançois Tigeot 		if (ret)
613a2fdbec6SFrançois Tigeot 			goto timeout;
614bad0eccaSFrançois Tigeot 	}
615bad0eccaSFrançois Tigeot 
616a2fdbec6SFrançois Tigeot 	/* Generate a STOP condition on the bus. Note that gmbus can't generata
617a2fdbec6SFrançois Tigeot 	 * a STOP on the very first cycle. To simplify the code we
618a2fdbec6SFrançois Tigeot 	 * unconditionally generate the STOP condition with an additional gmbus
619a2fdbec6SFrançois Tigeot 	 * cycle. */
620*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS1, GMBUS_CYCLE_STOP | GMBUS_SW_RDY);
621a2fdbec6SFrançois Tigeot 
622bad0eccaSFrançois Tigeot 	/* Mark the GMBUS interface as disabled after waiting for idle.
623bad0eccaSFrançois Tigeot 	 * We will re-enable it at the start of the next xfer,
624bad0eccaSFrançois Tigeot 	 * till then let it sleep.
625bad0eccaSFrançois Tigeot 	 */
626a2fdbec6SFrançois Tigeot 	if (gmbus_wait_idle(dev_priv)) {
627a2fdbec6SFrançois Tigeot 		DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n",
628a2fdbec6SFrançois Tigeot 			 sc->name);
629a2fdbec6SFrançois Tigeot 		ret = -ETIMEDOUT;
630a2fdbec6SFrançois Tigeot 	}
631*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS0, 0);
632a2fdbec6SFrançois Tigeot 	ret = ret ?: i;
633a2fdbec6SFrançois Tigeot 	goto timeout;	/* XXX: should be out */
634bad0eccaSFrançois Tigeot 
635bad0eccaSFrançois Tigeot clear_err:
636a2fdbec6SFrançois Tigeot 	/*
637a2fdbec6SFrançois Tigeot 	 * Wait for bus to IDLE before clearing NAK.
638a2fdbec6SFrançois Tigeot 	 * If we clear the NAK while bus is still active, then it will stay
639a2fdbec6SFrançois Tigeot 	 * active and the next transaction may fail.
640a2fdbec6SFrançois Tigeot 	 *
641a2fdbec6SFrançois Tigeot 	 * If no ACK is received during the address phase of a transaction, the
642a2fdbec6SFrançois Tigeot 	 * adapter must report -ENXIO. It is not clear what to return if no ACK
643a2fdbec6SFrançois Tigeot 	 * is received at other times. But we have to be careful to not return
644a2fdbec6SFrançois Tigeot 	 * spurious -ENXIO because that will prevent i2c and drm edid functions
645a2fdbec6SFrançois Tigeot 	 * from retrying. So return -ENXIO only when gmbus properly quiescents -
646a2fdbec6SFrançois Tigeot 	 * timing out seems to happen when there _is_ a ddc chip present, but
647a2fdbec6SFrançois Tigeot 	 * it's slow responding and only answers on the 2nd retry.
648a2fdbec6SFrançois Tigeot 	 */
649a2fdbec6SFrançois Tigeot 	ret = -ENXIO;
650a2fdbec6SFrançois Tigeot 	if (gmbus_wait_idle(dev_priv)) {
651a2fdbec6SFrançois Tigeot 		DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n",
652a2fdbec6SFrançois Tigeot 			      sc->name);
653a2fdbec6SFrançois Tigeot 		ret = -ETIMEDOUT;
654a2fdbec6SFrançois Tigeot 	}
655a2fdbec6SFrançois Tigeot 
656bad0eccaSFrançois Tigeot 	/* Toggle the Software Clear Interrupt bit. This has the effect
657bad0eccaSFrançois Tigeot 	 * of resetting the GMBUS controller and so clearing the
658bad0eccaSFrançois Tigeot 	 * BUS_ERROR raised by the slave's NAK.
659bad0eccaSFrançois Tigeot 	 */
660*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS1, GMBUS_SW_CLR_INT);
661*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS1, 0);
662*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS0, 0);
663bad0eccaSFrançois Tigeot 
664a2fdbec6SFrançois Tigeot 	DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n",
665a2fdbec6SFrançois Tigeot 			 sc->name, msgs[i].slave,
666a2fdbec6SFrançois Tigeot 			 (msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
667bad0eccaSFrançois Tigeot 
668477eb7f9SFrançois Tigeot 	/*
669477eb7f9SFrançois Tigeot 	 * Passive adapters sometimes NAK the first probe. Retry the first
670477eb7f9SFrançois Tigeot 	 * message once on -ENXIO for GMBUS transfers; the bit banging algorithm
671477eb7f9SFrançois Tigeot 	 * has retries internally. See also the retry loop in
672477eb7f9SFrançois Tigeot 	 * drm_do_probe_ddc_edid, which bails out on the first -ENXIO.
673477eb7f9SFrançois Tigeot 	 */
674477eb7f9SFrançois Tigeot 	if (ret == -ENXIO && i == 0 && try++ == 0) {
675477eb7f9SFrançois Tigeot 		DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n",
676477eb7f9SFrançois Tigeot 			      sc->name);
677477eb7f9SFrançois Tigeot 		goto retry;
678477eb7f9SFrançois Tigeot 	}
679477eb7f9SFrançois Tigeot 
680bad0eccaSFrançois Tigeot 	goto out;
681a2fdbec6SFrançois Tigeot 
682a2fdbec6SFrançois Tigeot timeout:
683a2fdbec6SFrançois Tigeot 	DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
684a2fdbec6SFrançois Tigeot 		 sc->name, sc->reg0 & 0xff);
685*352ff8bdSFrançois Tigeot 	I915_WRITE(GMBUS0, 0);
686a2fdbec6SFrançois Tigeot 
687a2fdbec6SFrançois Tigeot 	/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
688a2fdbec6SFrançois Tigeot 	sc->force_bit_dev = true;
689a2fdbec6SFrançois Tigeot 	ret = intel_i2c_quirk_xfer(dev_priv->bbbus[unit], msgs, num);
690a2fdbec6SFrançois Tigeot 
691a2fdbec6SFrançois Tigeot out:
692a2fdbec6SFrançois Tigeot 	mutex_unlock(&dev_priv->gmbus_mutex);
693*352ff8bdSFrançois Tigeot 
694*352ff8bdSFrançois Tigeot 	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
695*352ff8bdSFrançois Tigeot 
696a2fdbec6SFrançois Tigeot 	return ret;
697bad0eccaSFrançois Tigeot }
698bad0eccaSFrançois Tigeot 
69919c468b4SFrançois Tigeot struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv,
70019c468b4SFrançois Tigeot 					    unsigned int pin)
70119df918dSFrançois Tigeot {
70219c468b4SFrançois Tigeot 	if (WARN_ON(!intel_gmbus_is_valid_pin(dev_priv, pin)))
70319c468b4SFrançois Tigeot 		return NULL;
70419c468b4SFrançois Tigeot 
70519c468b4SFrançois Tigeot 	return dev_priv->gmbus[pin];
70619df918dSFrançois Tigeot }
70719df918dSFrançois Tigeot 
708bad0eccaSFrançois Tigeot void
709bad0eccaSFrançois Tigeot intel_gmbus_set_speed(device_t idev, int speed)
710bad0eccaSFrançois Tigeot {
711bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
712bad0eccaSFrançois Tigeot 
713bad0eccaSFrançois Tigeot 	sc = device_get_softc(device_get_parent(idev));
714bad0eccaSFrançois Tigeot 
715bad0eccaSFrançois Tigeot 	sc->reg0 = (sc->reg0 & ~(0x3 << 8)) | speed;
716bad0eccaSFrançois Tigeot }
717bad0eccaSFrançois Tigeot 
718bad0eccaSFrançois Tigeot void
719bad0eccaSFrançois Tigeot intel_gmbus_force_bit(device_t idev, bool force_bit)
720bad0eccaSFrançois Tigeot {
721bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
722bad0eccaSFrançois Tigeot 
723bad0eccaSFrançois Tigeot 	sc = device_get_softc(device_get_parent(idev));
724a2fdbec6SFrançois Tigeot 	sc->force_bit_dev += force_bit ? 1 : -1;
725a2fdbec6SFrançois Tigeot 	DRM_DEBUG_KMS("%sabling bit-banging on %s. force bit now %d\n",
726a2fdbec6SFrançois Tigeot 		      force_bit ? "en" : "dis", sc->name,
727a2fdbec6SFrançois Tigeot 		      sc->force_bit_dev);
728bad0eccaSFrançois Tigeot }
729bad0eccaSFrançois Tigeot 
730bad0eccaSFrançois Tigeot static int
731bad0eccaSFrançois Tigeot intel_gmbus_probe(device_t dev)
732bad0eccaSFrançois Tigeot {
733bad0eccaSFrançois Tigeot 
734bad0eccaSFrançois Tigeot 	return (BUS_PROBE_SPECIFIC);
735bad0eccaSFrançois Tigeot }
736bad0eccaSFrançois Tigeot 
737bad0eccaSFrançois Tigeot static int
738bad0eccaSFrançois Tigeot intel_gmbus_attach(device_t idev)
739bad0eccaSFrançois Tigeot {
740bad0eccaSFrançois Tigeot 	struct drm_i915_private *dev_priv;
741bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
742bad0eccaSFrançois Tigeot 	int pin;
743bad0eccaSFrançois Tigeot 
744bad0eccaSFrançois Tigeot 	sc = device_get_softc(idev);
745bad0eccaSFrançois Tigeot 	sc->drm_dev = device_get_softc(device_get_parent(idev));
746bad0eccaSFrançois Tigeot 	dev_priv = sc->drm_dev->dev_private;
747bad0eccaSFrançois Tigeot 	pin = device_get_unit(idev);
748bad0eccaSFrançois Tigeot 
749bad0eccaSFrançois Tigeot 	ksnprintf(sc->name, sizeof(sc->name), "gmbus bus %s", gpio_names[pin]);
750bad0eccaSFrançois Tigeot 	device_set_desc(idev, sc->name);
751bad0eccaSFrançois Tigeot 
752bad0eccaSFrançois Tigeot 	/* By default use a conservative clock rate */
75319c468b4SFrançois Tigeot 	sc->reg0 = pin | GMBUS_RATE_100KHZ;
754bad0eccaSFrançois Tigeot 
755bad0eccaSFrançois Tigeot 	/* XXX force bit banging until GMBUS is fully debugged */
756bad0eccaSFrançois Tigeot 	if (IS_GEN2(sc->drm_dev)) {
757bad0eccaSFrançois Tigeot 		sc->force_bit_dev = true;
758bad0eccaSFrançois Tigeot 	}
759bad0eccaSFrançois Tigeot 
760bad0eccaSFrançois Tigeot 	/* add bus interface device */
761bad0eccaSFrançois Tigeot 	sc->iic_dev = device_add_child(idev, "iicbus", -1);
762bad0eccaSFrançois Tigeot 	if (sc->iic_dev == NULL)
763bad0eccaSFrançois Tigeot 		return (ENXIO);
764bad0eccaSFrançois Tigeot 	device_quiet(sc->iic_dev);
765bad0eccaSFrançois Tigeot 	bus_generic_attach(idev);
766bad0eccaSFrançois Tigeot 
767bad0eccaSFrançois Tigeot 	return (0);
768bad0eccaSFrançois Tigeot }
769bad0eccaSFrançois Tigeot 
770bad0eccaSFrançois Tigeot static int
771bad0eccaSFrançois Tigeot intel_gmbus_detach(device_t idev)
772bad0eccaSFrançois Tigeot {
773bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
774bad0eccaSFrançois Tigeot 	struct drm_i915_private *dev_priv;
775bad0eccaSFrançois Tigeot 	device_t child;
776bad0eccaSFrançois Tigeot 	int u;
777bad0eccaSFrançois Tigeot 
778bad0eccaSFrançois Tigeot 	sc = device_get_softc(idev);
779bad0eccaSFrançois Tigeot 	u = device_get_unit(idev);
780bad0eccaSFrançois Tigeot 	dev_priv = sc->drm_dev->dev_private;
781bad0eccaSFrançois Tigeot 
782bad0eccaSFrançois Tigeot 	child = sc->iic_dev;
783bad0eccaSFrançois Tigeot 	bus_generic_detach(idev);
784bad0eccaSFrançois Tigeot 	if (child != NULL)
785bad0eccaSFrançois Tigeot 		device_delete_child(idev, child);
786bad0eccaSFrançois Tigeot 
787bad0eccaSFrançois Tigeot 	return (0);
788bad0eccaSFrançois Tigeot }
789bad0eccaSFrançois Tigeot 
790bad0eccaSFrançois Tigeot static int
791bad0eccaSFrançois Tigeot intel_iicbb_probe(device_t dev)
792bad0eccaSFrançois Tigeot {
793bad0eccaSFrançois Tigeot 
794bad0eccaSFrançois Tigeot 	return (BUS_PROBE_DEFAULT);
795bad0eccaSFrançois Tigeot }
796bad0eccaSFrançois Tigeot 
797bad0eccaSFrançois Tigeot static int
798bad0eccaSFrançois Tigeot intel_iicbb_detach(device_t idev)
799bad0eccaSFrançois Tigeot {
800bad0eccaSFrançois Tigeot 	struct intel_iic_softc *sc;
801bad0eccaSFrançois Tigeot 	device_t child;
802bad0eccaSFrançois Tigeot 
803bad0eccaSFrançois Tigeot 	sc = device_get_softc(idev);
804bad0eccaSFrançois Tigeot 	child = sc->iic_dev;
805bad0eccaSFrançois Tigeot 	bus_generic_detach(idev);
806bad0eccaSFrançois Tigeot 	if (child)
807bad0eccaSFrançois Tigeot 		device_delete_child(idev, child);
808bad0eccaSFrançois Tigeot 	return (0);
809bad0eccaSFrançois Tigeot }
810bad0eccaSFrançois Tigeot 
811bad0eccaSFrançois Tigeot static device_method_t intel_gmbus_methods[] = {
812bad0eccaSFrançois Tigeot 	DEVMETHOD(device_probe,		intel_gmbus_probe),
813bad0eccaSFrançois Tigeot 	DEVMETHOD(device_attach,	intel_gmbus_attach),
814bad0eccaSFrançois Tigeot 	DEVMETHOD(device_detach,	intel_gmbus_detach),
815bad0eccaSFrançois Tigeot 	DEVMETHOD(iicbus_reset,		intel_iicbus_reset),
816a2fdbec6SFrançois Tigeot 	DEVMETHOD(iicbus_transfer,	gmbus_xfer),
817bad0eccaSFrançois Tigeot 	DEVMETHOD_END
818bad0eccaSFrançois Tigeot };
819bad0eccaSFrançois Tigeot static driver_t intel_gmbus_driver = {
820bad0eccaSFrançois Tigeot 	"intel_gmbus",
821bad0eccaSFrançois Tigeot 	intel_gmbus_methods,
822bad0eccaSFrançois Tigeot 	sizeof(struct intel_iic_softc)
823bad0eccaSFrançois Tigeot };
824bad0eccaSFrançois Tigeot static devclass_t intel_gmbus_devclass;
825bad0eccaSFrançois Tigeot DRIVER_MODULE_ORDERED(intel_gmbus, drm, intel_gmbus_driver,
826aa6ac96eSSascha Wildner     intel_gmbus_devclass, NULL, NULL, SI_ORDER_FIRST);
8273a25be87SSascha Wildner DRIVER_MODULE(iicbus, intel_gmbus, iicbus_driver, iicbus_devclass, NULL, NULL);
828bad0eccaSFrançois Tigeot 
829bad0eccaSFrançois Tigeot static device_method_t intel_iicbb_methods[] =	{
830bad0eccaSFrançois Tigeot 	DEVMETHOD(device_probe,		intel_iicbb_probe),
831a2fdbec6SFrançois Tigeot 	DEVMETHOD(device_attach,	intel_gpio_setup),
832bad0eccaSFrançois Tigeot 	DEVMETHOD(device_detach,	intel_iicbb_detach),
833bad0eccaSFrançois Tigeot 
834bad0eccaSFrançois Tigeot 	DEVMETHOD(bus_add_child,	bus_generic_add_child),
835bad0eccaSFrançois Tigeot 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
836bad0eccaSFrançois Tigeot 
837bad0eccaSFrançois Tigeot 	DEVMETHOD(iicbb_callback,	iicbus_null_callback),
838bad0eccaSFrançois Tigeot 	DEVMETHOD(iicbb_reset,		intel_iicbus_reset),
839a2fdbec6SFrançois Tigeot 	DEVMETHOD(iicbb_setsda,		set_data),
840a2fdbec6SFrançois Tigeot 	DEVMETHOD(iicbb_setscl,		set_clock),
841a2fdbec6SFrançois Tigeot 	DEVMETHOD(iicbb_getsda,		get_data),
842a2fdbec6SFrançois Tigeot 	DEVMETHOD(iicbb_getscl,		get_clock),
843bad0eccaSFrançois Tigeot 	DEVMETHOD_END
844bad0eccaSFrançois Tigeot };
845bad0eccaSFrançois Tigeot static driver_t intel_iicbb_driver = {
846bad0eccaSFrançois Tigeot 	"intel_iicbb",
847bad0eccaSFrançois Tigeot 	intel_iicbb_methods,
848bad0eccaSFrançois Tigeot 	sizeof(struct intel_iic_softc)
849bad0eccaSFrançois Tigeot };
850bad0eccaSFrançois Tigeot static devclass_t intel_iicbb_devclass;
851bad0eccaSFrançois Tigeot DRIVER_MODULE_ORDERED(intel_iicbb, drm, intel_iicbb_driver,
852aa6ac96eSSascha Wildner     intel_iicbb_devclass, NULL, NULL, SI_ORDER_FIRST);
8533a25be87SSascha Wildner DRIVER_MODULE(iicbb, intel_iicbb, iicbb_driver, iicbb_devclass, NULL, NULL);
854bad0eccaSFrançois Tigeot 
855a2fdbec6SFrançois Tigeot static void intel_teardown_gmbus_m(struct drm_device *dev, int m);
856a2fdbec6SFrançois Tigeot 
85719c468b4SFrançois Tigeot /**
85819c468b4SFrançois Tigeot  * intel_gmbus_setup - instantiate all Intel i2c GMBuses
85919c468b4SFrançois Tigeot  * @dev: DRM device
86019c468b4SFrançois Tigeot  */
86119c468b4SFrançois Tigeot int intel_setup_gmbus(struct drm_device *dev)
862bad0eccaSFrançois Tigeot {
863a2fdbec6SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
864bad0eccaSFrançois Tigeot 	device_t iic_dev;
86519c468b4SFrançois Tigeot 	unsigned int pin;
86619c468b4SFrançois Tigeot 	int ret;
867bad0eccaSFrançois Tigeot 
8688e26cdf6SFrançois Tigeot 	if (HAS_PCH_NOP(dev))
8698e26cdf6SFrançois Tigeot 		return 0;
8708e26cdf6SFrançois Tigeot 	else if (HAS_PCH_SPLIT(dev))
871a2fdbec6SFrançois Tigeot 		dev_priv->gpio_mmio_base = PCH_GPIOA - GPIOA;
872a2fdbec6SFrançois Tigeot 	else if (IS_VALLEYVIEW(dev))
873a2fdbec6SFrançois Tigeot 		dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE;
874a2fdbec6SFrançois Tigeot 	else
875a2fdbec6SFrançois Tigeot 		dev_priv->gpio_mmio_base = 0;
876a2fdbec6SFrançois Tigeot 
87719df918dSFrançois Tigeot 	lockinit(&dev_priv->gmbus_mutex, "gmbus", 0, LK_CANRECURSE);
878a2fdbec6SFrançois Tigeot 	init_waitqueue_head(&dev_priv->gmbus_wait_queue);
879a2fdbec6SFrançois Tigeot 
88019c468b4SFrançois Tigeot 	dev_priv->gmbus_bridge = kmalloc(sizeof(device_t) * GMBUS_NUM_PINS,
8815a3b77d5SFrançois Tigeot 	    M_DRM, M_WAITOK | M_ZERO);
88219c468b4SFrançois Tigeot 	dev_priv->bbbus_bridge = kmalloc(sizeof(device_t) * GMBUS_NUM_PINS,
8835a3b77d5SFrançois Tigeot 	    M_DRM, M_WAITOK | M_ZERO);
88419c468b4SFrançois Tigeot 	dev_priv->gmbus = kmalloc(sizeof(device_t) * GMBUS_NUM_PINS,
8855a3b77d5SFrançois Tigeot 	    M_DRM, M_WAITOK | M_ZERO);
88619c468b4SFrançois Tigeot 	dev_priv->bbbus = kmalloc(sizeof(device_t) * GMBUS_NUM_PINS,
8875a3b77d5SFrançois Tigeot 	    M_DRM, M_WAITOK | M_ZERO);
888bad0eccaSFrançois Tigeot 
88919c468b4SFrançois Tigeot 	for (pin = 0; pin < GMBUS_NUM_PINS; pin++) {
89019c468b4SFrançois Tigeot 		if (!intel_gmbus_is_valid_pin(dev_priv, pin))
89119c468b4SFrançois Tigeot 			continue;
89219c468b4SFrançois Tigeot 
893bad0eccaSFrançois Tigeot 		/*
894bad0eccaSFrançois Tigeot 		 * Initialized bbbus_bridge before gmbus_bridge, since
895bad0eccaSFrançois Tigeot 		 * gmbus may decide to force quirk transfer in the
896bad0eccaSFrançois Tigeot 		 * attachment code.
897bad0eccaSFrançois Tigeot 		 */
89819c468b4SFrançois Tigeot 		dev_priv->bbbus_bridge[pin] = device_add_child(dev->dev,
89919c468b4SFrançois Tigeot 		    "intel_iicbb", pin);
90019c468b4SFrançois Tigeot 		if (dev_priv->bbbus_bridge[pin] == NULL) {
90119c468b4SFrançois Tigeot 			DRM_ERROR("bbbus bridge %d creation failed\n", pin);
902bad0eccaSFrançois Tigeot 			ret = ENXIO;
903bad0eccaSFrançois Tigeot 			goto err;
904bad0eccaSFrançois Tigeot 		}
90519c468b4SFrançois Tigeot 		device_quiet(dev_priv->bbbus_bridge[pin]);
90619c468b4SFrançois Tigeot 		ret = device_probe_and_attach(dev_priv->bbbus_bridge[pin]);
907bad0eccaSFrançois Tigeot 		if (ret != 0) {
90819c468b4SFrançois Tigeot 			DRM_ERROR("bbbus bridge %d attach failed, %d\n", pin, ret);
909bad0eccaSFrançois Tigeot 			goto err;
910bad0eccaSFrançois Tigeot 		}
911bad0eccaSFrançois Tigeot 
91219c468b4SFrançois Tigeot 		iic_dev = device_find_child(dev_priv->bbbus_bridge[pin], "iicbb",
913bad0eccaSFrançois Tigeot 		    -1);
914bad0eccaSFrançois Tigeot 		if (iic_dev == NULL) {
915bad0eccaSFrançois Tigeot 			DRM_ERROR("bbbus bridge doesn't have iicbb child\n");
916bad0eccaSFrançois Tigeot 			goto err;
917bad0eccaSFrançois Tigeot 		}
918bad0eccaSFrançois Tigeot 		iic_dev = device_find_child(iic_dev, "iicbus", -1);
919bad0eccaSFrançois Tigeot 		if (iic_dev == NULL) {
920bad0eccaSFrançois Tigeot 			DRM_ERROR(
921bad0eccaSFrançois Tigeot 		"bbbus bridge doesn't have iicbus grandchild\n");
922bad0eccaSFrançois Tigeot 			goto err;
923bad0eccaSFrançois Tigeot 		}
924bad0eccaSFrançois Tigeot 
92519c468b4SFrançois Tigeot 		dev_priv->bbbus[pin] = iic_dev;
926bad0eccaSFrançois Tigeot 
92719c468b4SFrançois Tigeot 		dev_priv->gmbus_bridge[pin] = device_add_child(dev->dev,
92819c468b4SFrançois Tigeot 		    "intel_gmbus", pin);
92919c468b4SFrançois Tigeot 		if (dev_priv->gmbus_bridge[pin] == NULL) {
93019c468b4SFrançois Tigeot 			DRM_ERROR("gmbus bridge %d creation failed\n", pin);
931bad0eccaSFrançois Tigeot 			ret = ENXIO;
932bad0eccaSFrançois Tigeot 			goto err;
933bad0eccaSFrançois Tigeot 		}
93419c468b4SFrançois Tigeot 		device_quiet(dev_priv->gmbus_bridge[pin]);
93519c468b4SFrançois Tigeot 		ret = device_probe_and_attach(dev_priv->gmbus_bridge[pin]);
936bad0eccaSFrançois Tigeot 		if (ret != 0) {
93719c468b4SFrançois Tigeot 			DRM_ERROR("gmbus bridge %d attach failed, %d\n", pin,
938bad0eccaSFrançois Tigeot 			    ret);
939bad0eccaSFrançois Tigeot 			ret = ENXIO;
940bad0eccaSFrançois Tigeot 			goto err;
941bad0eccaSFrançois Tigeot 		}
942bad0eccaSFrançois Tigeot 
94319c468b4SFrançois Tigeot 		iic_dev = device_find_child(dev_priv->gmbus_bridge[pin],
944bad0eccaSFrançois Tigeot 		    "iicbus", -1);
945bad0eccaSFrançois Tigeot 		if (iic_dev == NULL) {
946bad0eccaSFrançois Tigeot 			DRM_ERROR("gmbus bridge doesn't have iicbus child\n");
947bad0eccaSFrançois Tigeot 			goto err;
948bad0eccaSFrançois Tigeot 		}
94919c468b4SFrançois Tigeot 		dev_priv->gmbus[pin] = iic_dev;
950bad0eccaSFrançois Tigeot 
9513f2f609dSFrançois Tigeot 		intel_i2c_reset(dev);
952bad0eccaSFrançois Tigeot 	}
953bad0eccaSFrançois Tigeot 
954bad0eccaSFrançois Tigeot 	return (0);
955bad0eccaSFrançois Tigeot 
956bad0eccaSFrançois Tigeot err:
95719c468b4SFrançois Tigeot 	intel_teardown_gmbus_m(dev, pin);
958bad0eccaSFrançois Tigeot 	return (ret);
959bad0eccaSFrançois Tigeot }
960bad0eccaSFrançois Tigeot 
961bad0eccaSFrançois Tigeot static void
962bad0eccaSFrançois Tigeot intel_teardown_gmbus_m(struct drm_device *dev, int m)
963bad0eccaSFrançois Tigeot {
964bad0eccaSFrançois Tigeot 	struct drm_i915_private *dev_priv;
965bad0eccaSFrançois Tigeot 
966bad0eccaSFrançois Tigeot 	dev_priv = dev->dev_private;
967bad0eccaSFrançois Tigeot 
968175896dfSzrj 	kfree(dev_priv->gmbus);
969bad0eccaSFrançois Tigeot 	dev_priv->gmbus = NULL;
970175896dfSzrj 	kfree(dev_priv->bbbus);
971bad0eccaSFrançois Tigeot 	dev_priv->bbbus = NULL;
972175896dfSzrj 	kfree(dev_priv->gmbus_bridge);
973bad0eccaSFrançois Tigeot 	dev_priv->gmbus_bridge = NULL;
974175896dfSzrj 	kfree(dev_priv->bbbus_bridge);
975bad0eccaSFrançois Tigeot 	dev_priv->bbbus_bridge = NULL;
97619df918dSFrançois Tigeot 	lockuninit(&dev_priv->gmbus_mutex);
977bad0eccaSFrançois Tigeot }
978bad0eccaSFrançois Tigeot 
979bad0eccaSFrançois Tigeot void
980bad0eccaSFrançois Tigeot intel_teardown_gmbus(struct drm_device *dev)
981bad0eccaSFrançois Tigeot {
982bad0eccaSFrançois Tigeot 
983bad0eccaSFrançois Tigeot 	get_mplock();
98419c468b4SFrançois Tigeot 	intel_teardown_gmbus_m(dev, GMBUS_NUM_PINS);
985bad0eccaSFrançois Tigeot 	rel_mplock();
986bad0eccaSFrançois Tigeot }
987