Skip to content

Commit

Permalink
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "Bugfixes for I2C. Mostly core this time which is a bit unusual but
  nothing really scary in there"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: piix4: Avoid race conditions with IMC
  i2c: fix spelling mistake: "insufficent" -> "insufficient"
  i2c: print correct device invalid address
  i2c: do not enable fall back to Host Notify by default
  i2c: fix kernel memory disclosure in dev interface
  • Loading branch information
Linus Torvalds committed Jan 15, 2017
2 parents 83346fb + 701dc20 commit aa2797b
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 12 deletions.
8 changes: 8 additions & 0 deletions Documentation/devicetree/bindings/i2c/i2c.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ wants to support one of the below features, it should adapt the bindings below.
"irq" and "wakeup" names are recognized by I2C core, other names are
left to individual drivers.

- host-notify
device uses SMBus host notify protocol instead of interrupt line.

- multi-master
states that there is another master active on this bus. The OS can use
this information to adapt power management to keep the arbitration awake
Expand All @@ -81,6 +84,11 @@ Binding may contain optional "interrupts" property, describing interrupts
used by the device. I2C core will assign "irq" interrupt (or the very first
interrupt if not using interrupt names) as primary interrupt for the slave.

Alternatively, devices supporting SMbus Host Notify, and connected to
adapters that support this feature, may use "host-notify" property. I2C
core will create a virtual interrupt for Host Notify and assign it as
primary interrupt for the slave.

Also, if device is marked as a wakeup source, I2C core will set up "wakeup"
interrupt for the device. If "wakeup" interrupt name is not present in the
binding, then primary interrupt will be used as wakeup interrupt.
22 changes: 22 additions & 0 deletions drivers/i2c/busses/i2c-piix4.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,10 +585,29 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
u8 command, int size, union i2c_smbus_data *data)
{
struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
unsigned short piix4_smba = adapdata->smba;
int retries = MAX_TIMEOUT;
int smbslvcnt;
u8 smba_en_lo;
u8 port;
int retval;

/* Request the SMBUS semaphore, avoid conflicts with the IMC */
smbslvcnt = inb_p(SMBSLVCNT);
do {
outb_p(smbslvcnt | 0x10, SMBSLVCNT);

/* Check the semaphore status */
smbslvcnt = inb_p(SMBSLVCNT);
if (smbslvcnt & 0x10)
break;

usleep_range(1000, 2000);
} while (--retries);
/* SMBus is still owned by the IMC, we give up */
if (!retries)
return -EBUSY;

mutex_lock(&piix4_mutex_sb800);

outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
Expand All @@ -606,6 +625,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,

mutex_unlock(&piix4_mutex_sb800);

/* Release the semaphore */
outb_p(smbslvcnt | 0x20, SMBSLVCNT);

return retval;
}

Expand Down
21 changes: 10 additions & 11 deletions drivers/i2c/i2c-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,10 @@ static int i2c_device_probe(struct device *dev)
if (!client->irq) {
int irq = -ENOENT;

if (dev->of_node) {
if (client->flags & I2C_CLIENT_HOST_NOTIFY) {
dev_dbg(dev, "Using Host Notify IRQ\n");
irq = i2c_smbus_host_notify_to_irq(client);
} else if (dev->of_node) {
irq = of_irq_get_byname(dev->of_node, "irq");
if (irq == -EINVAL || irq == -ENODATA)
irq = of_irq_get(dev->of_node, 0);
Expand All @@ -940,14 +943,7 @@ static int i2c_device_probe(struct device *dev)
}
if (irq == -EPROBE_DEFER)
return irq;
/*
* ACPI and OF did not find any useful IRQ, try to see
* if Host Notify can be used.
*/
if (irq < 0) {
dev_dbg(dev, "Using Host Notify IRQ\n");
irq = i2c_smbus_host_notify_to_irq(client);
}

if (irq < 0)
irq = 0;

Expand Down Expand Up @@ -1708,14 +1704,17 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,

if (i2c_check_addr_validity(addr, info.flags)) {
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
info.addr, node->full_name);
addr, node->full_name);
return ERR_PTR(-EINVAL);
}

info.addr = addr;
info.of_node = of_node_get(node);
info.archdata = &dev_ad;

if (of_property_read_bool(node, "host-notify"))
info.flags |= I2C_CLIENT_HOST_NOTIFY;

if (of_get_property(node, "wakeup-source", NULL))
info.flags |= I2C_CLIENT_WAKE;

Expand Down Expand Up @@ -3633,7 +3632,7 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
int ret;

if (!client || !slave_cb) {
WARN(1, "insufficent data\n");
WARN(1, "insufficient data\n");
return -EINVAL;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/i2c/i2c-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
unsigned long arg)
{
struct i2c_smbus_ioctl_data data_arg;
union i2c_smbus_data temp;
union i2c_smbus_data temp = {};
int datasize, res;

if (copy_from_user(&data_arg,
Expand Down
1 change: 1 addition & 0 deletions include/linux/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,7 @@ i2c_unlock_adapter(struct i2c_adapter *adapter)
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
/* Must equal I2C_M_TEN below */
#define I2C_CLIENT_SLAVE 0x20 /* we are the slave */
#define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */
#define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */
#define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */
/* Must match I2C_M_STOP|IGNORE_NAK */
Expand Down

0 comments on commit aa2797b

Please sign in to comment.