diff options
Diffstat (limited to 'drivers/i2c/i2c-core-base.c')
-rw-r--r-- | drivers/i2c/i2c-core-base.c | 158 |
1 files changed, 63 insertions, 95 deletions
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index f26ed495d384..cefad0881942 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -186,10 +186,11 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap) * If we can set SDA, we will always create a STOP to ensure additional * pulses will do no harm. This is achieved by letting SDA follow SCL * half a cycle later. Check the 'incomplete_write_byte' fault injector - * for details. + * for details. Note that we must honour tsu:sto, 4us, but lets use 5us + * here for simplicity. */ bri->set_scl(adap, scl); - ndelay(RECOVERY_NDELAY / 2); + ndelay(RECOVERY_NDELAY); if (bri->set_sda) bri->set_sda(adap, scl); ndelay(RECOVERY_NDELAY / 2); @@ -211,7 +212,13 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap) scl = !scl; bri->set_scl(adap, scl); /* Creating STOP again, see above */ - ndelay(RECOVERY_NDELAY / 2); + if (scl) { + /* Honour minimum tsu:sto */ + ndelay(RECOVERY_NDELAY); + } else { + /* Honour minimum tf and thd:dat */ + ndelay(RECOVERY_NDELAY / 2); + } if (bri->set_sda) bri->set_sda(adap, scl); ndelay(RECOVERY_NDELAY / 2); @@ -350,13 +357,11 @@ static int i2c_device_probe(struct device *dev) return -ENODEV; if (client->flags & I2C_CLIENT_WAKE) { - int wakeirq = -ENOENT; + int wakeirq; - if (dev->of_node) { - wakeirq = of_irq_get_byname(dev->of_node, "wakeup"); - if (wakeirq == -EPROBE_DEFER) - return wakeirq; - } + wakeirq = of_irq_get_byname(dev->of_node, "wakeup"); + if (wakeirq == -EPROBE_DEFER) + return wakeirq; device_init_wakeup(&client->dev, true); @@ -451,15 +456,15 @@ static void i2c_client_dev_release(struct device *dev) } static ssize_t -show_name(struct device *dev, struct device_attribute *attr, char *buf) +name_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", dev->type == &i2c_client_type ? to_i2c_client(dev)->name : to_i2c_adapter(dev)->name); } -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); +static DEVICE_ATTR_RO(name); static ssize_t -show_modalias(struct device *dev, struct device_attribute *attr, char *buf) +modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); int len; @@ -474,7 +479,7 @@ show_modalias(struct device *dev, struct device_attribute *attr, char *buf) return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); } -static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); +static DEVICE_ATTR_RO(modalias); static struct attribute *i2c_dev_attrs[] = { &dev_attr_name.attr, @@ -826,13 +831,13 @@ EXPORT_SYMBOL_GPL(i2c_new_device); /** - * i2c_unregister_device - reverse effect of i2c_new_device() - * @client: value returned from i2c_new_device() + * i2c_unregister_device - reverse effect of i2c_new_*_device() + * @client: value returned from i2c_new_*_device() * Context: can sleep */ void i2c_unregister_device(struct i2c_client *client) { - if (!client) + if (IS_ERR_OR_NULL(client)) return; if (client->dev.of_node) { @@ -898,29 +903,6 @@ struct i2c_client *i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address } EXPORT_SYMBOL_GPL(i2c_new_dummy_device); -/** - * i2c_new_dummy - return a new i2c device bound to a dummy driver - * @adapter: the adapter managing the device - * @address: seven bit address to be used - * Context: can sleep - * - * This deprecated function has the same functionality as @i2c_new_dummy_device, - * it just returns NULL instead of an ERR_PTR in case of an error for - * compatibility with current I2C API. It will be removed once all users are - * converted. - * - * This returns the new i2c client, which should be saved for later use with - * i2c_unregister_device(); or NULL to indicate an error. - */ -struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address) -{ - struct i2c_client *ret; - - ret = i2c_new_dummy_device(adapter, address); - return IS_ERR(ret) ? NULL : ret; -} -EXPORT_SYMBOL_GPL(i2c_new_dummy); - struct i2c_dummy_devres { struct i2c_client *client; }; @@ -966,7 +948,7 @@ struct i2c_client *devm_i2c_new_dummy_device(struct device *dev, EXPORT_SYMBOL_GPL(devm_i2c_new_dummy_device); /** - * i2c_new_secondary_device - Helper to get the instantiated secondary address + * i2c_new_ancillary_device - Helper to get the instantiated secondary address * and create the associated device * @client: Handle to the primary client * @name: Handle to specify which secondary address to get @@ -985,9 +967,9 @@ EXPORT_SYMBOL_GPL(devm_i2c_new_dummy_device); * cell whose "reg-names" value matches the slave name. * * This returns the new i2c client, which should be saved for later use with - * i2c_unregister_device(); or NULL to indicate an error. + * i2c_unregister_device(); or an ERR_PTR to describe the error. */ -struct i2c_client *i2c_new_secondary_device(struct i2c_client *client, +struct i2c_client *i2c_new_ancillary_device(struct i2c_client *client, const char *name, u16 default_addr) { @@ -1002,9 +984,9 @@ struct i2c_client *i2c_new_secondary_device(struct i2c_client *client, } dev_dbg(&client->adapter->dev, "Address for %s : 0x%x\n", name, addr); - return i2c_new_dummy(client->adapter, addr); + return i2c_new_dummy_device(client->adapter, addr); } -EXPORT_SYMBOL_GPL(i2c_new_secondary_device); +EXPORT_SYMBOL_GPL(i2c_new_ancillary_device); /* ------------------------------------------------------------------------- */ @@ -1041,8 +1023,8 @@ EXPORT_SYMBOL_GPL(i2c_adapter_depth); * the user to provide incorrect parameters. */ static ssize_t -i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +new_device_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_adapter *adap = to_i2c_adapter(dev); struct i2c_board_info info; @@ -1097,7 +1079,7 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device); +static DEVICE_ATTR_WO(new_device); /* * And of course let the users delete the devices they instantiated, if @@ -1109,8 +1091,8 @@ static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device); * the user to delete the wrong device. */ static ssize_t -i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +delete_device_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_adapter *adap = to_i2c_adapter(dev); struct i2c_client *client, *next; @@ -1153,7 +1135,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, return res; } static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL, - i2c_sysfs_delete_device); + delete_device_store); static struct attribute *i2c_adapter_attrs[] = { &dev_attr_name.attr, @@ -1196,9 +1178,8 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter) down_read(&__i2c_board_lock); list_for_each_entry(devinfo, &__i2c_board_list, list) { - if (devinfo->busnum == adapter->nr - && !i2c_new_device(adapter, - &devinfo->board_info)) + if (devinfo->busnum == adapter->nr && + IS_ERR(i2c_new_client_device(adapter, &devinfo->board_info))) dev_err(&adapter->dev, "Can't create device at 0x%02x\n", devinfo->board_info.addr); @@ -1658,6 +1639,12 @@ void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_de t->sda_fall_ns = t->scl_fall_ns; device_property_read_u32(dev, "i2c-sda-hold-time-ns", &t->sda_hold_ns); + + device_property_read_u32(dev, "i2c-digital-filter-width-ns", + &t->digital_filter_width_ns); + + device_property_read_u32(dev, "i2c-analog-filter-cutoff-frequency", + &t->analog_filter_cutoff_freq_hz); } EXPORT_SYMBOL_GPL(i2c_parse_fw_timings); @@ -1739,38 +1726,6 @@ EXPORT_SYMBOL(i2c_del_driver); /* ------------------------------------------------------------------------- */ -/** - * i2c_use_client - increments the reference count of the i2c client structure - * @client: the client being referenced - * - * Each live reference to a client should be refcounted. The driver model does - * that automatically as part of driver binding, so that most drivers don't - * need to do this explicitly: they hold a reference until they're unbound - * from the device. - * - * A pointer to the client with the incremented reference counter is returned. - */ -struct i2c_client *i2c_use_client(struct i2c_client *client) -{ - if (client && get_device(&client->dev)) - return client; - return NULL; -} -EXPORT_SYMBOL(i2c_use_client); - -/** - * i2c_release_client - release a use of the i2c client structure - * @client: the client being no longer referenced - * - * Must be called when a user of a client is finished with it. - */ -void i2c_release_client(struct i2c_client *client) -{ - if (client) - put_device(&client->dev); -} -EXPORT_SYMBOL(i2c_release_client); - struct i2c_cmd_arg { unsigned cmd; void *arg; @@ -2206,13 +2161,13 @@ static int i2c_detect_address(struct i2c_client *temp_client, dev_warn(&adapter->dev, "This adapter will soon drop class based instantiation of devices. " "Please make sure client 0x%02x gets instantiated by other means. " - "Check 'Documentation/i2c/instantiating-devices' for details.\n", + "Check 'Documentation/i2c/instantiating-devices.rst' for details.\n", info.addr); dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n", info.type, info.addr); - client = i2c_new_device(adapter, &info); - if (client) + client = i2c_new_client_device(adapter, &info); + if (!IS_ERR(client)) list_add_tail(&client->detected, &driver->clients); else dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n", @@ -2236,7 +2191,7 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) if (adapter->class == I2C_CLASS_DEPRECATED) { dev_dbg(&adapter->dev, "This adapter dropped support for I2C classes and won't auto-detect %s devices anymore. " - "If you need it, check 'Documentation/i2c/instantiating-devices' for alternatives.\n", + "If you need it, check 'Documentation/i2c/instantiating-devices.rst' for alternatives.\n", driver->driver.name); return 0; } @@ -2273,10 +2228,10 @@ int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr) 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, - int (*probe)(struct i2c_adapter *adap, unsigned short addr)) +i2c_new_scanned_device(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *adap, unsigned short addr)) { int i; @@ -2306,11 +2261,24 @@ i2c_new_probed_device(struct i2c_adapter *adap, if (addr_list[i] == I2C_CLIENT_END) { dev_dbg(&adap->dev, "Probing failed, no device found\n"); - return NULL; + return ERR_PTR(-ENODEV); } info->addr = addr_list[i]; - return i2c_new_device(adap, info); + return i2c_new_client_device(adap, info); +} +EXPORT_SYMBOL_GPL(i2c_new_scanned_device); + +struct i2c_client * +i2c_new_probed_device(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *adap, unsigned short addr)) +{ + struct i2c_client *client; + + client = i2c_new_scanned_device(adap, info, addr_list, probe); + return IS_ERR(client) ? NULL : client; } EXPORT_SYMBOL_GPL(i2c_new_probed_device); |