xref: /openbmc/linux/drivers/gpu/drm/gma500/intel_gmbus.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
15c0c1d50SPatrik Jakobsson /*
25c0c1d50SPatrik Jakobsson  * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
35c0c1d50SPatrik Jakobsson  * Copyright © 2006-2008,2010 Intel Corporation
45c0c1d50SPatrik Jakobsson  *   Jesse Barnes <jesse.barnes@intel.com>
55c0c1d50SPatrik Jakobsson  *
65c0c1d50SPatrik Jakobsson  * Permission is hereby granted, free of charge, to any person obtaining a
75c0c1d50SPatrik Jakobsson  * copy of this software and associated documentation files (the "Software"),
85c0c1d50SPatrik Jakobsson  * to deal in the Software without restriction, including without limitation
95c0c1d50SPatrik Jakobsson  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
105c0c1d50SPatrik Jakobsson  * and/or sell copies of the Software, and to permit persons to whom the
115c0c1d50SPatrik Jakobsson  * Software is furnished to do so, subject to the following conditions:
125c0c1d50SPatrik Jakobsson  *
135c0c1d50SPatrik Jakobsson  * The above copyright notice and this permission notice (including the next
145c0c1d50SPatrik Jakobsson  * paragraph) shall be included in all copies or substantial portions of the
155c0c1d50SPatrik Jakobsson  * Software.
165c0c1d50SPatrik Jakobsson  *
175c0c1d50SPatrik Jakobsson  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
185c0c1d50SPatrik Jakobsson  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
195c0c1d50SPatrik Jakobsson  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
205c0c1d50SPatrik Jakobsson  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
215c0c1d50SPatrik Jakobsson  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
225c0c1d50SPatrik Jakobsson  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
235c0c1d50SPatrik Jakobsson  * DEALINGS IN THE SOFTWARE.
245c0c1d50SPatrik Jakobsson  *
255c0c1d50SPatrik Jakobsson  * Authors:
265c0c1d50SPatrik Jakobsson  *	Eric Anholt <eric@anholt.net>
275c0c1d50SPatrik Jakobsson  *	Chris Wilson <chris@chris-wilson.co.uk>
285c0c1d50SPatrik Jakobsson  */
29d825c565SSam Ravnborg 
300c7b178aSSam Ravnborg #include <linux/delay.h>
310c7b178aSSam Ravnborg #include <linux/i2c-algo-bit.h>
320c7b178aSSam Ravnborg #include <linux/i2c.h>
330c7b178aSSam Ravnborg #include <linux/module.h>
340c7b178aSSam Ravnborg 
355c0c1d50SPatrik Jakobsson #include "psb_drv.h"
360c7b178aSSam Ravnborg #include "psb_intel_drv.h"
375c0c1d50SPatrik Jakobsson #include "psb_intel_reg.h"
385c0c1d50SPatrik Jakobsson 
395c0c1d50SPatrik Jakobsson #define _wait_for(COND, MS, W) ({ \
405c0c1d50SPatrik Jakobsson 	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);	\
415c0c1d50SPatrik Jakobsson 	int ret__ = 0;							\
425c0c1d50SPatrik Jakobsson 	while (! (COND)) {						\
435c0c1d50SPatrik Jakobsson 		if (time_after(jiffies, timeout__)) {			\
445c0c1d50SPatrik Jakobsson 			ret__ = -ETIMEDOUT;				\
455c0c1d50SPatrik Jakobsson 			break;						\
465c0c1d50SPatrik Jakobsson 		}							\
476f02e9dfSSebastian Andrzej Siewior 		if (W && !(in_dbg_master()))				\
486f02e9dfSSebastian Andrzej Siewior 			msleep(W);					\
495c0c1d50SPatrik Jakobsson 	}								\
505c0c1d50SPatrik Jakobsson 	ret__;								\
515c0c1d50SPatrik Jakobsson })
525c0c1d50SPatrik Jakobsson 
535c0c1d50SPatrik Jakobsson #define wait_for(COND, MS) _wait_for(COND, MS, 1)
545c0c1d50SPatrik Jakobsson 
5586bd4103SPatrik Jakobsson #define GMBUS_REG_READ(reg) ioread32(dev_priv->gmbus_reg + (reg))
5686bd4103SPatrik Jakobsson #define GMBUS_REG_WRITE(reg, val) iowrite32((val), dev_priv->gmbus_reg + (reg))
5786bd4103SPatrik Jakobsson 
585c0c1d50SPatrik Jakobsson /* Intel GPIO access functions */
595c0c1d50SPatrik Jakobsson 
605c0c1d50SPatrik Jakobsson #define I2C_RISEFALL_TIME 20
615c0c1d50SPatrik Jakobsson 
625c0c1d50SPatrik Jakobsson static inline struct intel_gmbus *
to_intel_gmbus(struct i2c_adapter * i2c)635c0c1d50SPatrik Jakobsson to_intel_gmbus(struct i2c_adapter *i2c)
645c0c1d50SPatrik Jakobsson {
655c0c1d50SPatrik Jakobsson 	return container_of(i2c, struct intel_gmbus, adapter);
665c0c1d50SPatrik Jakobsson }
675c0c1d50SPatrik Jakobsson 
685c0c1d50SPatrik Jakobsson struct intel_gpio {
695c0c1d50SPatrik Jakobsson 	struct i2c_adapter adapter;
705c0c1d50SPatrik Jakobsson 	struct i2c_algo_bit_data algo;
715c0c1d50SPatrik Jakobsson 	struct drm_psb_private *dev_priv;
725c0c1d50SPatrik Jakobsson 	u32 reg;
735c0c1d50SPatrik Jakobsson };
745c0c1d50SPatrik Jakobsson 
755c0c1d50SPatrik Jakobsson void
gma_intel_i2c_reset(struct drm_device * dev)765c0c1d50SPatrik Jakobsson gma_intel_i2c_reset(struct drm_device *dev)
775c0c1d50SPatrik Jakobsson {
78f71635e8SThomas Zimmermann 	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
7986bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(GMBUS0, 0);
805c0c1d50SPatrik Jakobsson }
815c0c1d50SPatrik Jakobsson 
intel_i2c_quirk_set(struct drm_psb_private * dev_priv,bool enable)825c0c1d50SPatrik Jakobsson static void intel_i2c_quirk_set(struct drm_psb_private *dev_priv, bool enable)
835c0c1d50SPatrik Jakobsson {
845c0c1d50SPatrik Jakobsson 	/* When using bit bashing for I2C, this bit needs to be set to 1 */
855c0c1d50SPatrik Jakobsson 	/* FIXME: We are never Pineview, right?
865c0c1d50SPatrik Jakobsson 
875c0c1d50SPatrik Jakobsson 	u32 val;
885c0c1d50SPatrik Jakobsson 
895c0c1d50SPatrik Jakobsson 	if (!IS_PINEVIEW(dev_priv->dev))
905c0c1d50SPatrik Jakobsson 		return;
915c0c1d50SPatrik Jakobsson 
925c0c1d50SPatrik Jakobsson 	val = REG_READ(DSPCLK_GATE_D);
935c0c1d50SPatrik Jakobsson 	if (enable)
945c0c1d50SPatrik Jakobsson 		val |= DPCUNIT_CLOCK_GATE_DISABLE;
955c0c1d50SPatrik Jakobsson 	else
965c0c1d50SPatrik Jakobsson 		val &= ~DPCUNIT_CLOCK_GATE_DISABLE;
975c0c1d50SPatrik Jakobsson 	REG_WRITE(DSPCLK_GATE_D, val);
985c0c1d50SPatrik Jakobsson 
995c0c1d50SPatrik Jakobsson 	return;
1005c0c1d50SPatrik Jakobsson 	*/
1015c0c1d50SPatrik Jakobsson }
1025c0c1d50SPatrik Jakobsson 
get_reserved(struct intel_gpio * gpio)1035c0c1d50SPatrik Jakobsson static u32 get_reserved(struct intel_gpio *gpio)
1045c0c1d50SPatrik Jakobsson {
1055c0c1d50SPatrik Jakobsson 	struct drm_psb_private *dev_priv = gpio->dev_priv;
1065c0c1d50SPatrik Jakobsson 	u32 reserved = 0;
1075c0c1d50SPatrik Jakobsson 
1085c0c1d50SPatrik Jakobsson 	/* On most chips, these bits must be preserved in software. */
10986bd4103SPatrik Jakobsson 	reserved = GMBUS_REG_READ(gpio->reg) &
1105c0c1d50SPatrik Jakobsson 				     (GPIO_DATA_PULLUP_DISABLE |
1115c0c1d50SPatrik Jakobsson 				      GPIO_CLOCK_PULLUP_DISABLE);
1125c0c1d50SPatrik Jakobsson 
1135c0c1d50SPatrik Jakobsson 	return reserved;
1145c0c1d50SPatrik Jakobsson }
1155c0c1d50SPatrik Jakobsson 
get_clock(void * data)1165c0c1d50SPatrik Jakobsson static int get_clock(void *data)
1175c0c1d50SPatrik Jakobsson {
1185c0c1d50SPatrik Jakobsson 	struct intel_gpio *gpio = data;
1195c0c1d50SPatrik Jakobsson 	struct drm_psb_private *dev_priv = gpio->dev_priv;
1205c0c1d50SPatrik Jakobsson 	u32 reserved = get_reserved(gpio);
12186bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK);
12286bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(gpio->reg, reserved);
12386bd4103SPatrik Jakobsson 	return (GMBUS_REG_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0;
1245c0c1d50SPatrik Jakobsson }
1255c0c1d50SPatrik Jakobsson 
get_data(void * data)1265c0c1d50SPatrik Jakobsson static int get_data(void *data)
1275c0c1d50SPatrik Jakobsson {
1285c0c1d50SPatrik Jakobsson 	struct intel_gpio *gpio = data;
1295c0c1d50SPatrik Jakobsson 	struct drm_psb_private *dev_priv = gpio->dev_priv;
1305c0c1d50SPatrik Jakobsson 	u32 reserved = get_reserved(gpio);
13186bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK);
13286bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(gpio->reg, reserved);
13386bd4103SPatrik Jakobsson 	return (GMBUS_REG_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
1345c0c1d50SPatrik Jakobsson }
1355c0c1d50SPatrik Jakobsson 
set_clock(void * data,int state_high)1365c0c1d50SPatrik Jakobsson static void set_clock(void *data, int state_high)
1375c0c1d50SPatrik Jakobsson {
1385c0c1d50SPatrik Jakobsson 	struct intel_gpio *gpio = data;
1395c0c1d50SPatrik Jakobsson 	struct drm_psb_private *dev_priv = gpio->dev_priv;
1405c0c1d50SPatrik Jakobsson 	u32 reserved = get_reserved(gpio);
1415c0c1d50SPatrik Jakobsson 	u32 clock_bits;
1425c0c1d50SPatrik Jakobsson 
1435c0c1d50SPatrik Jakobsson 	if (state_high)
1445c0c1d50SPatrik Jakobsson 		clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
1455c0c1d50SPatrik Jakobsson 	else
1465c0c1d50SPatrik Jakobsson 		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
1475c0c1d50SPatrik Jakobsson 			GPIO_CLOCK_VAL_MASK;
1485c0c1d50SPatrik Jakobsson 
14986bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(gpio->reg, reserved | clock_bits);
15086bd4103SPatrik Jakobsson 	GMBUS_REG_READ(gpio->reg); /* Posting */
1515c0c1d50SPatrik Jakobsson }
1525c0c1d50SPatrik Jakobsson 
set_data(void * data,int state_high)1535c0c1d50SPatrik Jakobsson static void set_data(void *data, int state_high)
1545c0c1d50SPatrik Jakobsson {
1555c0c1d50SPatrik Jakobsson 	struct intel_gpio *gpio = data;
1565c0c1d50SPatrik Jakobsson 	struct drm_psb_private *dev_priv = gpio->dev_priv;
1575c0c1d50SPatrik Jakobsson 	u32 reserved = get_reserved(gpio);
1585c0c1d50SPatrik Jakobsson 	u32 data_bits;
1595c0c1d50SPatrik Jakobsson 
1605c0c1d50SPatrik Jakobsson 	if (state_high)
1615c0c1d50SPatrik Jakobsson 		data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
1625c0c1d50SPatrik Jakobsson 	else
1635c0c1d50SPatrik Jakobsson 		data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
1645c0c1d50SPatrik Jakobsson 			GPIO_DATA_VAL_MASK;
1655c0c1d50SPatrik Jakobsson 
16686bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(gpio->reg, reserved | data_bits);
16786bd4103SPatrik Jakobsson 	GMBUS_REG_READ(gpio->reg);
1685c0c1d50SPatrik Jakobsson }
1695c0c1d50SPatrik Jakobsson 
1705c0c1d50SPatrik Jakobsson static struct i2c_adapter *
intel_gpio_create(struct drm_psb_private * dev_priv,u32 pin)1715c0c1d50SPatrik Jakobsson intel_gpio_create(struct drm_psb_private *dev_priv, u32 pin)
1725c0c1d50SPatrik Jakobsson {
1735c0c1d50SPatrik Jakobsson 	static const int map_pin_to_reg[] = {
1745c0c1d50SPatrik Jakobsson 		0,
1755c0c1d50SPatrik Jakobsson 		GPIOB,
1765c0c1d50SPatrik Jakobsson 		GPIOA,
1775c0c1d50SPatrik Jakobsson 		GPIOC,
1785c0c1d50SPatrik Jakobsson 		GPIOD,
1795c0c1d50SPatrik Jakobsson 		GPIOE,
1805c0c1d50SPatrik Jakobsson 		0,
1815c0c1d50SPatrik Jakobsson 		GPIOF,
1825c0c1d50SPatrik Jakobsson 	};
1835c0c1d50SPatrik Jakobsson 	struct intel_gpio *gpio;
1845c0c1d50SPatrik Jakobsson 
1855c0c1d50SPatrik Jakobsson 	if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin])
1865c0c1d50SPatrik Jakobsson 		return NULL;
1875c0c1d50SPatrik Jakobsson 
1885c0c1d50SPatrik Jakobsson 	gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL);
1895c0c1d50SPatrik Jakobsson 	if (gpio == NULL)
1905c0c1d50SPatrik Jakobsson 		return NULL;
1915c0c1d50SPatrik Jakobsson 
1925c0c1d50SPatrik Jakobsson 	gpio->reg = map_pin_to_reg[pin];
1935c0c1d50SPatrik Jakobsson 	gpio->dev_priv = dev_priv;
1945c0c1d50SPatrik Jakobsson 
1955c0c1d50SPatrik Jakobsson 	snprintf(gpio->adapter.name, sizeof(gpio->adapter.name),
1965c0c1d50SPatrik Jakobsson 		 "gma500 GPIO%c", "?BACDE?F"[pin]);
1975c0c1d50SPatrik Jakobsson 	gpio->adapter.owner = THIS_MODULE;
1985c0c1d50SPatrik Jakobsson 	gpio->adapter.algo_data	= &gpio->algo;
199*c2f17e60SThomas Zimmermann 	gpio->adapter.dev.parent = dev_priv->dev.dev;
2005c0c1d50SPatrik Jakobsson 	gpio->algo.setsda = set_data;
2015c0c1d50SPatrik Jakobsson 	gpio->algo.setscl = set_clock;
2025c0c1d50SPatrik Jakobsson 	gpio->algo.getsda = get_data;
2035c0c1d50SPatrik Jakobsson 	gpio->algo.getscl = get_clock;
2045c0c1d50SPatrik Jakobsson 	gpio->algo.udelay = I2C_RISEFALL_TIME;
2055c0c1d50SPatrik Jakobsson 	gpio->algo.timeout = usecs_to_jiffies(2200);
2065c0c1d50SPatrik Jakobsson 	gpio->algo.data = gpio;
2075c0c1d50SPatrik Jakobsson 
2085c0c1d50SPatrik Jakobsson 	if (i2c_bit_add_bus(&gpio->adapter))
2095c0c1d50SPatrik Jakobsson 		goto out_free;
2105c0c1d50SPatrik Jakobsson 
2115c0c1d50SPatrik Jakobsson 	return &gpio->adapter;
2125c0c1d50SPatrik Jakobsson 
2135c0c1d50SPatrik Jakobsson out_free:
2145c0c1d50SPatrik Jakobsson 	kfree(gpio);
2155c0c1d50SPatrik Jakobsson 	return NULL;
2165c0c1d50SPatrik Jakobsson }
2175c0c1d50SPatrik Jakobsson 
2185c0c1d50SPatrik Jakobsson static int
intel_i2c_quirk_xfer(struct drm_psb_private * dev_priv,struct i2c_adapter * adapter,struct i2c_msg * msgs,int num)2195c0c1d50SPatrik Jakobsson intel_i2c_quirk_xfer(struct drm_psb_private *dev_priv,
2205c0c1d50SPatrik Jakobsson 		     struct i2c_adapter *adapter,
2215c0c1d50SPatrik Jakobsson 		     struct i2c_msg *msgs,
2225c0c1d50SPatrik Jakobsson 		     int num)
2235c0c1d50SPatrik Jakobsson {
2245c0c1d50SPatrik Jakobsson 	struct intel_gpio *gpio = container_of(adapter,
2255c0c1d50SPatrik Jakobsson 					       struct intel_gpio,
2265c0c1d50SPatrik Jakobsson 					       adapter);
2275c0c1d50SPatrik Jakobsson 	int ret;
2285c0c1d50SPatrik Jakobsson 
229*c2f17e60SThomas Zimmermann 	gma_intel_i2c_reset(&dev_priv->dev);
2305c0c1d50SPatrik Jakobsson 
2315c0c1d50SPatrik Jakobsson 	intel_i2c_quirk_set(dev_priv, true);
2325c0c1d50SPatrik Jakobsson 	set_data(gpio, 1);
2335c0c1d50SPatrik Jakobsson 	set_clock(gpio, 1);
2345c0c1d50SPatrik Jakobsson 	udelay(I2C_RISEFALL_TIME);
2355c0c1d50SPatrik Jakobsson 
2365c0c1d50SPatrik Jakobsson 	ret = adapter->algo->master_xfer(adapter, msgs, num);
2375c0c1d50SPatrik Jakobsson 
2385c0c1d50SPatrik Jakobsson 	set_data(gpio, 1);
2395c0c1d50SPatrik Jakobsson 	set_clock(gpio, 1);
2405c0c1d50SPatrik Jakobsson 	intel_i2c_quirk_set(dev_priv, false);
2415c0c1d50SPatrik Jakobsson 
2425c0c1d50SPatrik Jakobsson 	return ret;
2435c0c1d50SPatrik Jakobsson }
2445c0c1d50SPatrik Jakobsson 
2455c0c1d50SPatrik Jakobsson static int
gmbus_xfer(struct i2c_adapter * adapter,struct i2c_msg * msgs,int num)2465c0c1d50SPatrik Jakobsson gmbus_xfer(struct i2c_adapter *adapter,
2475c0c1d50SPatrik Jakobsson 	   struct i2c_msg *msgs,
2485c0c1d50SPatrik Jakobsson 	   int num)
2495c0c1d50SPatrik Jakobsson {
2505c0c1d50SPatrik Jakobsson 	struct intel_gmbus *bus = container_of(adapter,
2515c0c1d50SPatrik Jakobsson 					       struct intel_gmbus,
2525c0c1d50SPatrik Jakobsson 					       adapter);
2535c0c1d50SPatrik Jakobsson 	struct drm_psb_private *dev_priv = adapter->algo_data;
2545c0c1d50SPatrik Jakobsson 	int i, reg_offset;
2555c0c1d50SPatrik Jakobsson 
2565c0c1d50SPatrik Jakobsson 	if (bus->force_bit)
2575c0c1d50SPatrik Jakobsson 		return intel_i2c_quirk_xfer(dev_priv,
2585c0c1d50SPatrik Jakobsson 					    bus->force_bit, msgs, num);
2595c0c1d50SPatrik Jakobsson 
2605c0c1d50SPatrik Jakobsson 	reg_offset = 0;
2615c0c1d50SPatrik Jakobsson 
26286bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(GMBUS0 + reg_offset, bus->reg0);
2635c0c1d50SPatrik Jakobsson 
2645c0c1d50SPatrik Jakobsson 	for (i = 0; i < num; i++) {
2655c0c1d50SPatrik Jakobsson 		u16 len = msgs[i].len;
2665c0c1d50SPatrik Jakobsson 		u8 *buf = msgs[i].buf;
2675c0c1d50SPatrik Jakobsson 
2685c0c1d50SPatrik Jakobsson 		if (msgs[i].flags & I2C_M_RD) {
26986bd4103SPatrik Jakobsson 			GMBUS_REG_WRITE(GMBUS1 + reg_offset,
27086bd4103SPatrik Jakobsson 					GMBUS_CYCLE_WAIT |
27186bd4103SPatrik Jakobsson 					(i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
2725c0c1d50SPatrik Jakobsson 					(len << GMBUS_BYTE_COUNT_SHIFT) |
2735c0c1d50SPatrik Jakobsson 					(msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
2745c0c1d50SPatrik Jakobsson 					GMBUS_SLAVE_READ | GMBUS_SW_RDY);
27586bd4103SPatrik Jakobsson 			GMBUS_REG_READ(GMBUS2+reg_offset);
2765c0c1d50SPatrik Jakobsson 			do {
2775c0c1d50SPatrik Jakobsson 				u32 val, loop = 0;
2785c0c1d50SPatrik Jakobsson 
27986bd4103SPatrik Jakobsson 				if (wait_for(GMBUS_REG_READ(GMBUS2 + reg_offset) &
28086bd4103SPatrik Jakobsson 					     (GMBUS_SATOER | GMBUS_HW_RDY), 50))
2815c0c1d50SPatrik Jakobsson 					goto timeout;
28286bd4103SPatrik Jakobsson 				if (GMBUS_REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
2835c0c1d50SPatrik Jakobsson 					goto clear_err;
2845c0c1d50SPatrik Jakobsson 
28586bd4103SPatrik Jakobsson 				val = GMBUS_REG_READ(GMBUS3 + reg_offset);
2865c0c1d50SPatrik Jakobsson 				do {
2875c0c1d50SPatrik Jakobsson 					*buf++ = val & 0xff;
2885c0c1d50SPatrik Jakobsson 					val >>= 8;
2895c0c1d50SPatrik Jakobsson 				} while (--len && ++loop < 4);
2905c0c1d50SPatrik Jakobsson 			} while (len);
2915c0c1d50SPatrik Jakobsson 		} else {
2925c0c1d50SPatrik Jakobsson 			u32 val, loop;
2935c0c1d50SPatrik Jakobsson 
2945c0c1d50SPatrik Jakobsson 			val = loop = 0;
2955c0c1d50SPatrik Jakobsson 			do {
2965c0c1d50SPatrik Jakobsson 				val |= *buf++ << (8 * loop);
2975c0c1d50SPatrik Jakobsson 			} while (--len && ++loop < 4);
2985c0c1d50SPatrik Jakobsson 
29986bd4103SPatrik Jakobsson 			GMBUS_REG_WRITE(GMBUS3 + reg_offset, val);
30086bd4103SPatrik Jakobsson 			GMBUS_REG_WRITE(GMBUS1 + reg_offset,
3015c0c1d50SPatrik Jakobsson 				   (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) |
3025c0c1d50SPatrik Jakobsson 				   (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) |
3035c0c1d50SPatrik Jakobsson 				   (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
3045c0c1d50SPatrik Jakobsson 				   GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
30586bd4103SPatrik Jakobsson 			GMBUS_REG_READ(GMBUS2+reg_offset);
3065c0c1d50SPatrik Jakobsson 
3075c0c1d50SPatrik Jakobsson 			while (len) {
30886bd4103SPatrik Jakobsson 				if (wait_for(GMBUS_REG_READ(GMBUS2 + reg_offset) &
30986bd4103SPatrik Jakobsson 					     (GMBUS_SATOER | GMBUS_HW_RDY), 50))
3105c0c1d50SPatrik Jakobsson 					goto timeout;
31186bd4103SPatrik Jakobsson 				if (GMBUS_REG_READ(GMBUS2 + reg_offset) &
31286bd4103SPatrik Jakobsson 				    GMBUS_SATOER)
3135c0c1d50SPatrik Jakobsson 					goto clear_err;
3145c0c1d50SPatrik Jakobsson 
3155c0c1d50SPatrik Jakobsson 				val = loop = 0;
3165c0c1d50SPatrik Jakobsson 				do {
3175c0c1d50SPatrik Jakobsson 					val |= *buf++ << (8 * loop);
3185c0c1d50SPatrik Jakobsson 				} while (--len && ++loop < 4);
3195c0c1d50SPatrik Jakobsson 
32086bd4103SPatrik Jakobsson 				GMBUS_REG_WRITE(GMBUS3 + reg_offset, val);
32186bd4103SPatrik Jakobsson 				GMBUS_REG_READ(GMBUS2+reg_offset);
3225c0c1d50SPatrik Jakobsson 			}
3235c0c1d50SPatrik Jakobsson 		}
3245c0c1d50SPatrik Jakobsson 
32586bd4103SPatrik Jakobsson 		if (i + 1 < num && wait_for(GMBUS_REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50))
3265c0c1d50SPatrik Jakobsson 			goto timeout;
32786bd4103SPatrik Jakobsson 		if (GMBUS_REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
3285c0c1d50SPatrik Jakobsson 			goto clear_err;
3295c0c1d50SPatrik Jakobsson 	}
3305c0c1d50SPatrik Jakobsson 
3315c0c1d50SPatrik Jakobsson 	goto done;
3325c0c1d50SPatrik Jakobsson 
3335c0c1d50SPatrik Jakobsson clear_err:
3345c0c1d50SPatrik Jakobsson 	/* Toggle the Software Clear Interrupt bit. This has the effect
3355c0c1d50SPatrik Jakobsson 	 * of resetting the GMBUS controller and so clearing the
3365c0c1d50SPatrik Jakobsson 	 * BUS_ERROR raised by the slave's NAK.
3375c0c1d50SPatrik Jakobsson 	 */
33886bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT);
33986bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(GMBUS1 + reg_offset, 0);
3405c0c1d50SPatrik Jakobsson 
3415c0c1d50SPatrik Jakobsson done:
3425c0c1d50SPatrik Jakobsson 	/* Mark the GMBUS interface as disabled. We will re-enable it at the
3435c0c1d50SPatrik Jakobsson 	 * start of the next xfer, till then let it sleep.
3445c0c1d50SPatrik Jakobsson 	 */
34586bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(GMBUS0 + reg_offset, 0);
3465c0c1d50SPatrik Jakobsson 	return i;
3475c0c1d50SPatrik Jakobsson 
3485c0c1d50SPatrik Jakobsson timeout:
3495c0c1d50SPatrik Jakobsson 	DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n",
3505c0c1d50SPatrik Jakobsson 		 bus->reg0 & 0xff, bus->adapter.name);
35186bd4103SPatrik Jakobsson 	GMBUS_REG_WRITE(GMBUS0 + reg_offset, 0);
3525c0c1d50SPatrik Jakobsson 
3535c0c1d50SPatrik Jakobsson 	/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
3545c0c1d50SPatrik Jakobsson 	bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff);
3555c0c1d50SPatrik Jakobsson 	if (!bus->force_bit)
3565c0c1d50SPatrik Jakobsson 		return -ENOMEM;
3575c0c1d50SPatrik Jakobsson 
3585c0c1d50SPatrik Jakobsson 	return intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num);
3595c0c1d50SPatrik Jakobsson }
3605c0c1d50SPatrik Jakobsson 
gmbus_func(struct i2c_adapter * adapter)3615c0c1d50SPatrik Jakobsson static u32 gmbus_func(struct i2c_adapter *adapter)
3625c0c1d50SPatrik Jakobsson {
3635c0c1d50SPatrik Jakobsson 	struct intel_gmbus *bus = container_of(adapter,
3645c0c1d50SPatrik Jakobsson 					       struct intel_gmbus,
3655c0c1d50SPatrik Jakobsson 					       adapter);
3665c0c1d50SPatrik Jakobsson 
3675c0c1d50SPatrik Jakobsson 	if (bus->force_bit)
3685c0c1d50SPatrik Jakobsson 		bus->force_bit->algo->functionality(bus->force_bit);
3695c0c1d50SPatrik Jakobsson 
3705c0c1d50SPatrik Jakobsson 	return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
3715c0c1d50SPatrik Jakobsson 		/* I2C_FUNC_10BIT_ADDR | */
3725c0c1d50SPatrik Jakobsson 		I2C_FUNC_SMBUS_READ_BLOCK_DATA |
3735c0c1d50SPatrik Jakobsson 		I2C_FUNC_SMBUS_BLOCK_PROC_CALL);
3745c0c1d50SPatrik Jakobsson }
3755c0c1d50SPatrik Jakobsson 
3765c0c1d50SPatrik Jakobsson static const struct i2c_algorithm gmbus_algorithm = {
3775c0c1d50SPatrik Jakobsson 	.master_xfer	= gmbus_xfer,
3785c0c1d50SPatrik Jakobsson 	.functionality	= gmbus_func
3795c0c1d50SPatrik Jakobsson };
3805c0c1d50SPatrik Jakobsson 
3815c0c1d50SPatrik Jakobsson /**
382866604bbSKrzysztof Kozlowski  * gma_intel_setup_gmbus() - instantiate all Intel i2c GMBuses
3835c0c1d50SPatrik Jakobsson  * @dev: DRM device
3845c0c1d50SPatrik Jakobsson  */
gma_intel_setup_gmbus(struct drm_device * dev)3855c0c1d50SPatrik Jakobsson int gma_intel_setup_gmbus(struct drm_device *dev)
3865c0c1d50SPatrik Jakobsson {
3875c0c1d50SPatrik Jakobsson 	static const char *names[GMBUS_NUM_PORTS] = {
3885c0c1d50SPatrik Jakobsson 		"disabled",
3895c0c1d50SPatrik Jakobsson 		"ssc",
3905c0c1d50SPatrik Jakobsson 		"vga",
3915c0c1d50SPatrik Jakobsson 		"panel",
3925c0c1d50SPatrik Jakobsson 		"dpc",
3935c0c1d50SPatrik Jakobsson 		"dpb",
3945c0c1d50SPatrik Jakobsson 		"reserved",
3955c0c1d50SPatrik Jakobsson 		"dpd",
3965c0c1d50SPatrik Jakobsson 	};
397f71635e8SThomas Zimmermann 	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
3985c0c1d50SPatrik Jakobsson 	int ret, i;
3995c0c1d50SPatrik Jakobsson 
40051a59ac8SAxel Lin 	dev_priv->gmbus = kcalloc(GMBUS_NUM_PORTS, sizeof(struct intel_gmbus),
4015c0c1d50SPatrik Jakobsson 				  GFP_KERNEL);
4025c0c1d50SPatrik Jakobsson 	if (dev_priv->gmbus == NULL)
4035c0c1d50SPatrik Jakobsson 		return -ENOMEM;
4045c0c1d50SPatrik Jakobsson 
40586bd4103SPatrik Jakobsson 	if (IS_MRST(dev))
40686bd4103SPatrik Jakobsson 		dev_priv->gmbus_reg = dev_priv->aux_reg;
40786bd4103SPatrik Jakobsson 	else
40886bd4103SPatrik Jakobsson 		dev_priv->gmbus_reg = dev_priv->vdc_reg;
40986bd4103SPatrik Jakobsson 
4105c0c1d50SPatrik Jakobsson 	for (i = 0; i < GMBUS_NUM_PORTS; i++) {
4115c0c1d50SPatrik Jakobsson 		struct intel_gmbus *bus = &dev_priv->gmbus[i];
4125c0c1d50SPatrik Jakobsson 
4135c0c1d50SPatrik Jakobsson 		bus->adapter.owner = THIS_MODULE;
4145c0c1d50SPatrik Jakobsson 		bus->adapter.class = I2C_CLASS_DDC;
4155c0c1d50SPatrik Jakobsson 		snprintf(bus->adapter.name,
4165c0c1d50SPatrik Jakobsson 			 sizeof(bus->adapter.name),
4175c0c1d50SPatrik Jakobsson 			 "gma500 gmbus %s",
4185c0c1d50SPatrik Jakobsson 			 names[i]);
4195c0c1d50SPatrik Jakobsson 
420a2c68495SThomas Zimmermann 		bus->adapter.dev.parent = dev->dev;
4215c0c1d50SPatrik Jakobsson 		bus->adapter.algo_data	= dev_priv;
4225c0c1d50SPatrik Jakobsson 
4235c0c1d50SPatrik Jakobsson 		bus->adapter.algo = &gmbus_algorithm;
4245c0c1d50SPatrik Jakobsson 		ret = i2c_add_adapter(&bus->adapter);
4255c0c1d50SPatrik Jakobsson 		if (ret)
4265c0c1d50SPatrik Jakobsson 			goto err;
4275c0c1d50SPatrik Jakobsson 
4285c0c1d50SPatrik Jakobsson 		/* By default use a conservative clock rate */
4295c0c1d50SPatrik Jakobsson 		bus->reg0 = i | GMBUS_RATE_100KHZ;
4305c0c1d50SPatrik Jakobsson 
4315c0c1d50SPatrik Jakobsson 		/* XXX force bit banging until GMBUS is fully debugged */
4325c0c1d50SPatrik Jakobsson 		bus->force_bit = intel_gpio_create(dev_priv, i);
4335c0c1d50SPatrik Jakobsson 	}
4345c0c1d50SPatrik Jakobsson 
435*c2f17e60SThomas Zimmermann 	gma_intel_i2c_reset(&dev_priv->dev);
4365c0c1d50SPatrik Jakobsson 
4375c0c1d50SPatrik Jakobsson 	return 0;
4385c0c1d50SPatrik Jakobsson 
4395c0c1d50SPatrik Jakobsson err:
44052dfa12eSRasmus Villemoes 	while (i--) {
4415c0c1d50SPatrik Jakobsson 		struct intel_gmbus *bus = &dev_priv->gmbus[i];
4425c0c1d50SPatrik Jakobsson 		i2c_del_adapter(&bus->adapter);
4435c0c1d50SPatrik Jakobsson 	}
4445c0c1d50SPatrik Jakobsson 	kfree(dev_priv->gmbus);
4455c0c1d50SPatrik Jakobsson 	dev_priv->gmbus = NULL;
4465c0c1d50SPatrik Jakobsson 	return ret;
4475c0c1d50SPatrik Jakobsson }
4485c0c1d50SPatrik Jakobsson 
gma_intel_gmbus_set_speed(struct i2c_adapter * adapter,int speed)4495c0c1d50SPatrik Jakobsson void gma_intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed)
4505c0c1d50SPatrik Jakobsson {
4515c0c1d50SPatrik Jakobsson 	struct intel_gmbus *bus = to_intel_gmbus(adapter);
4525c0c1d50SPatrik Jakobsson 
4535c0c1d50SPatrik Jakobsson 	/* speed:
4545c0c1d50SPatrik Jakobsson 	 * 0x0 = 100 KHz
4555c0c1d50SPatrik Jakobsson 	 * 0x1 = 50 KHz
4565c0c1d50SPatrik Jakobsson 	 * 0x2 = 400 KHz
4575c0c1d50SPatrik Jakobsson 	 * 0x3 = 1000 Khz
4585c0c1d50SPatrik Jakobsson 	 */
4595c0c1d50SPatrik Jakobsson 	bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8);
4605c0c1d50SPatrik Jakobsson }
4615c0c1d50SPatrik Jakobsson 
gma_intel_gmbus_force_bit(struct i2c_adapter * adapter,bool force_bit)4625c0c1d50SPatrik Jakobsson void gma_intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
4635c0c1d50SPatrik Jakobsson {
4645c0c1d50SPatrik Jakobsson 	struct intel_gmbus *bus = to_intel_gmbus(adapter);
4655c0c1d50SPatrik Jakobsson 
4665c0c1d50SPatrik Jakobsson 	if (force_bit) {
4675c0c1d50SPatrik Jakobsson 		if (bus->force_bit == NULL) {
4685c0c1d50SPatrik Jakobsson 			struct drm_psb_private *dev_priv = adapter->algo_data;
4695c0c1d50SPatrik Jakobsson 			bus->force_bit = intel_gpio_create(dev_priv,
4705c0c1d50SPatrik Jakobsson 							   bus->reg0 & 0xff);
4715c0c1d50SPatrik Jakobsson 		}
4725c0c1d50SPatrik Jakobsson 	} else {
4735c0c1d50SPatrik Jakobsson 		if (bus->force_bit) {
4745c0c1d50SPatrik Jakobsson 			i2c_del_adapter(bus->force_bit);
4755c0c1d50SPatrik Jakobsson 			kfree(bus->force_bit);
4765c0c1d50SPatrik Jakobsson 			bus->force_bit = NULL;
4775c0c1d50SPatrik Jakobsson 		}
4785c0c1d50SPatrik Jakobsson 	}
4795c0c1d50SPatrik Jakobsson }
4805c0c1d50SPatrik Jakobsson 
gma_intel_teardown_gmbus(struct drm_device * dev)4815c0c1d50SPatrik Jakobsson void gma_intel_teardown_gmbus(struct drm_device *dev)
4825c0c1d50SPatrik Jakobsson {
483f71635e8SThomas Zimmermann 	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
4845c0c1d50SPatrik Jakobsson 	int i;
4855c0c1d50SPatrik Jakobsson 
4865c0c1d50SPatrik Jakobsson 	if (dev_priv->gmbus == NULL)
4875c0c1d50SPatrik Jakobsson 		return;
4885c0c1d50SPatrik Jakobsson 
4895c0c1d50SPatrik Jakobsson 	for (i = 0; i < GMBUS_NUM_PORTS; i++) {
4905c0c1d50SPatrik Jakobsson 		struct intel_gmbus *bus = &dev_priv->gmbus[i];
4915c0c1d50SPatrik Jakobsson 		if (bus->force_bit) {
4925c0c1d50SPatrik Jakobsson 			i2c_del_adapter(bus->force_bit);
4935c0c1d50SPatrik Jakobsson 			kfree(bus->force_bit);
4945c0c1d50SPatrik Jakobsson 		}
4955c0c1d50SPatrik Jakobsson 		i2c_del_adapter(&bus->adapter);
4965c0c1d50SPatrik Jakobsson 	}
4975c0c1d50SPatrik Jakobsson 
49886bd4103SPatrik Jakobsson 	dev_priv->gmbus_reg = NULL; /* iounmap is done in driver_unload */
4995c0c1d50SPatrik Jakobsson 	kfree(dev_priv->gmbus);
5005c0c1d50SPatrik Jakobsson 	dev_priv->gmbus = NULL;
5015c0c1d50SPatrik Jakobsson }
502