>From ef5a12fddf73716159f17d61391ad5b0e022bc38 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexdeuc...@gmail.com> Date: Fri, 5 Feb 2010 16:48:23 -0500 Subject: [PATCH] drm/radeon/kms: hw i2c fixes
- handle bus probing correctly - use meaningful error numbers - abort if transaction fails This gets i2cdetect working as well with hw i2c as sw. Signed-off-by: Alex Deucher <alexdeuc...@gmail.com> --- drivers/gpu/drm/radeon/radeon_i2c.c | 95 ++++++++++++++++++++++++++++++----- 1 files changed, 82 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 14a68b4..825c921 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -216,11 +216,43 @@ static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap, break; default: DRM_ERROR("gpio not supported with hw i2c\n"); - ret = -1; + ret = -EINVAL; goto done; } } + /* check for bus probe */ + p = &msgs[0]; + if ((num == 1) && (p->len == 0)) { + WREG32(i2c_cntl_0, (RADEON_I2C_DONE | + RADEON_I2C_NACK | + RADEON_I2C_HALT | + RADEON_I2C_SOFT_RST)); + WREG32(i2c_data, (p->addr << 1) & 0xff); + WREG32(i2c_data, 0); + WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) | + (1 << RADEON_I2C_ADDR_COUNT_SHIFT) | + RADEON_I2C_EN | + (48 << RADEON_I2C_TIME_LIMIT_SHIFT))); + WREG32(i2c_cntl_0, reg); + for (k = 0; k < 32; k++) { + udelay(10); + tmp = RREG32(i2c_cntl_0); + if (tmp & RADEON_I2C_GO) + continue; + tmp = RREG32(i2c_cntl_0); + if (tmp & RADEON_I2C_DONE) + break; + else { + DRM_DEBUG("i2c write error 0x%08x\n", tmp); + WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT); + ret = -EIO; + goto done; + } + } + goto done; + } + for (i = 0; i < num; i++) { p = &msgs[i]; for (j = 0; j < p->len; j++) { @@ -245,7 +277,8 @@ static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap, break; else { DRM_DEBUG("i2c read error 0x%08x\n", tmp); - ret = -1; + WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT); + ret = -EIO; goto done; } } @@ -272,7 +305,8 @@ static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap, break; else { DRM_DEBUG("i2c write error 0x%08x\n", tmp); - ret = -1; + WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT); + ret = -EIO; goto done; } } @@ -361,11 +395,10 @@ static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap, } if (i == 50) { DRM_ERROR("failed to get i2c bus\n"); - ret = -1; + ret = -EBUSY; goto done; } - if (rdev->family == CHIP_R520) prescale = (127 << 8) + ((rdev->clock.default_sclk * 10) / (4 * 127 * i2c_clock)); else @@ -384,7 +417,44 @@ static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap, break; default: DRM_ERROR("gpio not supported with hw i2c\n"); - ret = -1; + ret = -EINVAL; + goto done; + } + + /* check for bus probe */ + p = &msgs[0]; + if ((num == 1) && (p->len == 0)) { + WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE | + AVIVO_DC_I2C_NACK | + AVIVO_DC_I2C_HALT)); + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET); + udelay(1); + WREG32(AVIVO_DC_I2C_RESET, 0); + + WREG32(AVIVO_DC_I2C_DATA, (p->addr << 1) & 0xff); + WREG32(AVIVO_DC_I2C_DATA, 0); + + WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48)); + WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) | + AVIVO_DC_I2C_DATA_COUNT(1) | + (prescale << 16))); + WREG32(AVIVO_DC_I2C_CONTROL1, reg); + WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO); + for (j = 0; j < 200; j++) { + udelay(50); + tmp = RREG32(AVIVO_DC_I2C_STATUS1); + if (tmp & AVIVO_DC_I2C_GO) + continue; + tmp = RREG32(AVIVO_DC_I2C_STATUS1); + if (tmp & AVIVO_DC_I2C_DONE) + break; + else { + DRM_DEBUG("i2c write error 0x%08x\n", tmp); + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT); + ret = -EIO; + goto done; + } + } goto done; } @@ -422,7 +492,8 @@ static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap, break; else { DRM_DEBUG("i2c read error 0x%08x\n", tmp); - ret = -1; + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT); + ret = -EIO; goto done; } } @@ -464,7 +535,8 @@ static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap, break; else { DRM_DEBUG("i2c write error 0x%08x\n", tmp); - ret = -1; + WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT); + ret = -EIO; goto done; } } @@ -499,10 +571,7 @@ static int radeon_sw_i2c_xfer(struct i2c_adapter *i2c_adap, int ret; radeon_i2c_do_lock(i2c, 1); - if (i2c_transfer(&i2c->algo.radeon.bit_adapter, msgs, num) == num) - ret = num; - else - ret = -1; + ret = i2c_transfer(&i2c->algo.radeon.bit_adapter, msgs, num); radeon_i2c_do_lock(i2c, 0); return ret; @@ -580,7 +649,7 @@ static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap, break; default: DRM_ERROR("i2c: unhandled radeon chip\n"); - ret = -1; + ret = -EIO; break; } -- 1.5.6.3
0001-drm-radeon-kms-hw-i2c-fixes.patch
Description: application/mbox
------------------------------------------------------------------------------ The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away. http://p.sf.net/sfu/theplanet-com
-- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel