diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 04:42:39 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 04:42:39 +0300 |
commit | 24867481b8c0a3bc3ab53b634e3cc03680ac3ac6 (patch) | |
tree | 87a0f018c5e0fb61275b5a48977108ad1a33aa8b /drivers/i2c/i2c-core.c | |
parent | 9390bd0d14b4585f7ac2df15ff5f52af182251e1 (diff) | |
parent | a294aba164389a3d2c40dfcf5f3989a3bbfe38a2 (diff) | |
download | linux-24867481b8c0a3bc3ab53b634e3cc03680ac3ac6.tar.xz |
Merge branch 'i2c/for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
"Highlights:
- new drivers for Mediatek I2C, APM X-Gene, Broadcom Settop
- major updates to at91, davinci
- bugfixes to the mux infrastructure when dealing with the new quirk
mechanism
- more users for the bus recovery feature
- further improvements to the slave framework
Plus the usual bunch of smaller driver and core improvements and
fixes.
There is one patch removing old code from an ARM platform. This has
been acked by the sh_mobile maintainer Simon Horman"
* 'i2c/for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (48 commits)
i2c: busses: i2c-bcm2835: limits cdiv to allowed values
i2c: sh_mobile: use proper type for timeout
i2c: sh_mobile: use adapter default for timeout
i2c: rcar: use proper type for timeout
i2c: rcar: use adapter default for timeout
i2c: designware: Make sure the device is suspended before disabling runtime PM
i2c: tegra: apply size limit quirk
i2c: tegra: don't advertise SMBUS_QUICK
i2c: octeon: remove unused signal handling
i2c: davinci: Optimize SCL generation
i2c: mux: pca954x: Use __i2c_transfer because of quirks
i2c: mux: Use __i2c_transfer() instead of calling parent's master_xfer()
i2c: use parent adapter quirks in mux
i2c: bcm2835: clear reserved bits in S-Register
ARM: shmobile: r8a7740: remove I2C errata handling
i2c: sh_mobile: add errata workaround
i2c: at91: fix code checker warnings
i2c: busses: xgene-slimpro: fix incorrect __init declation for probe
i2c: davinci: Avoid sending to own address
i2c: davinci: Refactor i2c_davinci_wait_bus_not_busy()
...
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index fc2ee8213fb6..069a41f116dd 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -257,7 +257,7 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command, struct acpi_connection_info *info = &data->info; struct acpi_resource_i2c_serialbus *sb; struct i2c_adapter *adapter = data->adapter; - struct i2c_client client; + struct i2c_client *client; struct acpi_resource *ares; u32 accessor_type = function >> 16; u8 action = function & ACPI_IO_MASK; @@ -268,6 +268,12 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command, if (ACPI_FAILURE(ret)) return ret; + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) { + ret = AE_NO_MEMORY; + goto err; + } + if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { ret = AE_BAD_PARAMETER; goto err; @@ -279,75 +285,73 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command, goto err; } - memset(&client, 0, sizeof(client)); - client.adapter = adapter; - client.addr = sb->slave_address; - client.flags = 0; + client->adapter = adapter; + client->addr = sb->slave_address; if (sb->access_mode == ACPI_I2C_10BIT_MODE) - client.flags |= I2C_CLIENT_TEN; + client->flags |= I2C_CLIENT_TEN; switch (accessor_type) { case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV: if (action == ACPI_READ) { - status = i2c_smbus_read_byte(&client); + status = i2c_smbus_read_byte(client); if (status >= 0) { gsb->bdata = status; status = 0; } } else { - status = i2c_smbus_write_byte(&client, gsb->bdata); + status = i2c_smbus_write_byte(client, gsb->bdata); } break; case ACPI_GSB_ACCESS_ATTRIB_BYTE: if (action == ACPI_READ) { - status = i2c_smbus_read_byte_data(&client, command); + status = i2c_smbus_read_byte_data(client, command); if (status >= 0) { gsb->bdata = status; status = 0; } } else { - status = i2c_smbus_write_byte_data(&client, command, + status = i2c_smbus_write_byte_data(client, command, gsb->bdata); } break; case ACPI_GSB_ACCESS_ATTRIB_WORD: if (action == ACPI_READ) { - status = i2c_smbus_read_word_data(&client, command); + status = i2c_smbus_read_word_data(client, command); if (status >= 0) { gsb->wdata = status; status = 0; } } else { - status = i2c_smbus_write_word_data(&client, command, + status = i2c_smbus_write_word_data(client, command, gsb->wdata); } break; case ACPI_GSB_ACCESS_ATTRIB_BLOCK: if (action == ACPI_READ) { - status = i2c_smbus_read_block_data(&client, command, + status = i2c_smbus_read_block_data(client, command, gsb->data); if (status >= 0) { gsb->len = status; status = 0; } } else { - status = i2c_smbus_write_block_data(&client, command, + status = i2c_smbus_write_block_data(client, command, gsb->len, gsb->data); } break; case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE: if (action == ACPI_READ) { - status = acpi_gsb_i2c_read_bytes(&client, command, + status = acpi_gsb_i2c_read_bytes(client, command, gsb->data, info->access_length); if (status > 0) status = 0; } else { - status = acpi_gsb_i2c_write_bytes(&client, command, + status = acpi_gsb_i2c_write_bytes(client, command, gsb->data, info->access_length); } break; @@ -361,6 +365,7 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command, gsb->status = status; err: + kfree(client); ACPI_FREE(ares); return ret; } @@ -1276,7 +1281,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, } addr = of_get_property(node, "reg", &len); - if (!addr || (len < sizeof(int))) { + if (!addr || (len < sizeof(*addr))) { dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", node->full_name); return ERR_PTR(-EINVAL); @@ -1677,7 +1682,7 @@ void i2c_del_adapter(struct i2c_adapter *adap) * FIXME: This is old code and should ideally be replaced by an * alternative which results in decoupling the lifetime of the struct * device from the i2c_adapter, like spi or netdev do. Any solution - * should be throughly tested with DEBUG_KOBJECT_RELEASE enabled! + * should be thoroughly tested with DEBUG_KOBJECT_RELEASE enabled! */ init_completion(&adap->dev_released); device_unregister(&adap->dev); @@ -2918,18 +2923,24 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb) { int ret; - if (!client || !slave_cb) + if (!client || !slave_cb) { + WARN(1, "insufficent data\n"); return -EINVAL; + } if (!(client->flags & I2C_CLIENT_TEN)) { /* Enforce stricter address checking */ ret = i2c_check_addr_validity(client->addr); - if (ret) + if (ret) { + dev_err(&client->dev, "%s: invalid address\n", __func__); return ret; + } } - if (!client->adapter->algo->reg_slave) + if (!client->adapter->algo->reg_slave) { + dev_err(&client->dev, "%s: not supported by adapter\n", __func__); return -EOPNOTSUPP; + } client->slave_cb = slave_cb; @@ -2937,8 +2948,10 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb) ret = client->adapter->algo->reg_slave(client); i2c_unlock_adapter(client->adapter); - if (ret) + if (ret) { client->slave_cb = NULL; + dev_err(&client->dev, "%s: adapter returned error %d\n", __func__, ret); + } return ret; } @@ -2948,8 +2961,10 @@ int i2c_slave_unregister(struct i2c_client *client) { int ret; - if (!client->adapter->algo->unreg_slave) + if (!client->adapter->algo->unreg_slave) { + dev_err(&client->dev, "%s: not supported by adapter\n", __func__); return -EOPNOTSUPP; + } i2c_lock_adapter(client->adapter); ret = client->adapter->algo->unreg_slave(client); @@ -2957,6 +2972,8 @@ int i2c_slave_unregister(struct i2c_client *client) if (ret == 0) client->slave_cb = NULL; + else + dev_err(&client->dev, "%s: adapter returned error %d\n", __func__, ret); return ret; } |