aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2005-09-22 15:58:41 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 17:02:08 -0400
commitf118301416953d677de738100c33eb8cfb7adecb (patch)
tree145997f9c2159d1657dcaca8c56ee93341d8b5f9
parent5f49ef8e8cefe0a95948b4270db28507c1c287d4 (diff)
[PATCH] i2c-viapro: Implement I2C Block transactions
Implement the I2C block transactions on VIA chips which support them: VT82C686B, VT8233, VT8233A, VT8235 and VT8237R. This speeds up EEPROM accesses by a factor 10 or so. I would like to thank Antonino A. Daplas, Hinko Kocevar, Salah Coronya and Andreas Henriksson for their help in testing this new feature. Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Documentation/i2c/busses/i2c-viapro | 7 +++++- drivers/i2c/busses/i2c-viapro.c | 39 +++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-)
-rw-r--r--Documentation/i2c/busses/i2c-viapro7
-rw-r--r--drivers/i2c/busses/i2c-viapro.c39
2 files changed, 42 insertions, 4 deletions
diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro
index ef0f1e94e726..387cbd4015fc 100644
--- a/Documentation/i2c/busses/i2c-viapro
+++ b/Documentation/i2c/busses/i2c-viapro
@@ -14,7 +14,8 @@ Authors:
14 Frodo Looijaard <frodol@dds.nl>, 14 Frodo Looijaard <frodol@dds.nl>,
15 Philip Edelbrock <phil@netroedge.com>, 15 Philip Edelbrock <phil@netroedge.com>,
16 Kyösti Mälkki <kmalkki@cc.hut.fi>, 16 Kyösti Mälkki <kmalkki@cc.hut.fi>,
17 Mark D. Studebaker <mdsxyz123@yahoo.com> 17 Mark D. Studebaker <mdsxyz123@yahoo.com>,
18 Jean Delvare <khali@linux-fr.org>
18 19
19Module Parameters 20Module Parameters
20----------------- 21-----------------
@@ -43,3 +44,7 @@ Your lspci -n listing must show one of these :
43 44
44If none of these show up, you should look in the BIOS for settings like 45If none of these show up, you should look in the BIOS for settings like
45enable ACPI / SMBus or even USB. 46enable ACPI / SMBus or even USB.
47
48Except for the oldest chips (VT82C596A/B, VT82C686A and most probably
49VT8231), this driver supports I2C block transactions. Such transactions
50are mainly useful to read from and write to EEPROMs.
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 262755e1ae02..b420e752b1dc 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -4,6 +4,7 @@
4 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, 4 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
5 Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>, 5 Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
6 Mark D. Studebaker <mdsxyz123@yahoo.com> 6 Mark D. Studebaker <mdsxyz123@yahoo.com>
7 Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
7 8
8 This program is free software; you can redistribute it and/or modify 9 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by 10 it under the terms of the GNU General Public License as published by
@@ -88,6 +89,7 @@ static unsigned short smb_cf_hstcfg = 0xD2;
88#define VT596_BYTE_DATA 0x08 89#define VT596_BYTE_DATA 0x08
89#define VT596_WORD_DATA 0x0C 90#define VT596_WORD_DATA 0x0C
90#define VT596_BLOCK_DATA 0x14 91#define VT596_BLOCK_DATA 0x14
92#define VT596_I2C_BLOCK_DATA 0x34
91 93
92 94
93/* If force is set to anything different from 0, we forcibly enable the 95/* If force is set to anything different from 0, we forcibly enable the
@@ -107,6 +109,9 @@ MODULE_PARM_DESC(force_addr,
107 109
108static struct i2c_adapter vt596_adapter; 110static struct i2c_adapter vt596_adapter;
109 111
112#define FEATURE_I2CBLOCK (1<<0)
113static unsigned int vt596_features;
114
110/* Another internally used function */ 115/* Another internally used function */
111static int vt596_transaction(void) 116static int vt596_transaction(void)
112{ 117{
@@ -225,6 +230,12 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
225 } 230 }
226 size = VT596_WORD_DATA; 231 size = VT596_WORD_DATA;
227 break; 232 break;
233 case I2C_SMBUS_I2C_BLOCK_DATA:
234 if (!(vt596_features & FEATURE_I2CBLOCK))
235 return -1;
236 if (read_write == I2C_SMBUS_READ)
237 outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
238 /* Fall through */
228 case I2C_SMBUS_BLOCK_DATA: 239 case I2C_SMBUS_BLOCK_DATA:
229 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), 240 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
230 SMBHSTADD); 241 SMBHSTADD);
@@ -240,11 +251,12 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
240 for (i = 1; i <= len; i++) 251 for (i = 1; i <= len; i++)
241 outb_p(data->block[i], SMBBLKDAT); 252 outb_p(data->block[i], SMBBLKDAT);
242 } 253 }
243 size = VT596_BLOCK_DATA; 254 size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ?
255 VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA;
244 break; 256 break;
245 } 257 }
246 258
247 outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); 259 outb_p((size & 0x3C) + (ENABLE_INT9 & 1), SMBHSTCNT);
248 260
249 if (vt596_transaction()) /* Error in transaction */ 261 if (vt596_transaction()) /* Error in transaction */
250 return -1; 262 return -1;
@@ -266,6 +278,7 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
266 case VT596_WORD_DATA: 278 case VT596_WORD_DATA:
267 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); 279 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
268 break; 280 break;
281 case VT596_I2C_BLOCK_DATA:
269 case VT596_BLOCK_DATA: 282 case VT596_BLOCK_DATA:
270 data->block[0] = inb_p(SMBHSTDAT0); 283 data->block[0] = inb_p(SMBHSTDAT0);
271 if (data->block[0] > I2C_SMBUS_BLOCK_MAX) 284 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
@@ -280,9 +293,13 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
280 293
281static u32 vt596_func(struct i2c_adapter *adapter) 294static u32 vt596_func(struct i2c_adapter *adapter)
282{ 295{
283 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 296 u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
284 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 297 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
285 I2C_FUNC_SMBUS_BLOCK_DATA; 298 I2C_FUNC_SMBUS_BLOCK_DATA;
299
300 if (vt596_features & FEATURE_I2CBLOCK)
301 func |= I2C_FUNC_SMBUS_I2C_BLOCK;
302 return func;
286} 303}
287 304
288static struct i2c_algorithm smbus_algorithm = { 305static struct i2c_algorithm smbus_algorithm = {
@@ -379,6 +396,22 @@ found:
379 dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp); 396 dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
380 dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba); 397 dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
381 398
399 switch (pdev->device) {
400 case PCI_DEVICE_ID_VIA_8237:
401 case PCI_DEVICE_ID_VIA_8235:
402 case PCI_DEVICE_ID_VIA_8233A:
403 case PCI_DEVICE_ID_VIA_8233_0:
404 vt596_features |= FEATURE_I2CBLOCK;
405 break;
406 case PCI_DEVICE_ID_VIA_82C686_4:
407 /* The VT82C686B (rev 0x40) does support I2C block
408 transactions, but the VT82C686A (rev 0x30) doesn't */
409 if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
410 && temp >= 0x40)
411 vt596_features |= FEATURE_I2CBLOCK;
412 break;
413 }
414
382 vt596_adapter.dev.parent = &pdev->dev; 415 vt596_adapter.dev.parent = &pdev->dev;
383 snprintf(vt596_adapter.name, I2C_NAME_SIZE, 416 snprintf(vt596_adapter.name, I2C_NAME_SIZE,
384 "SMBus Via Pro adapter at %04x", vt596_smba); 417 "SMBus Via Pro adapter at %04x", vt596_smba);