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