Commit a97d8efd authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:

 - two driver fixes

 - better parameter check for the core

 - Documentation updates

 - part of a tree-wide HAS_DMA cleanup

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: sprd: Fix the i2c count issue
  i2c: sprd: Prevent i2c accesses after suspend is called
  i2c: dev: prevent ZERO_SIZE_PTR deref in i2cdev_ioctl_rdwr()
  Documentation/i2c: adopt kernel commenting style in examples
  Documentation/i2c: sync docs with current state of i2c-tools
  Documentation/i2c: whitespace cleanup
  i2c: Remove depends on HAS_DMA in case of platform dependency
parents 6e041ffc 2a010461
...@@ -23,11 +23,6 @@ First, you need to include these two headers: ...@@ -23,11 +23,6 @@ First, you need to include these two headers:
#include <linux/i2c-dev.h> #include <linux/i2c-dev.h>
#include <i2c/smbus.h> #include <i2c/smbus.h>
(Please note that there are two files named "i2c-dev.h" out there. One is
distributed with the Linux kernel and the other one is included in the
source tree of i2c-tools. They used to be different in content but since 2012
they're identical. You should use "linux/i2c-dev.h").
Now, you have to decide which adapter you want to access. You should Now, you have to decide which adapter you want to access. You should
inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this. inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this.
Adapter numbers are assigned somewhat dynamically, so you can not Adapter numbers are assigned somewhat dynamically, so you can not
...@@ -72,8 +67,10 @@ the device supports them. Both are illustrated below. ...@@ -72,8 +67,10 @@ the device supports them. Both are illustrated below.
/* res contains the read word */ /* res contains the read word */
} }
/* Using I2C Write, equivalent of /*
i2c_smbus_write_word_data(file, reg, 0x6543) */ * Using I2C Write, equivalent of
* i2c_smbus_write_word_data(file, reg, 0x6543)
*/
buf[0] = reg; buf[0] = reg;
buf[1] = 0x43; buf[1] = 0x43;
buf[2] = 0x65; buf[2] = 0x65;
...@@ -140,8 +137,8 @@ ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset) ...@@ -140,8 +137,8 @@ ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)
set in each message, overriding the values set with the above ioctl's. set in each message, overriding the values set with the above ioctl's.
ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args) ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)
Not meant to be called directly; instead, use the access functions If possible, use the provided i2c_smbus_* methods described below instead
below. of issuing direct ioctls.
You can do plain i2c transactions by using read(2) and write(2) calls. You can do plain i2c transactions by using read(2) and write(2) calls.
You do not need to pass the address byte; instead, set it through You do not need to pass the address byte; instead, set it through
...@@ -166,10 +163,9 @@ what happened. The 'write' transactions return 0 on success; the ...@@ -166,10 +163,9 @@ what happened. The 'write' transactions return 0 on success; the
returns the number of values read. The block buffers need not be longer returns the number of values read. The block buffers need not be longer
than 32 bytes. than 32 bytes.
The above functions are all inline functions, that resolve to calls to The above functions are made available by linking against the libi2c library,
the i2c_smbus_access function, that on its turn calls a specific ioctl which is provided by the i2c-tools project. See:
with the data in a specific format. Read the source code if you https://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git/.
want to know what happens behind the screens.
Implementation details Implementation details
......
...@@ -707,7 +707,6 @@ config I2C_MPC ...@@ -707,7 +707,6 @@ config I2C_MPC
config I2C_MT65XX config I2C_MT65XX
tristate "MediaTek I2C adapter" tristate "MediaTek I2C adapter"
depends on ARCH_MEDIATEK || COMPILE_TEST depends on ARCH_MEDIATEK || COMPILE_TEST
depends on HAS_DMA
help help
This selects the MediaTek(R) Integrated Inter Circuit bus driver This selects the MediaTek(R) Integrated Inter Circuit bus driver
for MT65xx and MT81xx. for MT65xx and MT81xx.
...@@ -885,7 +884,6 @@ config I2C_SH7760 ...@@ -885,7 +884,6 @@ config I2C_SH7760
config I2C_SH_MOBILE config I2C_SH_MOBILE
tristate "SuperH Mobile I2C Controller" tristate "SuperH Mobile I2C Controller"
depends on HAS_DMA
depends on ARCH_SHMOBILE || ARCH_RENESAS || COMPILE_TEST depends on ARCH_SHMOBILE || ARCH_RENESAS || COMPILE_TEST
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
...@@ -1098,7 +1096,6 @@ config I2C_XLP9XX ...@@ -1098,7 +1096,6 @@ config I2C_XLP9XX
config I2C_RCAR config I2C_RCAR
tristate "Renesas R-Car I2C Controller" tristate "Renesas R-Car I2C Controller"
depends on HAS_DMA
depends on ARCH_RENESAS || COMPILE_TEST depends on ARCH_RENESAS || COMPILE_TEST
select I2C_SLAVE select I2C_SLAVE
help help
......
...@@ -86,6 +86,7 @@ struct sprd_i2c { ...@@ -86,6 +86,7 @@ struct sprd_i2c {
u32 count; u32 count;
int irq; int irq;
int err; int err;
bool is_suspended;
}; };
static void sprd_i2c_set_count(struct sprd_i2c *i2c_dev, u32 count) static void sprd_i2c_set_count(struct sprd_i2c *i2c_dev, u32 count)
...@@ -283,6 +284,9 @@ static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap, ...@@ -283,6 +284,9 @@ static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap,
struct sprd_i2c *i2c_dev = i2c_adap->algo_data; struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
int im, ret; int im, ret;
if (i2c_dev->is_suspended)
return -EBUSY;
ret = pm_runtime_get_sync(i2c_dev->dev); ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -364,13 +368,12 @@ static irqreturn_t sprd_i2c_isr_thread(int irq, void *dev_id) ...@@ -364,13 +368,12 @@ static irqreturn_t sprd_i2c_isr_thread(int irq, void *dev_id)
struct sprd_i2c *i2c_dev = dev_id; struct sprd_i2c *i2c_dev = dev_id;
struct i2c_msg *msg = i2c_dev->msg; struct i2c_msg *msg = i2c_dev->msg;
bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK); bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK);
u32 i2c_count = readl(i2c_dev->base + I2C_COUNT);
u32 i2c_tran; u32 i2c_tran;
if (msg->flags & I2C_M_RD) if (msg->flags & I2C_M_RD)
i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD; i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD;
else else
i2c_tran = i2c_count; i2c_tran = i2c_dev->count;
/* /*
* If we got one ACK from slave when writing data, and we did not * If we got one ACK from slave when writing data, and we did not
...@@ -408,14 +411,13 @@ static irqreturn_t sprd_i2c_isr(int irq, void *dev_id) ...@@ -408,14 +411,13 @@ static irqreturn_t sprd_i2c_isr(int irq, void *dev_id)
{ {
struct sprd_i2c *i2c_dev = dev_id; struct sprd_i2c *i2c_dev = dev_id;
struct i2c_msg *msg = i2c_dev->msg; struct i2c_msg *msg = i2c_dev->msg;
u32 i2c_count = readl(i2c_dev->base + I2C_COUNT);
bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK); bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK);
u32 i2c_tran; u32 i2c_tran;
if (msg->flags & I2C_M_RD) if (msg->flags & I2C_M_RD)
i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD; i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD;
else else
i2c_tran = i2c_count; i2c_tran = i2c_dev->count;
/* /*
* If we did not get one ACK from slave when writing data, then we * If we did not get one ACK from slave when writing data, then we
...@@ -586,11 +588,23 @@ static int sprd_i2c_remove(struct platform_device *pdev) ...@@ -586,11 +588,23 @@ static int sprd_i2c_remove(struct platform_device *pdev)
static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev) static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev)
{ {
struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
i2c_lock_adapter(&i2c_dev->adap);
i2c_dev->is_suspended = true;
i2c_unlock_adapter(&i2c_dev->adap);
return pm_runtime_force_suspend(pdev); return pm_runtime_force_suspend(pdev);
} }
static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev) static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev)
{ {
struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
i2c_lock_adapter(&i2c_dev->adap);
i2c_dev->is_suspended = false;
i2c_unlock_adapter(&i2c_dev->adap);
return pm_runtime_force_resume(pdev); return pm_runtime_force_resume(pdev);
} }
......
...@@ -280,7 +280,7 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, ...@@ -280,7 +280,7 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
*/ */
if (msgs[i].flags & I2C_M_RECV_LEN) { if (msgs[i].flags & I2C_M_RECV_LEN) {
if (!(msgs[i].flags & I2C_M_RD) || if (!(msgs[i].flags & I2C_M_RD) ||
msgs[i].buf[0] < 1 || msgs[i].len < 1 || msgs[i].buf[0] < 1 ||
msgs[i].len < msgs[i].buf[0] + msgs[i].len < msgs[i].buf[0] +
I2C_SMBUS_BLOCK_MAX) { I2C_SMBUS_BLOCK_MAX) {
res = -EINVAL; res = -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment