Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: i2c-nforce2: Remove redundant error messages on ACPI conflict i2c: Use <linux/io.h> instead of <asm/io.h> i2c-algo-pca: Fix coding style issues i2c-dev: Fix all coding style issues i2c-core: Fix some coding style issues i2c-gpio: Move initialization code to subsys_initcall() i2c-parport: Make template structure const i2c-dev: Remove unnecessary casts at24: Fall back to byte or word reads if needed i2c-stub: Expose the default functionality flags i2c/scx200_acb: Make PCI device ids constant i2c-i801: Fix all checkpatch warnings i2c-i801: All newer devices have all the optional features i2c-i801: Let the user disable selected driver features
This commit is contained in:
+48
-11
@@ -54,7 +54,7 @@
|
||||
struct at24_data {
|
||||
struct at24_platform_data chip;
|
||||
struct memory_accessor macc;
|
||||
bool use_smbus;
|
||||
int use_smbus;
|
||||
|
||||
/*
|
||||
* Lock protects against activities from other Linux tasks,
|
||||
@@ -184,11 +184,19 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
|
||||
if (count > io_limit)
|
||||
count = io_limit;
|
||||
|
||||
if (at24->use_smbus) {
|
||||
switch (at24->use_smbus) {
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
/* Smaller eeproms can work given some SMBus extension calls */
|
||||
if (count > I2C_SMBUS_BLOCK_MAX)
|
||||
count = I2C_SMBUS_BLOCK_MAX;
|
||||
} else {
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
count = 2;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
count = 1;
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* When we have a better choice than SMBus calls, use a
|
||||
* combined I2C message. Write address; then read up to
|
||||
@@ -219,10 +227,27 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
|
||||
timeout = jiffies + msecs_to_jiffies(write_timeout);
|
||||
do {
|
||||
read_time = jiffies;
|
||||
if (at24->use_smbus) {
|
||||
switch (at24->use_smbus) {
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
status = i2c_smbus_read_i2c_block_data(client, offset,
|
||||
count, buf);
|
||||
} else {
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
status = i2c_smbus_read_word_data(client, offset);
|
||||
if (status >= 0) {
|
||||
buf[0] = status & 0xff;
|
||||
buf[1] = status >> 8;
|
||||
status = count;
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
status = i2c_smbus_read_byte_data(client, offset);
|
||||
if (status >= 0) {
|
||||
buf[0] = status;
|
||||
status = count;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = i2c_transfer(client->adapter, msg, 2);
|
||||
if (status == 2)
|
||||
status = count;
|
||||
@@ -436,7 +461,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct at24_platform_data chip;
|
||||
bool writable;
|
||||
bool use_smbus = false;
|
||||
int use_smbus = 0;
|
||||
struct at24_data *at24;
|
||||
int err;
|
||||
unsigned i, num_addresses;
|
||||
@@ -477,12 +502,19 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
err = -EPFNOSUPPORT;
|
||||
goto err_out;
|
||||
}
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
if (i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
|
||||
use_smbus = I2C_SMBUS_I2C_BLOCK_DATA;
|
||||
} else if (i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_WORD_DATA)) {
|
||||
use_smbus = I2C_SMBUS_WORD_DATA;
|
||||
} else if (i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
|
||||
use_smbus = I2C_SMBUS_BYTE_DATA;
|
||||
} else {
|
||||
err = -EPFNOSUPPORT;
|
||||
goto err_out;
|
||||
}
|
||||
use_smbus = true;
|
||||
}
|
||||
|
||||
if (chip.flags & AT24_FLAG_TAKE8ADDR)
|
||||
@@ -568,11 +600,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
dev_info(&client->dev, "%zu byte %s EEPROM %s\n",
|
||||
at24->bin.size, client->name,
|
||||
writable ? "(writable)" : "(read-only)");
|
||||
if (use_smbus == I2C_SMBUS_WORD_DATA ||
|
||||
use_smbus == I2C_SMBUS_BYTE_DATA) {
|
||||
dev_notice(&client->dev, "Falling back to %s reads, "
|
||||
"performance will suffer\n", use_smbus ==
|
||||
I2C_SMBUS_WORD_DATA ? "word" : "byte");
|
||||
}
|
||||
dev_dbg(&client->dev,
|
||||
"page_size %d, num_addresses %d, write_max %d%s\n",
|
||||
"page_size %d, num_addresses %d, write_max %d, use_smbus %d\n",
|
||||
chip.page_size, num_addresses,
|
||||
at24->write_max,
|
||||
use_smbus ? ", use_smbus" : "");
|
||||
at24->write_max, use_smbus);
|
||||
|
||||
/* export data to kernel code */
|
||||
if (chip.setup)
|
||||
|
||||
Reference in New Issue
Block a user