diff options
Diffstat (limited to 'drivers/i2c/i2c-core.c')
| -rw-r--r-- | drivers/i2c/i2c-core.c | 253 | 
1 files changed, 211 insertions, 42 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e6d4935161e4..5f89f1e3c2f2 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -27,6 +27,7 @@     I2C slave support (c) 2014 by Wolfram Sang <[email protected]>   */ +#include <dt-bindings/i2c/i2c.h>  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/delay.h> @@ -47,6 +48,7 @@  #include <linux/rwsem.h>  #include <linux/pm_runtime.h>  #include <linux/pm_domain.h> +#include <linux/pm_wakeirq.h>  #include <linux/acpi.h>  #include <linux/jump_label.h>  #include <asm/uaccess.h> @@ -57,6 +59,9 @@  #define CREATE_TRACE_POINTS  #include <trace/events/i2c.h> +#define I2C_ADDR_OFFSET_TEN_BIT	0xa000 +#define I2C_ADDR_OFFSET_SLAVE	0x1000 +  /* core_lock protects i2c_adapter_idr, and guarantees     that device detection, deletion of detected devices, and attach_adapter     calls are serialized */ @@ -567,6 +572,9 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)  	if (bri->prepare_recovery)  		bri->prepare_recovery(adap); +	bri->set_scl(adap, val); +	ndelay(RECOVERY_NDELAY); +  	/*  	 * By this time SCL is high, as we need to give 9 falling-rising edges  	 */ @@ -597,7 +605,6 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)  int i2c_generic_scl_recovery(struct i2c_adapter *adap)  { -	adap->bus_recovery_info->set_scl(adap, 1);  	return i2c_generic_recovery(adap);  }  EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery); @@ -639,11 +646,13 @@ static int i2c_device_probe(struct device *dev)  	if (!client->irq) {  		int irq = -ENOENT; -		if (dev->of_node) -			irq = of_irq_get(dev->of_node, 0); -		else if (ACPI_COMPANION(dev)) +		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); +		} else if (ACPI_COMPANION(dev)) {  			irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0); - +		}  		if (irq == -EPROBE_DEFER)  			return irq;  		if (irq < 0) @@ -656,23 +665,49 @@ static int i2c_device_probe(struct device *dev)  	if (!driver->probe || !driver->id_table)  		return -ENODEV; -	if (!device_can_wakeup(&client->dev)) -		device_init_wakeup(&client->dev, -					client->flags & I2C_CLIENT_WAKE); +	if (client->flags & I2C_CLIENT_WAKE) { +		int wakeirq = -ENOENT; + +		if (dev->of_node) { +			wakeirq = of_irq_get_byname(dev->of_node, "wakeup"); +			if (wakeirq == -EPROBE_DEFER) +				return wakeirq; +		} + +		device_init_wakeup(&client->dev, true); + +		if (wakeirq > 0 && wakeirq != client->irq) +			status = dev_pm_set_dedicated_wake_irq(dev, wakeirq); +		else if (client->irq > 0) +			status = dev_pm_set_wake_irq(dev, wakeirq); +		else +			status = 0; + +		if (status) +			dev_warn(&client->dev, "failed to set up wakeup irq"); +	} +  	dev_dbg(dev, "probe\n");  	status = of_clk_set_defaults(dev->of_node, false);  	if (status < 0) -		return status; +		goto err_clear_wakeup_irq;  	status = dev_pm_domain_attach(&client->dev, true);  	if (status != -EPROBE_DEFER) {  		status = driver->probe(client, i2c_match_id(driver->id_table,  					client));  		if (status) -			dev_pm_domain_detach(&client->dev, true); +			goto err_detach_pm_domain;  	} +	return 0; + +err_detach_pm_domain: +	dev_pm_domain_detach(&client->dev, true); +err_clear_wakeup_irq: +	dev_pm_clear_wake_irq(&client->dev); +	device_init_wakeup(&client->dev, false);  	return status;  } @@ -692,6 +727,10 @@ static int i2c_device_remove(struct device *dev)  	}  	dev_pm_domain_detach(&client->dev, true); + +	dev_pm_clear_wake_irq(&client->dev); +	device_init_wakeup(&client->dev, false); +  	return status;  } @@ -776,17 +815,32 @@ struct i2c_client *i2c_verify_client(struct device *dev)  EXPORT_SYMBOL(i2c_verify_client); +/* Return a unique address which takes the flags of the client into account */ +static unsigned short i2c_encode_flags_to_addr(struct i2c_client *client) +{ +	unsigned short addr = client->addr; + +	/* For some client flags, add an arbitrary offset to avoid collisions */ +	if (client->flags & I2C_CLIENT_TEN) +		addr |= I2C_ADDR_OFFSET_TEN_BIT; + +	if (client->flags & I2C_CLIENT_SLAVE) +		addr |= I2C_ADDR_OFFSET_SLAVE; + +	return addr; +} +  /* This is a permissive address validity check, I2C address map constraints   * are purposely not enforced, except for the general call address. */ -static int i2c_check_client_addr_validity(const struct i2c_client *client) +static int i2c_check_addr_validity(unsigned addr, unsigned short flags)  { -	if (client->flags & I2C_CLIENT_TEN) { +	if (flags & I2C_CLIENT_TEN) {  		/* 10-bit address, all values are valid */ -		if (client->addr > 0x3ff) +		if (addr > 0x3ff)  			return -EINVAL;  	} else {  		/* 7-bit address, reject the general call address */ -		if (client->addr == 0x00 || client->addr > 0x7f) +		if (addr == 0x00 || addr > 0x7f)  			return -EINVAL;  	}  	return 0; @@ -796,7 +850,7 @@ static int i2c_check_client_addr_validity(const struct i2c_client *client)   * 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) +static int i2c_check_7bit_addr_validity_strict(unsigned short addr)  {  	/*  	 * Reserved addresses per I2C specification: @@ -818,7 +872,7 @@ 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) +	if (client && i2c_encode_flags_to_addr(client) == addr)  		return -EBUSY;  	return 0;  } @@ -921,10 +975,8 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,  		return;  	} -	/* For 10-bit clients, add an arbitrary offset to avoid collisions */  	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), -		     client->addr | ((client->flags & I2C_CLIENT_TEN) -				     ? 0xa000 : 0)); +		     i2c_encode_flags_to_addr(client));  }  /** @@ -966,8 +1018,7 @@ 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); +	status = i2c_check_addr_validity(client->addr, client->flags);  	if (status) {  		dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",  			client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr); @@ -975,7 +1026,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)  	}  	/* Check for address business */ -	status = i2c_check_addr_busy(adap, client->addr); +	status = i2c_check_addr_busy(adap, i2c_encode_flags_to_addr(client));  	if (status)  		goto out_err; @@ -1140,6 +1191,16 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,  		return -EINVAL;  	} +	if ((info.addr & I2C_ADDR_OFFSET_TEN_BIT) == I2C_ADDR_OFFSET_TEN_BIT) { +		info.addr &= ~I2C_ADDR_OFFSET_TEN_BIT; +		info.flags |= I2C_CLIENT_TEN; +	} + +	if (info.addr & I2C_ADDR_OFFSET_SLAVE) { +		info.addr &= ~I2C_ADDR_OFFSET_SLAVE; +		info.flags |= I2C_CLIENT_SLAVE; +	} +  	client = i2c_new_device(adap, &info);  	if (!client)  		return -EINVAL; @@ -1191,7 +1252,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,  			  i2c_adapter_depth(adap));  	list_for_each_entry_safe(client, next, &adap->userspace_clients,  				 detected) { -		if (client->addr == addr) { +		if (i2c_encode_flags_to_addr(client) == addr) {  			dev_info(dev, "%s: Deleting device %s at 0x%02hx\n",  				 "delete_device", client->name, client->addr); @@ -1271,7 +1332,8 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,  	struct i2c_client *result;  	struct i2c_board_info info = {};  	struct dev_archdata dev_ad = {}; -	const __be32 *addr; +	const __be32 *addr_be; +	u32 addr;  	int len;  	dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); @@ -1282,20 +1344,31 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,  		return ERR_PTR(-EINVAL);  	} -	addr = of_get_property(node, "reg", &len); -	if (!addr || (len < sizeof(*addr))) { +	addr_be = of_get_property(node, "reg", &len); +	if (!addr_be || (len < sizeof(*addr_be))) {  		dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",  			node->full_name);  		return ERR_PTR(-EINVAL);  	} -	info.addr = be32_to_cpup(addr); -	if (info.addr > (1 << 10) - 1) { +	addr = be32_to_cpup(addr_be); +	if (addr & I2C_TEN_BIT_ADDRESS) { +		addr &= ~I2C_TEN_BIT_ADDRESS; +		info.flags |= I2C_CLIENT_TEN; +	} + +	if (addr & I2C_OWN_SLAVE_ADDRESS) { +		addr &= ~I2C_OWN_SLAVE_ADDRESS; +		info.flags |= I2C_CLIENT_SLAVE; +	} + +	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);  		return ERR_PTR(-EINVAL);  	} +	info.addr = addr;  	info.of_node = of_node_get(node);  	info.archdata = &dev_ad; @@ -1338,13 +1411,17 @@ static int of_dev_node_match(struct device *dev, void *data)  struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)  {  	struct device *dev; +	struct i2c_client *client; -	dev = bus_find_device(&i2c_bus_type, NULL, node, -					 of_dev_node_match); +	dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match);  	if (!dev)  		return NULL; -	return i2c_verify_client(dev); +	client = i2c_verify_client(dev); +	if (!client) +		put_device(dev); + +	return client;  }  EXPORT_SYMBOL(of_find_i2c_device_by_node); @@ -1352,15 +1429,37 @@ EXPORT_SYMBOL(of_find_i2c_device_by_node);  struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)  {  	struct device *dev; +	struct i2c_adapter *adapter; -	dev = bus_find_device(&i2c_bus_type, NULL, node, -					 of_dev_node_match); +	dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match);  	if (!dev)  		return NULL; -	return i2c_verify_adapter(dev); +	adapter = i2c_verify_adapter(dev); +	if (!adapter) +		put_device(dev); + +	return adapter;  }  EXPORT_SYMBOL(of_find_i2c_adapter_by_node); + +/* must call i2c_put_adapter() when done with returned i2c_adapter device */ +struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node) +{ +	struct i2c_adapter *adapter; + +	adapter = of_find_i2c_adapter_by_node(node); +	if (!adapter) +		return NULL; + +	if (!try_module_get(adapter->owner)) { +		put_device(&adapter->dev); +		adapter = NULL; +	} + +	return adapter; +} +EXPORT_SYMBOL(of_get_i2c_adapter_by_node);  #else  static void of_i2c_register_devices(struct i2c_adapter *adap) { }  #endif /* CONFIG_OF */ @@ -2252,14 +2351,14 @@ static int i2c_detect_address(struct i2c_client *temp_client,  	int err;  	/* Make sure the address is valid */ -	err = i2c_check_addr_validity(addr); +	err = i2c_check_7bit_addr_validity_strict(addr);  	if (err) {  		dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",  			 addr);  		return err;  	} -	/* Skip if already in use */ +	/* Skip if already in use (7 bit, no need to encode flags) */  	if (i2c_check_addr_busy(adapter, addr))  		return 0; @@ -2369,13 +2468,13 @@ i2c_new_probed_device(struct i2c_adapter *adap,  	for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {  		/* Check address validity */ -		if (i2c_check_addr_validity(addr_list[i]) < 0) { +		if (i2c_check_7bit_addr_validity_strict(addr_list[i]) < 0) {  			dev_warn(&adap->dev, "Invalid 7-bit address "  				 "0x%02x\n", addr_list[i]);  			continue;  		} -		/* Check address availability */ +		/* Check address availability (7 bit, no need to encode flags) */  		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]); @@ -2403,9 +2502,15 @@ struct i2c_adapter *i2c_get_adapter(int nr)  	mutex_lock(&core_lock);  	adapter = idr_find(&i2c_adapter_idr, nr); -	if (adapter && !try_module_get(adapter->owner)) +	if (!adapter) +		goto exit; + +	if (try_module_get(adapter->owner)) +		get_device(&adapter->dev); +	else  		adapter = NULL; + exit:  	mutex_unlock(&core_lock);  	return adapter;  } @@ -2413,8 +2518,11 @@ EXPORT_SYMBOL(i2c_get_adapter);  void i2c_put_adapter(struct i2c_adapter *adap)  { -	if (adap) -		module_put(adap->owner); +	if (!adap) +		return; + +	put_device(&adap->dev); +	module_put(adap->owner);  }  EXPORT_SYMBOL(i2c_put_adapter); @@ -2932,6 +3040,63 @@ trace:  }  EXPORT_SYMBOL(i2c_smbus_xfer); +/** + * i2c_smbus_read_i2c_block_data_or_emulated - read block or emulate + * @client: Handle to slave device + * @command: Byte interpreted by slave + * @length: Size of data block; SMBus allows at most I2C_SMBUS_BLOCK_MAX bytes + * @values: Byte array into which data will be read; big enough to hold + *	the data returned by the slave.  SMBus allows at most + *	I2C_SMBUS_BLOCK_MAX bytes. + * + * This executes the SMBus "block read" protocol if supported by the adapter. + * If block read is not supported, it emulates it using either word or byte + * read protocols depending on availability. + * + * The addresses of the I2C slave device that are accessed with this function + * must be mapped to a linear region, so that a block read will have the same + * effect as a byte read. Before using this function you must double-check + * if the I2C slave does support exchanging a block transfer with a byte + * transfer. + */ +s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client, +					      u8 command, u8 length, u8 *values) +{ +	u8 i = 0; +	int status; + +	if (length > I2C_SMBUS_BLOCK_MAX) +		length = I2C_SMBUS_BLOCK_MAX; + +	if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) +		return i2c_smbus_read_i2c_block_data(client, command, length, values); + +	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) +		return -EOPNOTSUPP; + +	if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) { +		while ((i + 2) <= length) { +			status = i2c_smbus_read_word_data(client, command + i); +			if (status < 0) +				return status; +			values[i] = status & 0xff; +			values[i + 1] = status >> 8; +			i += 2; +		} +	} + +	while (i < length) { +		status = i2c_smbus_read_byte_data(client, command + i); +		if (status < 0) +			return status; +		values[i] = status; +		i++; +	} + +	return i; +} +EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated); +  #if IS_ENABLED(CONFIG_I2C_SLAVE)  int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)  { @@ -2942,9 +3107,13 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)  		return -EINVAL;  	} +	if (!(client->flags & I2C_CLIENT_SLAVE)) +		dev_warn(&client->dev, "%s: client slave flag not set. You might see address collisions\n", +			 __func__); +  	if (!(client->flags & I2C_CLIENT_TEN)) {  		/* Enforce stricter address checking */ -		ret = i2c_check_addr_validity(client->addr); +		ret = i2c_check_7bit_addr_validity_strict(client->addr);  		if (ret) {  			dev_err(&client->dev, "%s: invalid address\n", __func__);  			return ret;  |