diff options
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 331 |
1 files changed, 229 insertions, 102 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e0f833cca3f..6649176de94 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -20,7 +20,9 @@ /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and - Jean Delvare <khali@linux-fr.org> */ + Jean Delvare <khali@linux-fr.org> + Mux support by Rodolfo Giometti <giometti@enneenne.com> and + Michael Lawnick <michael.lawnick.ext@nsn.com> */ #include <linux/module.h> #include <linux/kernel.h> @@ -30,6 +32,8 @@ #include <linux/init.h> #include <linux/idr.h> #include <linux/mutex.h> +#include <linux/of_i2c.h> +#include <linux/of_device.h> #include <linux/completion.h> #include <linux/hardirq.h> #include <linux/irqflags.h> @@ -47,7 +51,6 @@ static DEFINE_MUTEX(core_lock); static DEFINE_IDR(i2c_adapter_idr); static struct device_type i2c_client_type; -static int i2c_check_addr(struct i2c_adapter *adapter, int addr); static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); /* ------------------------------------------------------------------------- */ @@ -71,6 +74,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) if (!client) return 0; + /* Attempt an OF style match */ + if (of_driver_match_device(dev, drv)) + return 1; + driver = to_i2c_driver(drv); /* match on an id table if there is one */ if (driver->id_table) @@ -371,6 +378,135 @@ struct i2c_client *i2c_verify_client(struct device *dev) EXPORT_SYMBOL(i2c_verify_client); +/* This is a permissive address validity check, I2C address map constraints + * are purposedly not enforced, except for the general call address. */ +static int i2c_check_client_addr_validity(const struct i2c_client *client) +{ + if (client->flags & I2C_CLIENT_TEN) { + /* 10-bit address, all values are valid */ + if (client->addr > 0x3ff) + return -EINVAL; + } else { + /* 7-bit address, reject the general call address */ + if (client->addr == 0x00 || client->addr > 0x7f) + return -EINVAL; + } + return 0; +} + +/* And this is a strict address validity check, used when probing. If a + * device uses a reserved address, then it shouldn't be probed. 7-bit + * addressing is assumed, 10-bit address devices are rare and should be + * explicitly enumerated. */ +static int i2c_check_addr_validity(unsigned short addr) +{ + /* + * Reserved addresses per I2C specification: + * 0x00 General call address / START byte + * 0x01 CBUS address + * 0x02 Reserved for different bus format + * 0x03 Reserved for future purposes + * 0x04-0x07 Hs-mode master code + * 0x78-0x7b 10-bit slave addressing + * 0x7c-0x7f Reserved for future purposes + */ + if (addr < 0x08 || addr > 0x77) + return -EINVAL; + return 0; +} + +static int __i2c_check_addr_busy(struct device *dev, void *addrp) +{ + struct i2c_client *client = i2c_verify_client(dev); + int addr = *(int *)addrp; + + if (client && client->addr == addr) + return -EBUSY; + return 0; +} + +/* walk up mux tree */ +static int i2c_check_mux_parents(struct i2c_adapter *adapter, int addr) +{ + int result; + + result = device_for_each_child(&adapter->dev, &addr, + __i2c_check_addr_busy); + + if (!result && i2c_parent_is_i2c_adapter(adapter)) + result = i2c_check_mux_parents( + to_i2c_adapter(adapter->dev.parent), addr); + + return result; +} + +/* recurse down mux tree */ +static int i2c_check_mux_children(struct device *dev, void *addrp) +{ + int result; + + if (dev->type == &i2c_adapter_type) + result = device_for_each_child(dev, addrp, + i2c_check_mux_children); + else + result = __i2c_check_addr_busy(dev, addrp); + + return result; +} + +static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) +{ + int result = 0; + + if (i2c_parent_is_i2c_adapter(adapter)) + result = i2c_check_mux_parents( + to_i2c_adapter(adapter->dev.parent), addr); + + if (!result) + result = device_for_each_child(&adapter->dev, &addr, + i2c_check_mux_children); + + return result; +} + +/** + * i2c_lock_adapter - Get exclusive access to an I2C bus segment + * @adapter: Target I2C bus segment + */ +void i2c_lock_adapter(struct i2c_adapter *adapter) +{ + if (i2c_parent_is_i2c_adapter(adapter)) + i2c_lock_adapter(to_i2c_adapter(adapter->dev.parent)); + else + rt_mutex_lock(&adapter->bus_lock); +} +EXPORT_SYMBOL_GPL(i2c_lock_adapter); + +/** + * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment + * @adapter: Target I2C bus segment + */ +static int i2c_trylock_adapter(struct i2c_adapter *adapter) +{ + if (i2c_parent_is_i2c_adapter(adapter)) + return i2c_trylock_adapter(to_i2c_adapter(adapter->dev.parent)); + else + return rt_mutex_trylock(&adapter->bus_lock); +} + +/** + * i2c_unlock_adapter - Release exclusive access to an I2C bus segment + * @adapter: Target I2C bus segment + */ +void i2c_unlock_adapter(struct i2c_adapter *adapter) +{ + if (i2c_parent_is_i2c_adapter(adapter)) + i2c_unlock_adapter(to_i2c_adapter(adapter->dev.parent)); + else + rt_mutex_unlock(&adapter->bus_lock); +} +EXPORT_SYMBOL_GPL(i2c_unlock_adapter); + /** * i2c_new_device - instantiate an i2c device * @adap: the adapter managing the device @@ -410,8 +546,16 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) strlcpy(client->name, info->type, sizeof(client->name)); + /* Check for address validity */ + status = i2c_check_client_addr_validity(client); + if (status) { + dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n", + client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr); + goto out_err_silent; + } + /* Check for address business */ - status = i2c_check_addr(adap, client->addr); + status = i2c_check_addr_busy(adap, client->addr); if (status) goto out_err; @@ -436,6 +580,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) out_err: dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " "(%d)\n", client->name, client->addr, status); +out_err_silent: kfree(client); return NULL; } @@ -561,20 +706,14 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, return -EINVAL; } - if (info.addr < 0x03 || info.addr > 0x77) { - dev_err(dev, "%s: Invalid I2C address 0x%hx\n", "new_device", - info.addr); - return -EINVAL; - } - client = i2c_new_device(adap, &info); if (!client) - return -EEXIST; + return -EINVAL; /* Keep track of the added device */ - i2c_lock_adapter(adap); + mutex_lock(&adap->userspace_clients_lock); list_add_tail(&client->detected, &adap->userspace_clients); - i2c_unlock_adapter(adap); + mutex_unlock(&adap->userspace_clients_lock); dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", info.type, info.addr); @@ -613,7 +752,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, /* Make sure the device was added through sysfs */ res = -ENOENT; - i2c_lock_adapter(adap); + mutex_lock(&adap->userspace_clients_lock); list_for_each_entry_safe(client, next, &adap->userspace_clients, detected) { if (client->addr == addr) { @@ -626,7 +765,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, break; } } - i2c_unlock_adapter(adap); + mutex_unlock(&adap->userspace_clients_lock); if (res < 0) dev_err(dev, "%s: Can't find device in list\n", @@ -653,10 +792,11 @@ static const struct attribute_group *i2c_adapter_attr_groups[] = { NULL }; -static struct device_type i2c_adapter_type = { +struct device_type i2c_adapter_type = { .groups = i2c_adapter_attr_groups, .release = i2c_adapter_dev_release, }; +EXPORT_SYMBOL_GPL(i2c_adapter_type); #ifdef CONFIG_I2C_COMPAT static struct class_compat *i2c_adapter_compat_class; @@ -699,7 +839,7 @@ static int __process_new_adapter(struct device_driver *d, void *data) static int i2c_register_adapter(struct i2c_adapter *adap) { - int res = 0, dummy; + int res = 0; /* Can't register until after driver model init */ if (unlikely(WARN_ON(!i2c_bus_type.p))) { @@ -708,6 +848,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) } rt_mutex_init(&adap->bus_lock); + mutex_init(&adap->userspace_clients_lock); INIT_LIST_HEAD(&adap->userspace_clients); /* Set default timeout to 1 second if not already set */ @@ -735,10 +876,12 @@ static int i2c_register_adapter(struct i2c_adapter *adap) if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); + /* Register devices from the device tree */ + of_i2c_register_devices(adap); + /* Notify drivers */ mutex_lock(&core_lock); - dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, - __process_new_adapter); + bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); mutex_unlock(&core_lock); return 0; @@ -911,7 +1054,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) return res; /* Remove devices instantiated from sysfs */ - i2c_lock_adapter(adap); + mutex_lock(&adap->userspace_clients_lock); list_for_each_entry_safe(client, next, &adap->userspace_clients, detected) { dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, @@ -919,7 +1062,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) list_del(&client->detected); i2c_unregister_device(client); } - i2c_unlock_adapter(adap); + mutex_unlock(&adap->userspace_clients_lock); /* Detach any active clients. This can't fail, thus we do not checking the returned value. */ @@ -1024,21 +1167,6 @@ EXPORT_SYMBOL(i2c_del_driver); /* ------------------------------------------------------------------------- */ -static int __i2c_check_addr(struct device *dev, void *addrp) -{ - struct i2c_client *client = i2c_verify_client(dev); - int addr = *(int *)addrp; - - if (client && client->addr == addr) - return -EBUSY; - return 0; -} - -static int i2c_check_addr(struct i2c_adapter *adapter, int addr) -{ - return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr); -} - /** * i2c_use_client - increments the reference count of the i2c client structure * @client: the client being referenced @@ -1189,12 +1317,12 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) #endif if (in_atomic() || irqs_disabled()) { - ret = rt_mutex_trylock(&adap->bus_lock); + ret = i2c_trylock_adapter(adap); if (!ret) /* I2C activity is ongoing. */ return -EAGAIN; } else { - rt_mutex_lock(&adap->bus_lock); + i2c_lock_adapter(adap); } /* Retry automatically on arbitration loss */ @@ -1206,7 +1334,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (time_after(jiffies, orig_jiffies + adap->timeout)) break; } - rt_mutex_unlock(&adap->bus_lock); + i2c_unlock_adapter(adap); return ret; } else { @@ -1277,6 +1405,45 @@ EXPORT_SYMBOL(i2c_master_recv); * ---------------------------------------------------- */ +/* + * Legacy default probe function, mostly relevant for SMBus. The default + * probe method is a quick write, but it is known to corrupt the 24RF08 + * EEPROMs due to a state machine bug, and could also irreversibly + * write-protect some EEPROMs, so for address ranges 0x30-0x37 and 0x50-0x5f, + * we use a short byte read instead. Also, some bus drivers don't implement + * quick write, so we fallback to a byte read in that case too. + * On x86, there is another special case for FSC hardware monitoring chips, + * which want regular byte reads (address 0x73.) Fortunately, these are the + * only known chips using this I2C address on PC hardware. + * Returns 1 if probe succeeded, 0 if not. + */ +static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr) +{ + int err; + union i2c_smbus_data dummy; + +#ifdef CONFIG_X86 + if (addr == 0x73 && (adap->class & I2C_CLASS_HWMON) + && i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE_DATA)) + err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE_DATA, &dummy); + else +#endif + if (!((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50) + && i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) + err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0, + I2C_SMBUS_QUICK, NULL); + else if (i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) + err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE, &dummy); + else { + dev_warn(&adap->dev, "No suitable probing method supported\n"); + err = -EOPNOTSUPP; + } + + return err >= 0; +} + static int i2c_detect_address(struct i2c_client *temp_client, struct i2c_driver *driver) { @@ -1286,34 +1453,20 @@ static int i2c_detect_address(struct i2c_client *temp_client, int err; /* Make sure the address is valid */ - if (addr < 0x03 || addr > 0x77) { + err = i2c_check_addr_validity(addr); + if (err) { dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n", addr); - return -EINVAL; + return err; } /* Skip if already in use */ - if (i2c_check_addr(adapter, addr)) + if (i2c_check_addr_busy(adapter, addr)) return 0; /* Make sure there is something at this address */ - if (addr == 0x73 && (adapter->class & I2C_CLASS_HWMON)) { - /* Special probe for FSC hwmon chips */ - union i2c_smbus_data dummy; - - if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0, - I2C_SMBUS_BYTE_DATA, &dummy) < 0) - return 0; - } else { - if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0, - I2C_SMBUS_QUICK, NULL) < 0) - return 0; - - /* Prevent 24RF08 corruption */ - if ((addr & ~0x0f) == 0x50) - i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0, - I2C_SMBUS_QUICK, NULL); - } + if (!i2c_default_probe(adapter, addr)) + return 0; /* Finally call the custom detection function */ memset(&info, 0, sizeof(struct i2c_board_info)); @@ -1367,17 +1520,6 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) if (!(adapter->class & driver->class)) goto exit_free; - /* Stop here if we can't use SMBUS_QUICK */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) { - if (address_list[0] == I2C_CLIENT_END) - goto exit_free; - - dev_warn(&adapter->dev, "SMBus Quick command not supported, " - "can't probe for chips\n"); - err = -EOPNOTSUPP; - goto exit_free; - } - for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { dev_dbg(&adapter->dev, "found normal entry for adapter %d, " "addr 0x%02x\n", adap_id, address_list[i]); @@ -1392,57 +1534,42 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) return err; } +int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr) +{ + return i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, + I2C_SMBUS_QUICK, NULL) >= 0; +} +EXPORT_SYMBOL_GPL(i2c_probe_func_quick_read); + struct i2c_client * i2c_new_probed_device(struct i2c_adapter *adap, struct i2c_board_info *info, - unsigned short const *addr_list) + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *, unsigned short addr)) { int i; - /* Stop here if the bus doesn't support probing */ - if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) { - dev_err(&adap->dev, "Probing not supported\n"); - return NULL; - } + if (!probe) + probe = i2c_default_probe; for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { /* Check address validity */ - if (addr_list[i] < 0x03 || addr_list[i] > 0x77) { + if (i2c_check_addr_validity(addr_list[i]) < 0) { dev_warn(&adap->dev, "Invalid 7-bit address " "0x%02x\n", addr_list[i]); continue; } /* Check address availability */ - if (i2c_check_addr(adap, addr_list[i])) { + if (i2c_check_addr_busy(adap, addr_list[i])) { dev_dbg(&adap->dev, "Address 0x%02x already in " "use, not probing\n", addr_list[i]); continue; } - /* Test address responsiveness - The default probe method is a quick write, but it is known - to corrupt the 24RF08 EEPROMs due to a state machine bug, - and could also irreversibly write-protect some EEPROMs, so - for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte - read instead. Also, some bus drivers don't implement - quick write, so we fallback to a byte read it that case - too. */ - if ((addr_list[i] & ~0x07) == 0x30 - || (addr_list[i] & ~0x0f) == 0x50 - || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) { - union i2c_smbus_data data; - - if (i2c_smbus_xfer(adap, addr_list[i], 0, - I2C_SMBUS_READ, 0, - I2C_SMBUS_BYTE, &data) >= 0) - break; - } else { - if (i2c_smbus_xfer(adap, addr_list[i], 0, - I2C_SMBUS_WRITE, 0, - I2C_SMBUS_QUICK, NULL) >= 0) - break; - } + /* Test address responsiveness */ + if (probe(adap, addr_list[i])) + break; } if (addr_list[i] == I2C_CLIENT_END) { @@ -1953,7 +2080,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, flags &= I2C_M_TEN | I2C_CLIENT_PEC; if (adapter->algo->smbus_xfer) { - rt_mutex_lock(&adapter->bus_lock); + i2c_lock_adapter(adapter); /* Retry automatically on arbitration loss */ orig_jiffies = jiffies; @@ -1967,7 +2094,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, orig_jiffies + adapter->timeout)) break; } - rt_mutex_unlock(&adapter->bus_lock); + i2c_unlock_adapter(adapter); } else res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, command, protocol, data); |