summaryrefslogtreecommitdiff
path: root/drivers/i2c/i2c-core.c
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-08-13 15:39:10 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-08-13 15:39:10 -0400
commit0980bd9cd32de2fef7eaa2858345c49d14498625 (patch)
tree41f5f823d0569a81b22037e79c22d823933a63f1 /drivers/i2c/i2c-core.c
parent78821b2c0299ab807d483802f09897728b93bce0 (diff)
parent0d7614f09c1ebdbaa1599a5aba7593f147bf96ee (diff)
Merge commit 'v3.6-rc1' into linux-next
* commit 'v3.6-rc1': (9532 commits) Linux 3.6-rc1 mm: remove node_start_pfn checking in new WARN_ON for now ARM: mmp: add missing irqs.h arm: mvebu: fix typo in .dtsi comment for Armada XP SoCs ARM: PRIMA2: delete redundant codes to restore LATCHED when timer resumes libceph: fix crypto key null deref, memory leak ceph: simplify+fix atomic_open sh: explicitly include sh_dma.h in setup-sh7722.c um: Add arch/x86/um to MAINTAINERS um: pass siginfo to guest process um: fix ubd_file_size for read-only files md/dm-raid: DM_RAID should select MD_RAID10 md/raid1: submit IO from originating thread instead of md thread. raid5: raid5d handle stripe in batch way raid5: make_request use batch stripe release um: pull interrupt_end() into userspace() um: split syscall_trace(), pass pt_regs to it um: switch UPT_SET_RETURN_VALUE and regs_return_value to pt_regs MIPS: Loongson 2: Sort out clock managment. locks: remove unused lm_release_private ...
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r--drivers/i2c/i2c-core.c60
1 files changed, 44 insertions, 16 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index a6ad32bc0a96..2efa56c5ff2c 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1312,6 +1312,37 @@ module_exit(i2c_exit);
*/
/**
+ * __i2c_transfer - unlocked flavor of i2c_transfer
+ * @adap: Handle to I2C bus
+ * @msgs: One or more messages to execute before STOP is issued to
+ * terminate the operation; each message begins with a START.
+ * @num: Number of messages to be executed.
+ *
+ * Returns negative errno, else the number of messages executed.
+ *
+ * Adapter lock must be held when calling this function. No debug logging
+ * takes place. adap->algo->master_xfer existence isn't checked.
+ */
+int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ unsigned long orig_jiffies;
+ int ret, try;
+
+ /* Retry automatically on arbitration loss */
+ orig_jiffies = jiffies;
+ for (ret = 0, try = 0; try <= adap->retries; try++) {
+ ret = adap->algo->master_xfer(adap, msgs, num);
+ if (ret != -EAGAIN)
+ break;
+ if (time_after(jiffies, orig_jiffies + adap->timeout))
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(__i2c_transfer);
+
+/**
* i2c_transfer - execute a single or combined I2C message
* @adap: Handle to I2C bus
* @msgs: One or more messages to execute before STOP is issued to
@@ -1325,8 +1356,7 @@ module_exit(i2c_exit);
*/
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
- unsigned long orig_jiffies;
- int ret, try;
+ int ret;
/* REVISIT the fault reporting model here is weak:
*
@@ -1364,15 +1394,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
i2c_lock_adapter(adap);
}
- /* Retry automatically on arbitration loss */
- orig_jiffies = jiffies;
- for (ret = 0, try = 0; try <= adap->retries; try++) {
- ret = adap->algo->master_xfer(adap, msgs, num);
- if (ret != -EAGAIN)
- break;
- if (time_after(jiffies, orig_jiffies + adap->timeout))
- break;
- }
+ ret = __i2c_transfer(adap, msgs, num);
i2c_unlock_adapter(adap);
return ret;
@@ -2122,7 +2144,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
int try;
s32 res;
- flags &= I2C_M_TEN | I2C_CLIENT_PEC;
+ flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
if (adapter->algo->smbus_xfer) {
i2c_lock_adapter(adapter);
@@ -2140,11 +2162,17 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
break;
}
i2c_unlock_adapter(adapter);
- } else
- res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,
- command, protocol, data);
- return res;
+ if (res != -EOPNOTSUPP || !adapter->algo->master_xfer)
+ return res;
+ /*
+ * Fall back to i2c_smbus_xfer_emulated if the adapter doesn't
+ * implement native support for the SMBus operation.
+ */
+ }
+
+ return i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,
+ command, protocol, data);
}
EXPORT_SYMBOL(i2c_smbus_xfer);