diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_i2c.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 206 | 
1 files changed, 90 insertions, 116 deletions
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index d30ccccb9d7..601c86e664a 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -37,7 +37,7 @@  /* Intel GPIO access functions */ -#define I2C_RISEFALL_TIME 20 +#define I2C_RISEFALL_TIME 10  static inline struct intel_gmbus *  to_intel_gmbus(struct i2c_adapter *i2c) @@ -45,13 +45,6 @@ to_intel_gmbus(struct i2c_adapter *i2c)  	return container_of(i2c, struct intel_gmbus, adapter);  } -struct intel_gpio { -	struct i2c_adapter adapter; -	struct i2c_algo_bit_data algo; -	struct drm_i915_private *dev_priv; -	u32 reg; -}; -  void  intel_i2c_reset(struct drm_device *dev)  { @@ -78,15 +71,15 @@ static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)  	I915_WRITE(DSPCLK_GATE_D, val);  } -static u32 get_reserved(struct intel_gpio *gpio) +static u32 get_reserved(struct intel_gmbus *bus)  { -	struct drm_i915_private *dev_priv = gpio->dev_priv; +	struct drm_i915_private *dev_priv = bus->dev_priv;  	struct drm_device *dev = dev_priv->dev;  	u32 reserved = 0;  	/* On most chips, these bits must be preserved in software. */  	if (!IS_I830(dev) && !IS_845G(dev)) -		reserved = I915_READ_NOTRACE(gpio->reg) & +		reserved = I915_READ_NOTRACE(bus->gpio_reg) &  					     (GPIO_DATA_PULLUP_DISABLE |  					      GPIO_CLOCK_PULLUP_DISABLE); @@ -95,29 +88,29 @@ static u32 get_reserved(struct intel_gpio *gpio)  static int get_clock(void *data)  { -	struct intel_gpio *gpio = data; -	struct drm_i915_private *dev_priv = gpio->dev_priv; -	u32 reserved = get_reserved(gpio); -	I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); -	I915_WRITE_NOTRACE(gpio->reg, reserved); -	return (I915_READ_NOTRACE(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; +	struct intel_gmbus *bus = data; +	struct drm_i915_private *dev_priv = bus->dev_priv; +	u32 reserved = get_reserved(bus); +	I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK); +	I915_WRITE_NOTRACE(bus->gpio_reg, reserved); +	return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0;  }  static int get_data(void *data)  { -	struct intel_gpio *gpio = data; -	struct drm_i915_private *dev_priv = gpio->dev_priv; -	u32 reserved = get_reserved(gpio); -	I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); -	I915_WRITE_NOTRACE(gpio->reg, reserved); -	return (I915_READ_NOTRACE(gpio->reg) & GPIO_DATA_VAL_IN) != 0; +	struct intel_gmbus *bus = data; +	struct drm_i915_private *dev_priv = bus->dev_priv; +	u32 reserved = get_reserved(bus); +	I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK); +	I915_WRITE_NOTRACE(bus->gpio_reg, reserved); +	return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0;  }  static void set_clock(void *data, int state_high)  { -	struct intel_gpio *gpio = data; -	struct drm_i915_private *dev_priv = gpio->dev_priv; -	u32 reserved = get_reserved(gpio); +	struct intel_gmbus *bus = data; +	struct drm_i915_private *dev_priv = bus->dev_priv; +	u32 reserved = get_reserved(bus);  	u32 clock_bits;  	if (state_high) @@ -126,15 +119,15 @@ static void set_clock(void *data, int state_high)  		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |  			GPIO_CLOCK_VAL_MASK; -	I915_WRITE_NOTRACE(gpio->reg, reserved | clock_bits); -	POSTING_READ(gpio->reg); +	I915_WRITE_NOTRACE(bus->gpio_reg, reserved | clock_bits); +	POSTING_READ(bus->gpio_reg);  }  static void set_data(void *data, int state_high)  { -	struct intel_gpio *gpio = data; -	struct drm_i915_private *dev_priv = gpio->dev_priv; -	u32 reserved = get_reserved(gpio); +	struct intel_gmbus *bus = data; +	struct drm_i915_private *dev_priv = bus->dev_priv; +	u32 reserved = get_reserved(bus);  	u32 data_bits;  	if (state_high) @@ -143,13 +136,14 @@ static void set_data(void *data, int state_high)  		data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |  			GPIO_DATA_VAL_MASK; -	I915_WRITE_NOTRACE(gpio->reg, reserved | data_bits); -	POSTING_READ(gpio->reg); +	I915_WRITE_NOTRACE(bus->gpio_reg, reserved | data_bits); +	POSTING_READ(bus->gpio_reg);  } -static struct i2c_adapter * -intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin) +static bool +intel_gpio_setup(struct intel_gmbus *bus, u32 pin)  { +	struct drm_i915_private *dev_priv = bus->dev_priv;  	static const int map_pin_to_reg[] = {  		0,  		GPIOB, @@ -160,65 +154,48 @@ intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin)  		0,  		GPIOF,  	}; -	struct intel_gpio *gpio; +	struct i2c_algo_bit_data *algo;  	if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin]) -		return NULL; +		return false; -	gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL); -	if (gpio == NULL) -		return NULL; +	algo = &bus->bit_algo; -	gpio->reg = map_pin_to_reg[pin]; +	bus->gpio_reg = map_pin_to_reg[pin];  	if (HAS_PCH_SPLIT(dev_priv->dev)) -		gpio->reg += PCH_GPIOA - GPIOA; -	gpio->dev_priv = dev_priv; - -	snprintf(gpio->adapter.name, sizeof(gpio->adapter.name), -		 "i915 GPIO%c", "?BACDE?F"[pin]); -	gpio->adapter.owner = THIS_MODULE; -	gpio->adapter.algo_data	= &gpio->algo; -	gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev; -	gpio->algo.setsda = set_data; -	gpio->algo.setscl = set_clock; -	gpio->algo.getsda = get_data; -	gpio->algo.getscl = get_clock; -	gpio->algo.udelay = I2C_RISEFALL_TIME; -	gpio->algo.timeout = usecs_to_jiffies(2200); -	gpio->algo.data = gpio; +		bus->gpio_reg += PCH_GPIOA - GPIOA; -	if (i2c_bit_add_bus(&gpio->adapter)) -		goto out_free; +	bus->adapter.algo_data = algo; +	algo->setsda = set_data; +	algo->setscl = set_clock; +	algo->getsda = get_data; +	algo->getscl = get_clock; +	algo->udelay = I2C_RISEFALL_TIME; +	algo->timeout = usecs_to_jiffies(2200); +	algo->data = bus; -	return &gpio->adapter; - -out_free: -	kfree(gpio); -	return NULL; +	return true;  }  static int -intel_i2c_quirk_xfer(struct drm_i915_private *dev_priv, -		     struct i2c_adapter *adapter, +intel_i2c_quirk_xfer(struct intel_gmbus *bus,  		     struct i2c_msg *msgs,  		     int num)  { -	struct intel_gpio *gpio = container_of(adapter, -					       struct intel_gpio, -					       adapter); +	struct drm_i915_private *dev_priv = bus->dev_priv;  	int ret;  	intel_i2c_reset(dev_priv->dev);  	intel_i2c_quirk_set(dev_priv, true); -	set_data(gpio, 1); -	set_clock(gpio, 1); +	set_data(bus, 1); +	set_clock(bus, 1);  	udelay(I2C_RISEFALL_TIME); -	ret = adapter->algo->master_xfer(adapter, msgs, num); +	ret = i2c_bit_algo.master_xfer(&bus->adapter, msgs, num); -	set_data(gpio, 1); -	set_clock(gpio, 1); +	set_data(bus, 1); +	set_clock(bus, 1);  	intel_i2c_quirk_set(dev_priv, false);  	return ret; @@ -232,12 +209,15 @@ gmbus_xfer(struct i2c_adapter *adapter,  	struct intel_gmbus *bus = container_of(adapter,  					       struct intel_gmbus,  					       adapter); -	struct drm_i915_private *dev_priv = adapter->algo_data; -	int i, reg_offset; +	struct drm_i915_private *dev_priv = bus->dev_priv; +	int i, reg_offset, ret; + +	mutex_lock(&dev_priv->gmbus_mutex); -	if (bus->force_bit) -		return intel_i2c_quirk_xfer(dev_priv, -					    bus->force_bit, msgs, num); +	if (bus->force_bit) { +		ret = intel_i2c_quirk_xfer(bus, msgs, num); +		goto out; +	}  	reg_offset = HAS_PCH_SPLIT(dev_priv->dev) ? PCH_GMBUS0 - GMBUS0 : 0; @@ -249,7 +229,8 @@ gmbus_xfer(struct i2c_adapter *adapter,  		if (msgs[i].flags & I2C_M_RD) {  			I915_WRITE(GMBUS1 + reg_offset, -				   GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | +				   GMBUS_CYCLE_WAIT | +				   (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |  				   (len << GMBUS_BYTE_COUNT_SHIFT) |  				   (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |  				   GMBUS_SLAVE_READ | GMBUS_SW_RDY); @@ -278,7 +259,8 @@ gmbus_xfer(struct i2c_adapter *adapter,  			I915_WRITE(GMBUS3 + reg_offset, val);  			I915_WRITE(GMBUS1 + reg_offset, -				   (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) | +				   GMBUS_CYCLE_WAIT | +				   (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |  				   (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) |  				   (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |  				   GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); @@ -317,11 +299,15 @@ clear_err:  	I915_WRITE(GMBUS1 + reg_offset, 0);  done: -	/* Mark the GMBUS interface as disabled. We will re-enable it at the -	 * start of the next xfer, till then let it sleep. +	/* Mark the GMBUS interface as disabled after waiting for idle. +	 * We will re-enable it at the start of the next xfer, +	 * till then let it sleep.  	 */ +	if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10)) +		DRM_INFO("GMBUS timed out waiting for idle\n");  	I915_WRITE(GMBUS0 + reg_offset, 0); -	return i; +	ret = i; +	goto out;  timeout:  	DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", @@ -329,23 +315,21 @@ timeout:  	I915_WRITE(GMBUS0 + reg_offset, 0);  	/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ -	bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); -	if (!bus->force_bit) -		return -ENOMEM; - -	return intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num); +	if (!bus->has_gpio) { +		ret = -EIO; +	} else { +		bus->force_bit = true; +		ret = intel_i2c_quirk_xfer(bus, msgs, num); +	} +out: +	mutex_unlock(&dev_priv->gmbus_mutex); +	return ret;  }  static u32 gmbus_func(struct i2c_adapter *adapter)  { -	struct intel_gmbus *bus = container_of(adapter, -					       struct intel_gmbus, -					       adapter); - -	if (bus->force_bit) -		bus->force_bit->algo->functionality(bus->force_bit); - -	return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | +	return i2c_bit_algo.functionality(adapter) & +		(I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |  		/* I2C_FUNC_10BIT_ADDR | */  		I2C_FUNC_SMBUS_READ_BLOCK_DATA |  		I2C_FUNC_SMBUS_BLOCK_PROC_CALL); @@ -375,11 +359,13 @@ int intel_setup_gmbus(struct drm_device *dev)  	struct drm_i915_private *dev_priv = dev->dev_private;  	int ret, i; -	dev_priv->gmbus = kcalloc(sizeof(struct intel_gmbus), GMBUS_NUM_PORTS, +	dev_priv->gmbus = kcalloc(GMBUS_NUM_PORTS, sizeof(struct intel_gmbus),  				  GFP_KERNEL);  	if (dev_priv->gmbus == NULL)  		return -ENOMEM; +	mutex_init(&dev_priv->gmbus_mutex); +  	for (i = 0; i < GMBUS_NUM_PORTS; i++) {  		struct intel_gmbus *bus = &dev_priv->gmbus[i]; @@ -391,7 +377,7 @@ int intel_setup_gmbus(struct drm_device *dev)  			 names[i]);  		bus->adapter.dev.parent = &dev->pdev->dev; -		bus->adapter.algo_data	= dev_priv; +		bus->dev_priv = dev_priv;  		bus->adapter.algo = &gmbus_algorithm;  		ret = i2c_add_adapter(&bus->adapter); @@ -401,8 +387,11 @@ int intel_setup_gmbus(struct drm_device *dev)  		/* By default use a conservative clock rate */  		bus->reg0 = i | GMBUS_RATE_100KHZ; +		bus->has_gpio = intel_gpio_setup(bus, i); +  		/* XXX force bit banging until GMBUS is fully debugged */ -		bus->force_bit = intel_gpio_create(dev_priv, i); +		if (bus->has_gpio && IS_GEN2(dev)) +			bus->force_bit = true;  	}  	intel_i2c_reset(dev_priv->dev); @@ -430,19 +419,8 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)  {  	struct intel_gmbus *bus = to_intel_gmbus(adapter); -	if (force_bit) { -		if (bus->force_bit == NULL) { -			struct drm_i915_private *dev_priv = adapter->algo_data; -			bus->force_bit = intel_gpio_create(dev_priv, -							   bus->reg0 & 0xff); -		} -	} else { -		if (bus->force_bit) { -			i2c_del_adapter(bus->force_bit); -			kfree(bus->force_bit); -			bus->force_bit = NULL; -		} -	} +	if (bus->has_gpio) +		bus->force_bit = force_bit;  }  void intel_teardown_gmbus(struct drm_device *dev) @@ -455,10 +433,6 @@ void intel_teardown_gmbus(struct drm_device *dev)  	for (i = 0; i < GMBUS_NUM_PORTS; i++) {  		struct intel_gmbus *bus = &dev_priv->gmbus[i]; -		if (bus->force_bit) { -			i2c_del_adapter(bus->force_bit); -			kfree(bus->force_bit); -		}  		i2c_del_adapter(&bus->adapter);  	}  |