Commit aa2797b3 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:
 "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
parents 83346fbc 701dc207
...@@ -62,6 +62,9 @@ wants to support one of the below features, it should adapt the bindings below. ...@@ -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 "irq" and "wakeup" names are recognized by I2C core, other names are
left to individual drivers. left to individual drivers.
- host-notify
device uses SMBus host notify protocol instead of interrupt line.
- multi-master - multi-master
states that there is another master active on this bus. The OS can use 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 this information to adapt power management to keep the arbitration awake
...@@ -81,6 +84,11 @@ Binding may contain optional "interrupts" property, describing interrupts ...@@ -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 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. 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" 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 interrupt for the device. If "wakeup" interrupt name is not present in the
binding, then primary interrupt will be used as wakeup interrupt. binding, then primary interrupt will be used as wakeup interrupt.
...@@ -585,10 +585,29 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -585,10 +585,29 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
u8 command, int size, union i2c_smbus_data *data) u8 command, int size, union i2c_smbus_data *data)
{ {
struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap); 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 smba_en_lo;
u8 port; u8 port;
int retval; 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); mutex_lock(&piix4_mutex_sb800);
outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX); outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
...@@ -606,6 +625,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -606,6 +625,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
mutex_unlock(&piix4_mutex_sb800); mutex_unlock(&piix4_mutex_sb800);
/* Release the semaphore */
outb_p(smbslvcnt | 0x20, SMBSLVCNT);
return retval; return retval;
} }
......
...@@ -931,7 +931,10 @@ static int i2c_device_probe(struct device *dev) ...@@ -931,7 +931,10 @@ static int i2c_device_probe(struct device *dev)
if (!client->irq) { if (!client->irq) {
int irq = -ENOENT; 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"); irq = of_irq_get_byname(dev->of_node, "irq");
if (irq == -EINVAL || irq == -ENODATA) if (irq == -EINVAL || irq == -ENODATA)
irq = of_irq_get(dev->of_node, 0); irq = of_irq_get(dev->of_node, 0);
...@@ -940,14 +943,7 @@ static int i2c_device_probe(struct device *dev) ...@@ -940,14 +943,7 @@ static int i2c_device_probe(struct device *dev)
} }
if (irq == -EPROBE_DEFER) if (irq == -EPROBE_DEFER)
return irq; 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) if (irq < 0)
irq = 0; irq = 0;
...@@ -1708,7 +1704,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, ...@@ -1708,7 +1704,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
if (i2c_check_addr_validity(addr, info.flags)) { if (i2c_check_addr_validity(addr, info.flags)) {
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", 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); return ERR_PTR(-EINVAL);
} }
...@@ -1716,6 +1712,9 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, ...@@ -1716,6 +1712,9 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
info.of_node = of_node_get(node); info.of_node = of_node_get(node);
info.archdata = &dev_ad; 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)) if (of_get_property(node, "wakeup-source", NULL))
info.flags |= I2C_CLIENT_WAKE; info.flags |= I2C_CLIENT_WAKE;
...@@ -3633,7 +3632,7 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb) ...@@ -3633,7 +3632,7 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
int ret; int ret;
if (!client || !slave_cb) { if (!client || !slave_cb) {
WARN(1, "insufficent data\n"); WARN(1, "insufficient data\n");
return -EINVAL; return -EINVAL;
} }
......
...@@ -331,7 +331,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, ...@@ -331,7 +331,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
unsigned long arg) unsigned long arg)
{ {
struct i2c_smbus_ioctl_data data_arg; struct i2c_smbus_ioctl_data data_arg;
union i2c_smbus_data temp; union i2c_smbus_data temp = {};
int datasize, res; int datasize, res;
if (copy_from_user(&data_arg, if (copy_from_user(&data_arg,
......
...@@ -665,6 +665,7 @@ i2c_unlock_adapter(struct i2c_adapter *adapter) ...@@ -665,6 +665,7 @@ i2c_unlock_adapter(struct i2c_adapter *adapter)
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */ #define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
/* Must equal I2C_M_TEN below */ /* Must equal I2C_M_TEN below */
#define I2C_CLIENT_SLAVE 0x20 /* we are the slave */ #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_WAKE 0x80 /* for board_info; true iff can wake */
#define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */ #define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */
/* Must match I2C_M_STOP|IGNORE_NAK */ /* Must match I2C_M_STOP|IGNORE_NAK */
......
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