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
This commit is contained in:
commit
a97d8efd9d
|
@ -9,8 +9,8 @@ i2c adapters present on your system at a given time. i2cdetect is part of
|
|||
the i2c-tools package.
|
||||
|
||||
I2C device files are character device files with major device number 89
|
||||
and a minor device number corresponding to the number assigned as
|
||||
explained above. They should be called "i2c-%d" (i2c-0, i2c-1, ...,
|
||||
and a minor device number corresponding to the number assigned as
|
||||
explained above. They should be called "i2c-%d" (i2c-0, i2c-1, ...,
|
||||
i2c-10, ...). All 256 minor device numbers are reserved for i2c.
|
||||
|
||||
|
||||
|
@ -23,11 +23,6 @@ First, you need to include these two headers:
|
|||
#include <linux/i2c-dev.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
|
||||
inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this.
|
||||
Adapter numbers are assigned somewhat dynamically, so you can not
|
||||
|
@ -38,7 +33,7 @@ Next thing, open the device file, as follows:
|
|||
int file;
|
||||
int adapter_nr = 2; /* probably dynamically determined */
|
||||
char filename[20];
|
||||
|
||||
|
||||
snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
|
||||
file = open(filename, O_RDWR);
|
||||
if (file < 0) {
|
||||
|
@ -72,8 +67,10 @@ the device supports them. Both are illustrated below.
|
|||
/* 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[1] = 0x43;
|
||||
buf[2] = 0x65;
|
||||
|
@ -140,14 +137,14 @@ ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)
|
|||
set in each message, overriding the values set with the above ioctl's.
|
||||
|
||||
ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)
|
||||
Not meant to be called directly; instead, use the access functions
|
||||
below.
|
||||
If possible, use the provided i2c_smbus_* methods described below instead
|
||||
of issuing direct ioctls.
|
||||
|
||||
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
|
||||
ioctl I2C_SLAVE before you try to access the device.
|
||||
|
||||
You can do SMBus level transactions (see documentation file smbus-protocol
|
||||
You can do SMBus level transactions (see documentation file smbus-protocol
|
||||
for details) through the following functions:
|
||||
__s32 i2c_smbus_write_quick(int file, __u8 value);
|
||||
__s32 i2c_smbus_read_byte(int file);
|
||||
|
@ -158,7 +155,7 @@ for details) through the following functions:
|
|||
__s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value);
|
||||
__s32 i2c_smbus_process_call(int file, __u8 command, __u16 value);
|
||||
__s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
|
||||
__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
|
||||
__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
|
||||
__u8 *values);
|
||||
All these transactions return -1 on failure; you can read errno to see
|
||||
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
|
||||
than 32 bytes.
|
||||
|
||||
The above functions are all inline functions, that resolve to calls to
|
||||
the i2c_smbus_access function, that on its turn calls a specific ioctl
|
||||
with the data in a specific format. Read the source code if you
|
||||
want to know what happens behind the screens.
|
||||
The above functions are made available by linking against the libi2c library,
|
||||
which is provided by the i2c-tools project. See:
|
||||
https://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git/.
|
||||
|
||||
|
||||
Implementation details
|
||||
|
|
|
@ -707,7 +707,6 @@ config I2C_MPC
|
|||
config I2C_MT65XX
|
||||
tristate "MediaTek I2C adapter"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
depends on HAS_DMA
|
||||
help
|
||||
This selects the MediaTek(R) Integrated Inter Circuit bus driver
|
||||
for MT65xx and MT81xx.
|
||||
|
@ -885,7 +884,6 @@ config I2C_SH7760
|
|||
|
||||
config I2C_SH_MOBILE
|
||||
tristate "SuperH Mobile I2C Controller"
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_SHMOBILE || ARCH_RENESAS || COMPILE_TEST
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
|
@ -1098,7 +1096,6 @@ config I2C_XLP9XX
|
|||
|
||||
config I2C_RCAR
|
||||
tristate "Renesas R-Car I2C Controller"
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
select I2C_SLAVE
|
||||
help
|
||||
|
|
|
@ -86,6 +86,7 @@ struct sprd_i2c {
|
|||
u32 count;
|
||||
int irq;
|
||||
int err;
|
||||
bool is_suspended;
|
||||
};
|
||||
|
||||
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,
|
|||
struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
|
||||
int im, ret;
|
||||
|
||||
if (i2c_dev->is_suspended)
|
||||
return -EBUSY;
|
||||
|
||||
ret = pm_runtime_get_sync(i2c_dev->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -364,13 +368,12 @@ static irqreturn_t sprd_i2c_isr_thread(int irq, void *dev_id)
|
|||
struct sprd_i2c *i2c_dev = dev_id;
|
||||
struct i2c_msg *msg = i2c_dev->msg;
|
||||
bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK);
|
||||
u32 i2c_count = readl(i2c_dev->base + I2C_COUNT);
|
||||
u32 i2c_tran;
|
||||
|
||||
if (msg->flags & I2C_M_RD)
|
||||
i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD;
|
||||
else
|
||||
i2c_tran = i2c_count;
|
||||
i2c_tran = i2c_dev->count;
|
||||
|
||||
/*
|
||||
* 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)
|
|||
{
|
||||
struct sprd_i2c *i2c_dev = dev_id;
|
||||
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);
|
||||
u32 i2c_tran;
|
||||
|
||||
if (msg->flags & I2C_M_RD)
|
||||
i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD;
|
||||
else
|
||||
i2c_tran = i2c_count;
|
||||
i2c_tran = i2c_dev->count;
|
||||
|
||||
/*
|
||||
* 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)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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_RD) ||
|
||||
msgs[i].buf[0] < 1 ||
|
||||
msgs[i].len < 1 || msgs[i].buf[0] < 1 ||
|
||||
msgs[i].len < msgs[i].buf[0] +
|
||||
I2C_SMBUS_BLOCK_MAX) {
|
||||
res = -EINVAL;
|
||||
|
|
Loading…
Reference in New Issue