Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvar...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 May 2010 17:49:43 +0000 (10:49 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 May 2010 17:49:43 +0000 (10:49 -0700)
* '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

1  2 
drivers/misc/eeprom/at24.c

@@@ -54,7 -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 +184,19 @@@ static ssize_t at24_eeprom_read(struct 
        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
        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;
@@@ -274,8 -299,7 +299,8 @@@ static ssize_t at24_read(struct at24_da
        return retval;
  }
  
 -static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr,
 +static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj,
 +              struct bin_attribute *attr,
                char *buf, loff_t off, size_t count)
  {
        struct at24_data *at24;
@@@ -396,8 -420,7 +421,8 @@@ static ssize_t at24_write(struct at24_d
        return retval;
  }
  
 -static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr,
 +static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj,
 +              struct bin_attribute *attr,
                char *buf, loff_t off, size_t count)
  {
        struct at24_data *at24;
@@@ -436,7 -459,7 +461,7 @@@ static int at24_probe(struct i2c_clien
  {
        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;
                        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)
        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)